手把手教你用ChatGPT建立人工智能聊天室!

时间:2023-02-22 15:24:51

摘要

在本教程中,我将建立一个聊天室网络应用,允许用户输入他们的信息并与ChatGPT进行对话。

手把手教你用ChatGPT建立人工智能聊天室!

开篇

最近,ChatGPT已经变得非常流行。人们要求ChatGPT帮助他们写论文、做作业,甚至要求他们如何赚钱。有了类似的想法,我认为通过向ChatGPT咨询,建立一个聊天室应用程序是很有趣的。

从简单的东西开始,我计划建立一个聊天室网络应用,允许用户输入他们的信息并与ChatGPT进行对话。由此产生的应用程序将看起来像这样。

手把手教你用ChatGPT建立人工智能聊天室!

我将首先弄清楚如何整合ChatGPT,因为这对我来说是新事物。然后,我将建立用户界面,实现逻辑和动作,完成整个应用程序。

不知道如何调用ChatGPT?

我是ChatGPT的新手,不知道如何调用ChatGPT,所以我的脑海中突然出现了一个想法。为什么不直接问ChatGPT呢?

所以我提出了我的第一个问题。

你能给我一个java的代码例子,向ChatGPT发送一个HTTP请求来发送一个消息吗?

然后ChatGPT给我回复了一个连接
​https://api.openai.com/v1/engines/davinci-codex/completions​​ 的Java类例子,并提醒我用我自己的API密钥替换。


然后我问:

我在哪里可以得到API密钥?

ChatGPT给我提供了相关信息,我在这里总结一下:

  1. 去OpenAI的网站。
  2. 注册一个账户,或者如果你已经有一个账户,就登录。
  3. 一旦你登录了,在控制台中导航到API密钥部分。
  4. 点击 "创建密钥 "按钮。
  5. 给你的API密钥起个名字,并指定你想使用它的项目。
  6. 点击 "创建 "来生成API密钥。
  7. 把API密钥保存在安全的地方,因为它只会显示一次。

看起来很有希望。但当我实际运行Java代码的例子时,API返回代码429,这不是我所期望的。在检查了文档后,似乎URL是错误的。

所以我重新表述了我的问题。

如何在Java中调用OpenAI GPT-3模型?

它用另一个代码回答了我,这个代码连接到了这里。

点击给定的链接后,我发现这个URL已经失效了。所以我善意地告诉ChatGPT。

打开AI文档
​https://beta.openai.com/docs/api-reference/engines,提到Engines端点已被废弃。​

ChatGPT说:"你是正确的,"并给了我另一个带有正确URL的代码。经验之谈! 不要总是相信ChatGPT的回答。

这次运行代码,我终于得到了预期的JSON响应。

由于我懒得检查JSON字段以获得实际的文本回复,我又问了一个问题。

如何在Java中从OpenAI API响应中提取 "文本"?

而我又一次从ChatGPT中得到了一些有用的东西。

在ChatGPT的帮助下,通过将Java类重构为几个方法,我完成了ChatService,它调用OpenAI API来接收聊天完成建议。基本思路是创建一个HttpURLConnection实例,向OpenAI API端点(
​https://api.openai.com/v1/completions)发送一个POST请求,请求体包括聊天提示和其他相关参数,并接收JSON格式的API响应。我在这里包括了技术细节。​

Java 代码如下

public class ChatService {

static final String API_KEY = loadApiKey();
private HttpURLConnection con;
private URL url;

public ChatService() {
try {
url = new URL("<https://api.openai.com/v1/completions>");
}catch (MalformedURLException e){
throw new IllegalStateException(e);
}
}

public String prompt(String message) {
try {
sendRequest(message);
return readResponse().trim().replace("\\n\\n", "\\n");
} catch (IOException e) {
e.printStackTrace();
return e.toString();
}
}

private void sendRequest(String prompt) throws IOException {
initHttpURLConnection();
String requestBody = "{\\"model\\": \\"text-davinci-003\\", \\"prompt\\": \\"" + prompt + "\\", \\"temperature\\": 0.5, \\"max_tokens\\": 2048}";
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(this.con.getOutputStream());
wr.writeBytes(requestBody);
wr.flush();
wr.close();
}

prompt()向API发送一个聊天提示,并接收一个完成建议。

sendRequest()设置了HttpURLConnection,并将JSON请求体发送给API。

private String readResponse() throws IOException {
int responseCode = this.con.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(this.con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(response.toString());
JsonObject jsonObject = jsonElement.getAsJsonObject();
JsonArray jsonArray = jsonObject.getAsJsonArray("choices");
JsonObject firstChoice = jsonArray.get(0).getAsJsonObject();

in.close();
con.disconnect();
return firstChoice.get("text").getAsString();
}

readResponse()从API读取JSON响应,并从JSON对象中检索完成建议。

关于OpenAI的API和完成端点的更多信息可以在OpenAI官方API文档中找到。

在我通过询问GPT,搞清楚了最大的未知数--ChatGPT的整合之后,我已经准备好将其引入我的网络应用。

用ZK设计一个聊天用户界面

在ChatService准备好后,我现在需要一个用户界面来让最终用户输入他们的信息。由于我已经和ZK框架合作了很长时间,我决定使用ZK和zul来构建用户界面。

用ZK组件构建用户界面

如果你没有听说过ZK--它是一个UI框架,允许你在Java中构建Web应用程序。ZK提供了一种ZUL语言,它为构建用户界面带来了大量的组件,从标签、按钮和文本框等基本元素,到网格、树和图表等高级组件。除了这些组件之外,ZUL还提供了一套属性,可以用来定制组件的行为和外观。

我将要建立的聊天室应用程序看起来是这样的。

手把手教你用ChatGPT建立人工智能聊天室!

这个用户界面可以用下面的zul来完成

<zk xmlns:h="native">
<style src="style.css"></style>
<window vflex="1" sclass="container">
<h:h1 style="text-align: center;">Chat with AI</h:h1>
<checkbox label="fast response"></checkbox>
<hlayout vflex="1">
<div hflex="7" vflex="1">
<div vflex="1" sclass="messageBox" style="overflow-y: auto">
</div>
<hlayout>
<textbox focus="true" hflex="1" placeholder="type your messages here"></textbox>
<button iconSclass="z-icon-send" width="100px"></button>
</hlayout>
</div>
</hlayout>
</div>
</zk>

hflex and vflex

在上面的ZUL代码中,我使用"<hlayout>"来定义我的聊天室的水平布局。<hlayout>有2个属性,hflex和vflex,它们决定了组件的相对大小。"hflex"的值决定了高度而"vflex"的值决定了宽度。在这个例子中,我用hflex="1 "来指定第一个"<div>"应该占用一个单位的水平空间,用hflex="7 "来指定第二个"<div>"应该占用七个单位的水平空间。"这可以使聊天室的布局对大多数屏幕宽度有响应,因为它没有固定的宽度。

textbox

textbox "用于创建聊天室中的文本输入区域。"我使用id属性给它一个唯一的标识符,它可以用来在我的composer类中引用文本框(在后面的段落中解释)。"焦点 "属性被设置为 "true",以强制文本框在页面加载时接受焦点。占位符属性用于向终端用户提供关于文本框用途的提示。

混合HTML标签

在一个ZUL文件中,HTML标签可以在ZUL命名空间内使用,指定为 "xmlns:h"="native"。然后,标签"<h:h1>表示一个HTML标题标签。有了这个命名空间,你可以在他们的ZUL页面中利用HTML标签,如标题、链接和图片,为他们的网络应用添加结构和风格。这为你提供了包括由网页设计师制作的HTML片段的能力,并在zul中建立你自己的自定义部分。

构建用户界面的各种方法

除了编写zul之外,你还可以通过另外2种方式在ZK中建立你的UI。

1.以Swing风格在Java中建立UI

2.用ZUL代码片段调用Java方法。我将在控制器部分做进一步解释。

用CSS打造一个独特的用户体验

在上一节中,我做了用户界面的布局。现在,为了使它更漂亮,我用对比强烈的颜色和不同的背景来区分我的信息和AI的回复。这不仅增强了应用程序的视觉效果,而且也增加了对话的整体可读性。我还为消息框添加了适当的边距和填充物,以创造一个视觉上有吸引力的、有条理的布局。这些都可以通过使用CSS来实现。

手把手教你用ChatGPT建立人工智能聊天室!

在这一节中,我将谈一谈用CSS为ZUL页面设计样式的基本知识,包括<style>标签的使用、sclass和style属性,以及iconSclass属性。

<style>"允许你为ZUL页面定义CSS样式。你可以用src属性在你的ZUL中直接包含一个CSS文件,如上面的代码片段。"这个文件中定义的样式可以使用sclass属性应用到你的ZUL中的组件上。

sclass 属性用于将CSS类应用于组件。在上面的zul中,容器类被应用到<div>组件上,并使用sclass="container "属性。通过使用CSS类,你可以在你的ZUL中为多个组件应用一致的样式。

style 属性允许你将内联样式直接应用于一个组件。在上面的ZUL中,messageBox类被应用到了带有sclass=messageBox属性的div组件中。此外,overflow-y: auto 样式被添加到样式属性中,以指定<div>的内容在溢出其高度时应可垂直滚动。

iconSclass 属性用于在一个按钮上显示图标。"在应用程序中,一个发送图标被显示在<button>上,图标Sclass="z-icon-send "属性。"这是用ZK捆绑的Font Awesome图标完成的,它提供了大量可扩展的矢量图标集合,可以用CSS定制。ZK已经默认包含了它,你不需要手动下载和包含它。

用ZK控制器实现你的应用逻辑

现在我已经准备好了我的用户界面,并以我喜欢的方式进行了风格设计。我的下一步是实现我的应用逻辑。这个用例中的应用逻辑非常简单。

当点击发送按钮(或按下回车键)时,在消息区显示用户输入的消息和ChatGPT的回复。

我目前使用的模式是ZK MVC。我应该在一个ZK控制器的事件监听器中实现我的应用逻辑。控制器是一个Java类,它通过操纵ZK组件来实现应用逻辑,它可以用来处理事件,访问数据,以及操纵用户界面。ZUL中的相关属性是apply属性,它被用来将ZK控制器类与ZUL组件联系起来。

<window apply="org.zkoss.support.ChatRoomComposer" vflex="1" sclass="container">

在这个应用程序中,apply属性被设置为
org.zkoss.support.ChatRoomComposer,它将composer类与div联系起来。然后,这个控制器就可以操作这个div和它的子组件了。

连接组件

"ChatRoomComposer "扩展了ZK框架的SelectorComposer。SelectorComposer提供了一个注解,"@Wire",用于将ZUL中的组件与composer中的成员字段连接起来。它提供了类似CSS的选择器

public class ChatRoomComposer extends SelectorComposer {
@Wire
protected Textbox myMessage;
@Wire
private Button send;
@Wire(".messageBox")
protected Div msgBox;
@Wire("checkbox")
private Checkbox fastCheckbox;
  • 第2-3行:ZUL中id="myMessage "的<textbox>被连接到myMessage字段,因为默认是 "ID选择器"
  • 第6-7行:这是由 "sclass选择器 "连接的。
  • 第8-9行:这是由 "组件名称选择器 "连接的。

关于完整的选择器语法,请参考Wire Components。

事件监听器

控制器还通过@Listen包含了事件监听器,它监听ZUL中组件上的事件,例如最终用户点击按钮或检查复选框。

点击发送按钮

在这个应用程序中,当 "发送 "按钮被点击时,我想调用send(),所以我写道。

public class ChatRoomComposer extends SelectorComposer {
...
@Listen("onClick = #send")
public void send(){...}

onClick是事件名称。#send是 "发送 "按钮的ID选择器。

此外,为了方便,当终端用户在关注文本框时按下 "Enter "键,我也希望send()方法被调用。因此我写道。

public class ChatRoomComposer extends SelectorComposer {
...
@Listen("onClick = #send; onOK = #myMessage")
public void send(){...}

onOK是终端用户在文本框中按下 "Enter "键时触发的事件名称。

所以现在我可以用一个监听器成功地监听到2个事件。关于完整的监听器语法,请参考《Wire Event Listeners》。

发送我的信息

在send()中,我可以调用组件API来实现应用逻辑:将我的消息发送到ChatGPT。

public void send(){
if (myMessage.getValue().isEmpty())
return;
if (fastCheckbox.isChecked()){
submitFastResponse();
}else{
submit();
}
}

myMessage.getValue() 返回文本框中的用户输入。

fastCheckbox.isChecked() 返回 "快速响应 "的检查状态。

现在我可以发送和接收消息了,我只需要在用户界面上显示它们。

显示AI回复 - 在Java代码中构建UI

在文章的开头,我用zul来显示我的用户界面。你可以在这里使用同样的方式来显示AI回复,但我决定使用一种不同的技术--使用Java代码来创建和操作ZK组件。

protected void appendAiMessage(String myMessage) {
Div msgDiv = new Div();
Label aiName = new Label("ChatAI: ");
aiName.setSclass("ai");
msgDiv.appendChild(aiName);
Label msg = new Label(chatService.prompt(myMessage));
msg.setMultiline(true);
msgDiv.appendChild(msg);
msgBox.appendChild(msgDiv);
}


  • 它创建了一个Div组件来容纳整个AI信息。
  • 创建一个新的Label组件,名为aiName,文本为 "ChatAI:",并将其样式类设置为ai。因为我想把这个文本变成绿色。
  • 它将aiName追加到msgDiv中作为其子项。
  • 它创建了另一个名为msg的Label,其文本来自chatService.prompt(),是ChatpGPT的回复。我将多行属性设置为true以显示多行消息
  • 最后,它将msgDiv追加到msgBox中作为其子节点。

正如你所看到的,你可以在Java中创建UI组件,配置它们,并建立父-子关系。实际上,你可以用zul做的一切,都可以在Java代码中完成。

显示我的信息 - 用Zul在Java中建立UI

接下来,我将在用户界面中显示用户的信息。同样,你可以使用上面提到的同样的方法,但我决定使用另一种技术--用ZUL在Java中构建用户界面。

用zul和Java构建UI有它自己的好处。使用zul的好处是可读性。通过ZUL,你可以对一个页面有一个大致的了解。然而,使用Java可以让你在运行时根据状态动态地构建UI。如果我可以同时拥有这两个好处呢?这将是非常好的!

ZK确实提供了这样一种方式:通过向
Executions.createComponents()传递zul路径,你可以用zul动态创建组件

protected void appendMyMessage(String myMessage) {
Div msgDiv = new Div();
Executions.createComponents("/me.zul", msgDiv, null);
msgDiv.appendChild(new Label(myMessage));
msgBox.appendChild(msgDiv);
}

从一个ZUL代码段动态地创建UI组件。ZUL代码片段为用户名创建了一个Label。然后这个组件被附加到msgDiv .NET中。

使用这种方法,你可以建立一个动态的、功能性的用户界面,并根据你的应用程序的需要进行优化。

在这一点上,我已经把所有的东西都挂接起来了,我的由ChatGPT驱动的聊天室应用程序已经完全正常了

总结

通过询问ChatGPT,我能够收集到将ChatGPT纳入我的应用程序所需的所有信息。并非所有ChatGPT的答案都是准确的,但询问后续问题或重新表述我的问题都有帮助,并引导我找到我需要的一切。这个过程很有趣,节省了我50%以上的阅读文档和在线寻找资源的时间。