人工智能(AI)最近一直在掀起波澜,ChatGPT的Chat completions彻底改变了互联网。
你可以用它做很多事情:起草电子邮件或其他文章,回答关于一组文件的问题,创建对话代理,给你的软件一个自然语言界面,辅导各种科目,翻译语言,等等。本教程使用Chat completions功能建立一个AI聊天应用程序的基本知识,使每个程序员都能轻松上手。它并不像看起来那样艰难。在你跟随本教程时,你会看到这一点。
您将学到以下内容:
- 如何只用Node.js创建一个CLI聊天应用程序。
- 如何只用React建立一个聊天应用。
- 如何结合React和Node.js来创建更好的聊天AI软件。
本教程将以 gpt-3.5-turbo
模型为基础。
前提条件
本教程需要JavaScript、CSS、React和Node.js的基本知识。你还需要一个OpenAI平台的账户,chatGPT就在这个平台上。它是免费的,所以你可以在这里创建一个。
如何用Node.js创建一个CLI聊天AI应用程序
本节将重点介绍创建一个只在终端使用Node.js运行的聊天应用程序。
首先,为该项目创建一个目录:
mkdir nodejs-chatgpt-tutorial
导航到该文件夹:
cd nodejs-chatgpt-tutorial
初始化该项目:
npm init -y
这将创建一个 package.json
文件来跟踪项目的细节
在该文件中添加以下一行代码:
"type": "module"
这将使你能够使用ES6模块的导入语句。用以下命令安装OpenAI:
npm i openai
创建一个文件,所有的代码都在其中。命名为 index.js
:
touch index.js
从OpenAI模块导入 Configuration
和 OpenAIApi
,从 readline
模块导入readline:
import { Configuration, OpenAIApi } from "openai"; import readline from "readline";
像这样建立OpenAI的配置:
const configuration = new Configuration({ organization: "org-0nmrFWw6wSm6xIJXSbx4FpTw", apiKey: "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", });
这段代码创建了一个 Configuration
对象的新实例。在它里面,你将输入你的 organization
和 apiKey
的值。你可以在设置中找到你的组织的详细信息,在API密钥中找到你的apiKey信息。如果你没有现有的API Key,你可以创建它。在配置后输入以下代码,创建一个新的OpenAI API实例:
const openai = new OpenAIApi(configuration);
你将在整个项目中使用它。
输入下面的代码来测试 createChatCompletion
函数:
openai .createChatCompletion({ model: "gpt-3.5-turbo", messages: [{ role: "user", content: "Hello" }], }) .then((res) => { console.log(res.data.choices[0].message.content); }) .catch((e) => { console.log(e); });
这段代码调用 createChatCompletion
函数,触发一个端点( https://api.openai.com/v1/chat/completions
)。该函数接受一个参数对象(使用中的chatGPT model
和用户与AI之间的 messages
数组。我们将在下一节中研究如何使用 messages
数组来保存聊天历史并改进应用程序)。每个消息都是一个对象,包含 role
(即谁发送了该消息。如果是来自人工智能,该值可以是助理,如果是来自人类的消息,该值可以是用户)和 content
(发送的信息)。最后,代码打印了来自人工智能的响应( res.data.choice[0].message.content
)。用这个命令在终端运行该文件:
node index
这将在几秒钟后返回人工智能的响应。这就是创建聊天机器人的全部内容!但通过请求用户输入信息而不是将信息内容硬编码到代码中,使应用程序更具互动性将是很有帮助的。readline模块将在这方面帮助我们。要使其具有互动性,请删除你最后输入的代码,并添加以下内容:
const userInterface = readline.createInterface({ input: process.stdin, output: process.stdout, });
这段代码在终端创建了一个用户界面,允许用户输入他们的问题。
接下来,用下面的代码提示用户输入一个信息:
userInterface.prompt();
最后,输入以下代码:
userInterface.on("line", async (input) => { await openai .createChatCompletion({ model: "gpt-3.5-turbo", messages: [{ role: "user", content: input }], }) .then((res) => { console.log(res.data.choices[0].message.content); userInterface.prompt(); }) .catch((e) => { console.log(e); }); });
在上面的代码中
- 当用户输入东西并点击
Enter
时,上面的代码会触发一个回调函数。 - 它将用户输入的任何内容作为
input
。 -
input
的内容现在被用作content
。 - 在显示人工智能的响应后,在
then
块中提示用户输入另一条信息。
查看GitHub上的所有代码。运行该文件并与人工智能进行对话。它将看起来像下面的图片:
与AI的CLI聊天
很好! 这是一个交互式CLI聊天。这对少数人(如工程师)很有用,但它有很好的安全性,因为它是在服务器端。但其他可能不了解如何使用CLI应用程序的人呢?他们将需要一些更容易使用的、具有更好的用户界面(UI)和用户体验(UX)的东西。下一节将重点介绍使用React构建这种应用程序。
如何使用React创建一个聊天应用程序
本节旨在帮助前端开发者快速掌握ChatGPT API,以创建一个聊天应用程序,并构建一个更好的用户界面,给用户带来更好的体验。你可以把在这里获得的知识应用于其他前端框架或库。
首先要做的是设置一个基本的React模板。我将使用Vite来实现这一目的。你可以用Vite来搭建任何现代JavaScript前端项目的脚手架。使用下面的命令:
npm create vite@latest
该命令将提示你为你的项目创建一个名称和文件夹,并选择一个框架或库(本教程使用React)。之后,你将导航到该文件夹,并运行以下命令:
npm install npm run dev
这些命令将安装必要的依赖性,并在 5173
端口启动本地服务器,接下来,用以下命令安装OpenAI:
npm i openai
这个模块提供了我们创建聊天应用程序所需的所有权限。现在我们准备开始写代码了!导航到 src/App.jsx
文件,删除其所有内容。然后添加以下导入语句:
import { useState } from "react"; import { Configuration, OpenAIApi } from "openai";
上面的代码导入了用于设置配置值的 Configuration
和用于让我们访问Chat completions的 OpenAIApi
。之后,像这样建立配置:
const configuration = new Configuration({ organization: "org-0nmrFWw6wSm6xIJXSbx4FpTw", apiKey: "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", });
这段代码创建了一个 Configuration
对象的新实例。在它里面,你输入你的 organization
和 apiKey
的值。你可以在设置中找到你的组织的详细信息,你的apiKey信息在API密钥中。如果你没有现有的API密钥,你可以创建它。在配置后输入以下代码,创建一个新的OpenAI API实例:
const openai = new OpenAIApi(configuration);
我们将在整个项目中使用它。创建并导出一个默认函数:
function App() { return ( <main> <h1>Chat AI Tutorial</h1> <main/> ); } export default App;
这个函数将容纳其余的代码。在 return
语句之前设置以下状态:
const [message, setMessage] = useState(""); const [chats, setChats] = useState([]); const [isTyping, setIsTyping] = useState(false);
message
将保存从应用程序发送至人工智能的信息。chats
数组将记录双方(用户和人工智能)发送的所有信息。isTyping
变量将通知用户,机器人是否正在打字。
在h1标签下输入以下几行代码
<div className={isTyping ? "" : "hide"}> <p> <i>{isTyping ? "Typing" : ""}</i> </p> </div>
上面的代码将显示 Typing
,只要用户在等待AI的响应。创建一个表单,用户可以在其中输入信息,将下面的代码添加到 main
元素中:
<form action="" onSubmit={(e) => chat(e, message)}> <input type="text" name="message" value={message} placeholder="Type a message here and hit Enter..." onChange={(e) => setMessage(e.target.value)} /> </form>
这段代码创建了一个有一个输入的表单。每当点击 Enter
键提交表单时,就会触发 chat
函数。聊天函数将接受两(2)个参数(e
和 message
),像这样:
const chat = async (e, message) => { }
在该函数中输入以下几行:
e.preventDefault(); if (!message) return; setIsTyping(true);
上面的代码防止 form
重新加载网页,检查提交前是否输入了信息,并将 isTyping
设置为 true
,以表明应用程序已经开始处理所提供的输入。ChatGPT有一个信息的格式。它采取以下模式:
{role: user | assistant, content: message to be sent
每条信息(content
)都必须显示谁发送的。当聊天是来自人工智能时,角色是 assistant
,但如果是来自人类,则是 user
。因此,在发送消息之前,一定要正确地格式化它,并像这样把它添加到数组(chats
)中:
let msgs = chats; msgs.push({ role: "user", content: message }); setChats(msgs); setMessage("");
上面的最后一行清除了输入,以便用户输入另一个音符。现在我们将通过使用下面的代码触发 createChatCompletion
函数来调用 createChatCompletion
端点:
await openai .createChatCompletion({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: "You are a EbereGPT. You can help with graphic design tasks", }, ...chats, ], })
createChatCompletion
函数至少需要两(2)个参数(model
和 messages
):
- 模型指定了正在使用的chatGPT的版本。
- 消息是迄今为止用户和人工智能之间的所有消息的列表,以及一个系统消息,让人工智能了解它能提供什么样的帮助。
{ role: "system", content: "You are a EbereGPT. You can help with graphic design tasks", }
你可以把内容改成任何适合你的东西。messages
不一定要在数组中包含一个以上的对象。它可以只是一条消息。但是当它是一个数组时,它提供了一个消息历史,人工智能可以依靠它在未来给出更好的回复,而且它使用户打字更少,因为可能没有必要一直过度描述。 createChatCompletion
函数返回一个承诺。所以使用 then...catch...
块来获取响应。
.then((res) => { msgs.push(res.data.choices[0].message); setChats(msgs); setIsTyping(false); }) .catch((error) => { console.log(error); });
这段代码将从人工智能返回的消息添加到聊天数组中,并将 isTyping
设置为 false
,表示人工智能已经完成了回复。你现在应该在每次发送消息时收到反馈(Typing):
聊天应用程序在人工智能即将作出反应时给予反馈
现在是显示聊天历史给用户看的时候了。在 h1
标签下面输入以下代码:
<section> {chats && chats.length ? chats.map((chat, index) => ( <p key={index} className={chat.role === "user" ? "user_msg" : ""}> <span> <b>{chat.role.toUpperCase()}</b> </span> <span>:</span> <span>{chat.content}</span> </p> )) : ""} </section>
上面的代码循环浏览 chats
,并将它们一个接一个地显示给用户。它把 role
的大写字母和消息的 content
并排输出。以下是输出结果的样子:
聊天机器人在没有CSS的情况下按预期工作
这看起来很酷!但添加一些造型会让它看起来像WhatsApp或Messenger一样吸引人。用以下内容替换 src/index.css
文件的内容:
:root { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; line-height: 1.5; font-weight: 400; color-scheme: light dark; color: rgba(255, 255, 255, 0.87); background-color: #242424; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-text-size-adjust: 100%; } h1 { font-size: 3.2em; line-height: 1.1; text-align: center; position: sticky; top: 0; background-color: #242424; } main{ max-width: 500px; margin: auto; } p{ background-color: darkslategray; max-width: 70%; padding: 15px; border-radius: 50px; } p span{ margin: 5px; } p span:first-child{ margin-right: 0; } .user_msg{ text-align: right; margin-left: 30%; display: flex; flex-direction: row-reverse; } .hide { visibility: hidden; display: none; } form{ text-align: center; position: sticky; bottom: 0; } input{ width: 100%; height: 40px; border: none; padding: 10px; font-size: 1.2rem; } input:focus{ outline: none; }
并删除 src/App.css
文件中的所有样式。
你可以在GitHub上找到完整的代码。现在应用程序应该有一个新的外观:
聊天机器人如期使用CSS工作
用React和ChatGPT创建一个聊天机器人的工作就这样结束了。它并不像听起来那么困难。但像这样的前端应用最好是用于演示,而不是生产。这样创建应用程序的问题是,前端将API密钥暴露给网络攻击。
要解决这个问题,明智的做法可能是将API Key和Organisation Id保存在云端某个安全的地方并引用它,或者为你的应用程序建立一个具有更好安全性的后端。下面的部分将致力于解决这个问题。
如何结合React和Node.js来制作一个全栈式的聊天AI软件
本节现在将加入前几节的力量,建立一个更安全的应用程序,同时表现出更好的用户界面和用户体验。
我们将改进Node部分,使用服务器来暴露一个端点供前端使用,并简化前端与后台的交互,而不是直接联系OpenAI。
如何设置项目
这一部分将创建项目所需的文件夹和文件。创建项目目录:
mkdir react-node-chatgpt-tutorial
导航到该文件夹:
cd react-node-chatgpt-tutorial
使用Vite安装React,并将文件夹命名为 frontend
。使用这个命令:
npm create vite@latest
之后,你将浏览到该文件夹并运行以下命令:
npm install npm run dev
这些命令将安装必要的依赖,并在 5173
端口启动本地服务器。创建后台文件夹:
mkdir backend
现在导航到后端文件夹,用这个命令初始化项目:
npm init -y
这将创建一个 package.json
文件来跟踪项目的细节。在该文件中添加以下一行代码:
"type": "module"
这将使ES6模块导入语句的使用成为可能。用下面的命令安装OpenAI和其他依赖项:
npm i openai body-parser cors express
创建一个文件,所有的代码都在其中。命名为 index.js
:
touch index.js
这就完成了项目的设置。现在有两个文件夹(frontend
和 backend
)。
如何搭建服务器
这一部分将着重于创建一个本地服务器,以监听 8000
端口。
首先要做的是像这样导入必要的模块:
import { Configuration, OpenAIApi } from "openai"; import express from "express"; import bodyParser from "body-parser"; import cors from "cors";
接下来,设置 express
、监听 port
、用于接收输入的 body-parser
以及允许前端和后端自由通信的 cors
。使用下面的代码:
const app = express(); const port = 8000; app.use(bodyParser.json()); app.use(cors());
最后,输入以下代码:
app.listen(port, () => { console.log(`listening on port ${port}`); });
这就完成了服务器的设置。当你运行 index.js
时,你应该得到以下输出:
listening on port 8000
如何创建端点
在这一部分,我们将建立一个端点,该端点将使用请求体接收来自前端的消息,并向调用者返回一个响应。开始时,我们要像前几节那样建立配置参数:
const configuration = new Configuration({ organization: "org-0nmrFWw6wSm6xIJXSbx4FpTw", apiKey: "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", }); const openai = new OpenAIApi(configuration);
接下来,使用下面的代码创建一个异步POST路由:
app.post("/", async (request, response) => { });
这个端点将使用 http://localhost:8000/
,在回调函数中,输入以下代码,从请求体( request.body
)接收 chats
的输入:
const { chats } = request.body;
现在像我们在React部分做的那样,调用 createChatCompletion
端点:
const result = await openai.createChatCompletion({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: "You are a EbereGPT. You can help with graphic design tasks", }, ...chats, ], });
这里的区别是,我们没有使用 then...catch...
块,而是将其分配给一个变量( result
),并使用 response.json()
返回响应,如以下代码:
response.json({ output: result.data.choices[0].message, });
在GitHub上找到这部分的代码。以下是在Postman上测试时的输出:
来自Postman的输出
代码的后端部分就这样结束了。下一部分将使用刚刚创建的端点( http://localhost:8000/
)连接前端和后端。
如何从前端连接到后端
这一部分把我们带到前台,在那里我们将创建一个表单。该表单将通过API端点向后端发送消息,并通过相同的媒介接收响应。导航到 frontend/src/App.jsx
文件并输入以下代码:
import { useState } from "react"; function App() { const [message, setMessage] = useState(""); const [chats, setChats] = useState([]); const [isTyping, setIsTyping] = useState(false); const chat = async (e, message) => { e.preventDefault(); if (!message) return; setIsTyping(true); let msgs = chats; msgs.push({ role: "user", content: message }); setChats(msgs); setMessage(""); alert(message); }; return ( <main> <h1>FullStack Chat AI Tutorial</h1> <section> {chats && chats.length ? chats.map((chat, index) => ( <p key={index} className={chat.role === "user" ? "user_msg" : ""}> <span> <b>{chat.role.toUpperCase()}</b> </span> <span>:</span> <span>{chat.content}</span> </p> )) : ""} </section> <div className={isTyping ? "" : "hide"}> <p> <i>{isTyping ? "Typing" : ""}</i> </p> </div> <form action="" onSubmit={(e) => chat(e, message)}> <input type="text" name="message" value={message} placeholder="Type a message here and hit Enter..." onChange={(e) => setMessage(e.target.value)} /> </form> </main> ); } export default App;
这段代码与上一节的代码相似。但我们删除了OpenAI的配置,因为我们在本节中不再需要它们。
在这一点上,每当表单被提交时,就会弹出一个警报。这一点一会儿就会改变。在聊天函数中,去掉 alert
信息,然后输入以下内容:
fetch("http://localhost:8000/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ chats, }), }) .then((response) => response.json()) .then((data) => { msgs.push(data.output); setChats(msgs); setIsTyping(false); }) .catch((error) => { console.log(error); });
上面的代码调用了我们创建的端点,并传入 chats
数组供其处理。然后它返回一个响应,该响应被添加到 chats
中并显示在用户界面上:
样式设计前的全栈聊天UI
如果你在 frontend/src/index.css
文件中添加以下样式,UI会看起来更好:
:root { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; line-height: 1.5; font-weight: 400; color-scheme: light dark; color: rgba(255, 255, 255, 0.87); background-color: #242424; font-synthesis: 无; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-text-size-adjust: 100%; } html, body{ scroll-behavior: smooth; } h1 { font-size: 3.2em; line-height: 1.1; text-align: center; position: sticky; top: 0; background-color: #242424; } main{ max-width: 800px; margin: auto; } p{ background-color: darkslategray; max-width: 70%; padding: 15px; border-radius: 50px; } p span{ margin: 5px; } p span:first-child{ margin-right: 0; } .user_msg{ text-align: right; margin-left: 30%; display: flex; flex-direction: row-reverse; } .hide { visibility: hidden; display: none; } form{ text-align: center; position: sticky; bottom: 0; } input{ width: 100%; height: 40px; border: none; padding: 10px; font-size: 1.2rem; background-color: rgb(28, 23, 23); } input:focus{ outline: none; }
并删除 frontend/src/App.css
文件中的所有样式。
这一部分的代码在GitHub上。现在,这里是最终的输出:
全栈式聊天机器人如期使用CSS工作
恭喜你完成了这个项目!全栈聊天机器人的工作更多,但它帮助我们分离了关注点,建立了一个更安全和有吸引力的应用程序,并为用户提供了更好的体验。所以,这些努力是值得的。你可以在GitHub上找到这一部分的代码。
小结
本教程希望向你展示,任何具有基本编程知识的人都可以构建人工智能驱动的软件。你学会了如何使用React和Nodejs构建一个聊天机器人,我们还讨论了每种技术的利弊。最后,我们建立了一个既实用、安全又有视觉吸引力的解决方案。读完本教程后,你现在可以探索AI的功能,如图像处理和音频互动。花点时间浏览一下文档,看看你可以如何扩展我们在这里涉及的内容。
评论留言