如果喜歡本文章,記得收藏哦!
關(guān)注我,一起學(xué)Java。
一、基于ChatGPT API的PC端軟件開發(fā)過程遇到的問題的分析
最近這個(gè)OpenAI公司推出的GPT-4.0模型真是太火了。當(dāng)然由于OpenAI目前還沒有正式全面對外開放GPT-4.0 API,所以本次使用的是GPT-3.5 API。
首先來看一下效果圖吧!
本客戶端使用的是 JavaFX 開發(fā)的。JavaFX 相比于 Swing 來說,JavaFX 支持 CSS 樣式,如果使用 Java 來開發(fā) GUI 軟件的話,還是推薦使用 JavaFX 的。JavaFX 是 2008 年由 Oracle 公司推出的項(xiàng)目。需要說明的是在高版本的 JDK 中不含有 JavaFX 相關(guān)的 API,所以你需要自己安裝 JavaFX。因?yàn)槲议_發(fā)使用的是 JDK 8 所以無需自己另外安裝 JavaFX,直接就可以調(diào)用 JavaFX API。
上面的圖中我們可以看到使用 JavaFX 編寫的 UI 界面不是太好看,沒辦法 Java 是我的主力編程語言,所以只能用 Java 來編寫 UI 界面了。
主要有四個(gè)功能,分別是:發(fā)送,保存,查看,刪除。其中發(fā)送是最核心的功能。在發(fā)送時(shí)會間接調(diào)用 GPT-3.5 API,這里為什么說是間接調(diào)用而不是直接調(diào)用呢,想必大家都知道,這個(gè) OpenAI 公司是不對我們中國地區(qū)開放的,雖然我們可以直接訪問OpenAI 的官方網(wǎng)站,但是不能訪問 OpenAI 的產(chǎn)品ChatGPT。所以這里我們必須要自己使用一個(gè)國外的服務(wù)器作為中轉(zhuǎn)服務(wù)器。很容易理解為啥使用中轉(zhuǎn)服務(wù)器就可以訪問GPT API,比如你是A,你可以訪問B,但是你無法訪問C,然而B是可以訪問C的,那么你就可以告訴B,讓B把信息傳遞給C。
這里我只講開發(fā)客戶端軟件遇到的問題,不會講解如何編寫接口。
二、遇到的第一個(gè)問題,用戶點(diǎn)擊發(fā)送按鈕后,線程阻塞
這個(gè)問題主要是因?yàn)橛脩酎c(diǎn)擊了發(fā)送按鈕后會調(diào)用 Hutool 工具類中的 HttpRequest.post() 方法將數(shù)據(jù)發(fā)送到自己定義的接口上。代碼如下:
sendButton.setOnAction(e -> sendMessage());
private void sendMessage() {
// 獲取用戶輸入的消息并將其添加到聊天區(qū)域
String prompt = inputArea.getText();
// 獲取當(dāng)前時(shí)間
String nowTime = getNowTime();
chatArea.appendText(nowTime + "\n");
chatArea.appendText("我說:" + prompt + "\n\n");
// 清空輸入框
inputArea.setText("");
// 存儲上下文語境
messages.add(new Message("user", prompt));
// 獲取 ChatGPT 的回復(fù)
String reply = httpRequest(messages);
// 機(jī)器人回復(fù)時(shí)間
String replyTime = getNowTime();
chatArea.appendText(replyTime + "\n");
// 把內(nèi)容顯示到 UI 界面上
chatArea.appendText("機(jī)器人說:" + reply + "\n\n");
messages.add(new Message("assistant", reply));
}
在上面的代碼中,運(yùn)行的時(shí)候給用戶的感覺是不好的,因?yàn)樵谡{(diào)用 httpRequest(messages) 時(shí)會造成線程阻塞。因?yàn)樵诋?dāng)前線程在進(jìn)行網(wǎng)絡(luò)請求時(shí)是非常耗時(shí)的操作,所以整個(gè) main 線程會阻塞,導(dǎo)致應(yīng)用卡頓,如果 ChatGPT 一直沒有響應(yīng)結(jié)果,那么會一直卡在那里。
或許你們想到的是創(chuàng)建一個(gè)新的線程來發(fā)送 http 請求就解決了,其實(shí)不是的,問題的根源在我們點(diǎn)擊“發(fā)送”按鈕,我們應(yīng)該在點(diǎn)擊發(fā)送按鈕的時(shí)候創(chuàng)建新的線程,當(dāng)然這里我在發(fā)送 http 的時(shí)候也是創(chuàng)建了新的線程。代碼如下:
sendButton.setOnAction(e -> {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
// 執(zhí)行耗時(shí)操作,例如發(fā)送網(wǎng)絡(luò)請求或執(zhí)行計(jì)算密集型任務(wù)
sendMessage();
// 返回null
return null;
}
};
// 在后臺線程上執(zhí)行Task
new Thread(task).start();
// 將操作提交到JavaFX應(yīng)用程序線程隊(duì)列中
Platform.runLater(() -> {
// 在此更新UI或執(zhí)行其他需要在JavaFX應(yīng)用程序線程上執(zhí)行的操作
});
});
private void sendMessage() {
// 獲取用戶輸入的消息并將其添加到聊天區(qū)域
String prompt = inputArea.getText();
// 獲取當(dāng)前時(shí)間
String nowTime = getNowTime();
chatArea.appendText(nowTime + "\n");
chatArea.appendText("我說:" + prompt + "\n\n");
// 清空輸入框
inputArea.setText("");
// 存儲上下文語境
messages.add(new Message("user", prompt));
// 獲取 ChatGPT 的回復(fù)
// String reply = httpRequest(messages);
// 創(chuàng)建新的線程去發(fā)送 ChatGPT 請求
FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
return httpRequest(messages);
}
});
new Thread(task).start();
try {
String reply = task.get();
// 機(jī)器人回復(fù)時(shí)間
String replyTime = getNowTime();
chatArea.appendText(replyTime + "\n");
// 把內(nèi)容顯示到 UI 界面上
chatArea.appendText("機(jī)器人說:" + reply + "\n\n");
messages.add(new Message("assistant", reply));
} catch (Exception e) {
e.printStackTrace();
}
}
注意:如果想要更新 UI 界面的內(nèi)容,那么可以使用Platform.runLater()
。
三、第二個(gè)問題是ChatGPT無法進(jìn)行連續(xù)對話,也就是沒有上下文語境
這個(gè)問題折騰了好久。官方開發(fā)文檔好像也沒有特地說明這一點(diǎn)。我是研究了 GitHub 的代碼,并且網(wǎng)上搜索了別人的想法,然后知道必須要把聊天記錄再次發(fā)送給 ChatGPT API。但是這樣就會消耗更多的資金。因?yàn)?OpenAI 并非真的是 Open。
我們每次把聊天記錄發(fā)送給 ChatGPT 就行。
這里我們使用一個(gè)集合存放聊天記錄,每次把聊天記錄追加到集合里面即可。然后把 List 集合發(fā)送到 ChatGPT API。
// 存放上下文語境
private List<Message> messages = new ArrayList<>();
// 存儲上下文語境
messages.add(new Message("system", "你是一個(gè)助手"));
messages.add(new Message("user", prompt));
messages.add(new Message("assistant", reply));
其中 Message 類代碼如下:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Message {
private String role;
private String content;
}
ChatGPT 開發(fā)文檔中說明了 role 有三種值,一個(gè)是 system,表示讓 ChatGPT 充當(dāng)什么角色,第二種取值是 user,表示用戶,第三種是 assistant,表示 ChatGPT。而角色對應(yīng)的內(nèi)容存儲到 content 變量中。這類似于 map 集合,也就是 role 是 key,content 是 value。文章來源:http://www.zghlxwxcb.cn/news/detail-401930.html
有更多問題歡迎訪問博客。文章來源地址http://www.zghlxwxcb.cn/news/detail-401930.html
到了這里,關(guān)于基于ChatGPT API的PC端軟件開發(fā)過程遇到的問題的分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!