乐趣区

关于javascript:如何构建全栈-AI-应用

人工智能 (AI) 最近掀起了波澜,ChatGPT 通过 chat completion 性能彻底改变了互联网。

你能够用它做很多事件:起草电子邮件或其余文章、答复文档相干的问题、创立会话代理、为你的软件提供自然语言界面、辅导各种科目、翻译语言等等。

本文将教会你应用 chat completion 性能构建聊天应用程序的基础知识,让每个程序员都能轻松上手。它并不像看起来那么难。

你将学到以下内容:

  • 如何仅应用 Node.js 创立 CLI 聊天应用程序
  • 如何仅应用 React 构建聊天应用程序
  • 如何联合 React 和 Node.js 来创立更好的聊天 AI 软件

本文的内容将基于 gpt-3.5-turbo 模型

所需常识

本教程须要 JavaScript、CSS、React 和 Node.js 的基本知识。

你还须要在 chatGPT 的 OpenAI 平台上领有一个帐户。你能够在这里创立一个

如何应用 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 导入 ConfigurationOpenAIApi,以及从 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 对象的新实例。在其中,你将为 organizationapiKey 输出值。你能够在设置中找到你的组织的详细信息,在 API keys 中找到你的 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);
  });

此代码调用触发接口 ([](https://api.openai.com/v1/chat/completions)https://api.openai.com/v1/chat/completions) 的 createChatCompletion 函数。该函数承受一个参数对象(正在应用的 chatGPT 模型 和用户与 AI 之间的 messages 数组。咱们将在下一章中理解如何应用 messages 数组来保留聊天记录并改良应用程序)。

每条音讯都是一个对象,蕴含 role(即谁发送了音讯。当音讯来自人时,这个值为 user;如果它来自 AI,则该值能够是 assistant)和 content(发送的信息)

最初,代码打印来自 AI 的响应内容(res.data.choices[0].message.content),应用以下命令在终端中运行文件:

node index

这将在几秒钟后返回 AI 的响应

这就是创立聊天机器人所需的所有!

然而,为了使应用程序更具交互性,咱们须要让程序能够接管用户输出音讯而不是将音讯内容硬编码到代码中。readline 模块将在这方面帮忙咱们。

要使其具备交互性,请删除输出的最初一个代码并增加以下内容:

const userInterface = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

此代码在终端中创立一个 UI,容许用户输出他们的问题。

接下来,应用以下代码提醒用户输出音讯:

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
  • 显示 AI 的响应后,将提醒用户在 then中输出另一条音讯

增加 dotenv

npm i dotenv

根目录创立 .env 文件,在文件中编写以下环境变量(你本人的账号的 Configuration 信息)

ORG = "org-xxx"
API_KEY = "sk-xxx"

批改 index.js 文件

...
...
import * as dotenv from 'dotenv'

dotenv.config()

const configuration = new Configuration({
    organization: process.env.ORG,
    apiKey: process.env.API_KEY,
})

最初记得创立我的项目的 .gitignore 文件,增加上面的内容

node_modules
.DS_Store
.env

你能够在这里看到所有的代码

[](https://github.com/zidanDirk/nodejs-chatgpt-tutorial-cn/)https://github.com/zidanDirk/nodejs-chatgpt-tutorial-cn/

运行文件并与 AI 对话。它将如下图所示:

十分好!这是一个交互式 CLI 聊天工具。

这对多数人(如工程师)有用,但它具备良好的安全性,因为它能够运行在服务器端

然而其余可能不理解如何应用 CLI 应用程序的人呢?他们将须要更易于应用、具备更敌对的用户界面 (UI) 和用户体验 (UX) 的货色。下一节将重点介绍如何应用 React 构建此类应用程序。

如何应用 React 创立一个聊天程序

本节旨在帮忙前端开发人员放慢应用 ChatGPT API 的速度,以创立聊天应用程序并构建更好的用户界面,从而为用户提供更好的体验。你能够将在这里取得的常识利用到其余前端框架或库中。

首先要做的是设置一个根本的 React 模版。为此,我将应用 Vite。你能够应用 Vite 作为搭建任何古代 JavaScript 前端我的项目的脚手架。应用以下命令:

npm create vite@latest

✔ Project name: react-chatgpt-tutorial-cn
✔ Select a framework: › React
✔ Select a variant: › JavaScript

此命令将提醒你为我的项目创立名称和文件夹,并抉择框架或库(本教程应用 React)。之后,你将进入到该文件夹并运行以下命令:

npm install
npm run dev

这些命令将装置必要的依赖项并在端口 5173 上启动本地服务器

接下来,应用以下命令装置 OpenAI:

npm i openai

这个模块能够拜访咱们创立聊天应用程序所需的所有。

当初咱们筹备开始编写代码了!

定位到 src/App.jsx 文件并删除它所有的内容。增加上面的导入语句

import {useState} from "react";
import {Configuration, OpenAIApi} from "openai";

下面的代码导入了用于设置配置值的 ConfigurationOpenAIApi,使咱们可能拜访 chat completion 性能。

之后,像这样构建配置:

const configuration = new Configuration({
  organization: "org-xxxx",
  apiKey: "sk-xxxx",
});

此代码创立 Configuration 对象的新实例。在其中,你将为 organizationapiKey 输出值。你能够在设置中找到你的组织的详细信息,在 API keys 中找到你的 apiKey 信息。如果你没有现有的 API Key,您能够创立它。

配置后输出以下代码,创立一个新的 OpenAI API 实例:

const openai = new OpenAIApi(configuration);

咱们将在整个我的项目中应用它。

创立并导出默认函数:

function App() {
  return <main>
        <h1> 对话 AI 教程 </h1>
      </main>
}

return 之前设置上面的 state

const [message, setMessage] = useState("");
const [chats, setChats] = useState([]);
const [isTyping, setIsTyping] = useState(false);
  • message 将保留从应用程序发送到 AI 的信息。
  • chats 数组将跟踪单方(用户和 AI)发送的所有音讯。
  • isTyping 变量将告诉用户以后机器人是否正在输出。

在 h1 标签下键入以下代码行

<div className={isTyping ? "":"hide"}>
  <p>
    <i>{isTyping ? "正在输出..." : ""}</i>
  </p>
</div>

每当用户期待 AI 的响应时,下面的代码将显示 正在输出...

通过将以下代码增加到 main 元素中,创立一个用户能够在其中键入音讯的表单:

<form action="" onSubmit={(e) => chat(e, message)}>
  <input
    type="text"
    name="message"
    value={message}
    placeholder="在这里输出音讯并按下回车键..."
    onChange={(e) => setMessage(e.target.value)}
  />
</form>

此代码创立一个具备一个输出项的表单。每当通过按 回车 键提交表单时,它都会触发 chat 回调函数。

chat 回调函数将会承受两个参数(emessage),像这样:

const chat = async (e, message) => {}

函数的内容是这样的:

const chat = async (e, message) => {e.preventDefault();
      
      if (!message) return;
      setIsTyping(true);
 }

下面的代码阻止表单从新刷新网页,查看在提交之前是否键入了音讯,并将 isTyping 设置为 true 来告知应用程序已开始解决用户的输出。

ChatGPT 响应的音讯的格局采纳以下模式:

{role: user | assistant, content: message to be sent}

每条音讯(content)都必须显示发送者。当聊天来自 AI 时,roleassitant,但如果是来自人类,则 roleuser。因而,在发送音讯之前,请务必正确格式化并将其增加到数组(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:
              "你当初是 EbereGPT。你能够帮忙实现图形设计工作",
          },
          ...chats,
        ],
      })

createChatCompletion 函数至多须要 2 个参数(modelmessages):

  • model 指定了正在应用的 chatGPT 版本
  • messages 是到目前为止用户和 AI 之间的所有音讯的列表,以及让 AI 理解它能够提供什么样的帮忙的零碎音讯。
{
    role: "system",
    content: "你当初是 EbereGPT。你能够帮忙实现图形设计工作",
}

你能够将 content 更改为适宜你的任何内容

messages 不用是数组并且蕴含多个对象。它能够只是一条音讯。然而当它是一个数组时,它提供了 AI 能够依赖的音讯历史记录,以便在将来提供更好的回复,并且它能够缩小用户的输出,因为能够不须要始终进行适度形容。

createChatCompletion 函数返回的是一个 promise 对象,所以须要应用 thencatch 来获取响应

            .then((res) => {msgs.push(res.data.choices[0].message);
        setChats(msgs);
        setIsTyping(false);
      })
      .catch((error) => {console.log(error);
      });

此代码将 AI 返回的音讯增加到 chats 数组并将 isTyping 设置为 false,示意 AI 已实现回复。

当初应该在每次发送音讯时收到反馈(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

输入应该如下所示:

这几乎泰裤辣

如果你是一步一步依照我上述的教程编码,那你还须要在这个时候增加你的款式,让你的利用更加好看。用上面的代码替换 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;
}
.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;}

应用 React 和 ChatGPT 创立聊天机器人的过程到此结束。它并不像听起来那么难。

然而像这样的前端应用程序最适宜演示,而不是生产。以这种形式创立应用程序的问题是前端将 API 密钥裸露给网络攻击。

要解决这个问题,理智的做法是将 API Key 和 Organisation Id 保留在云中平安的某个中央并援用它,或者为您的应用程序构建一个安全性更高的后端。

本章的代码你能够在 这里 取得

下一节将解决这个问题。

如何联合 React 和 Node.js 制作全栈聊天 AI 软件

本局部当初将联合后面局部的性能来构建更平安的应用程序,同时展现更好的 UI 和 UX

咱们将通过应用服务器来改良 Node 局部,为前端的调用裸露一个接口,并简化前端与后端的交互,而不是间接调用 OpenAI

如何搭建我的项目

这部分将创立我的项目所需的文件夹和文件。

创立我的项目目录:

mkdir react-nodejs-chatgpt-tutorial-cn

进入目录

cd react-nodejs-chatgpt-tutorial-cn

应用 Vite 创立 React 我的项目,命名为 frontend,应用以下命令

npm create vite@latest

接着咱们进入目录进行装置和运行

npm install

npm run dev

这些命令将装置必要的依赖项并在端口 5173 上启动本地服务器

创立后端目录:

mkdir backend

当初进入到后端文件夹并应用以下命令初始化我的项目:

cd backend
npm init -y

这将创立一个 package.json 文件来跟踪我的项目详细信息

将以下代码行增加到文件中:

"type": "module"

这将使你可能应用 ES6 模块导入语句

应用上面的命令来装置 OpenAI 和其余依赖项

npm i openai body-parser cors express dotenv

创立一个蕴含所有代码的文件。将其命名为 index.js

touch index.js

这样就实现了我的项目设置。当初有两个文件夹(frontendbackend

如何创立一个服务器

这部分将重点创立一个本地服务器来监听 8000 端口

首先要做的是像这样导入必要的模块:

import {Configuration, OpenAIApi} from "openai";
import express from "express";
import bodyParser from "body-parser";
import cors from "cors";
import * as dotenv from 'dotenv'
dotenv.config()

接下来,设置 express、要监听的 端口、用于接管输出的 body-parser 以及容许前端和后端之间跨域通信的 cors,设置环境变量的 dotenv,应用以下代码:

const app = express();
const port = 8000;
app.use(bodyParser.json());
app.use(cors());

最初输出上面的代码

app.listen(port, () => {console.log(` 正在监听端口 ${port} ...`);
});

这样就实现了服务器设置。

当你运行 index.js 时,应该失去以下输入:

正在监听端口 8000 ...

如何创立一个接口

在这一部分中,咱们将构建一个接口,该接口将从前端接管音讯并将响应返回给调用者。

像咱们在前几节中所做的那样,首先建设配置参数:

const configuration = new Configuration({
    organization: process.env.organization,
    apiKey: process.env.apiKey,
});
const openai = new OpenAIApi(configuration);

创立 backend/.env 文件,在 .env 文件中配置 organizationapiKey

organization = "xxxx"
apiKey="xxx"

接下来,应用以下代码创立异步 POST 路由:

app.post("/", async (request, response) => {});

将应用 [](http://localhost:8000/)http://localhost:8000/ 调用此接口

在回调函数中,输出以下代码以接管从申请体(request.body)输出的聊天信息:

const {chats} = request.body;

当初像咱们在 React 局部中所做的那样调用 createChatCompletion 办法:

const result = await openai.createChatCompletion({
        model: "gpt-3.5-turbo",
        messages: [
          {
            role: "system",
            content: "你当初是 EbereGPT。你能够帮忙实现图形设计工作",
          },
          ...chats,
        ],
    });

这里的区别在于,咱们没有应用 then...catch... 块,而是将其调配给一个变量(result)并应用 response.json() 返回响应,如以下代码所示:

response.json({output: result.data.choices[0].message,
  });

你能够在这里查问到相干的代码

如何在前端连贯后端服务

这部分将咱们带到前端,咱们将在其中创立一个表单。表单将通过 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> 全栈 AI 聊天程序 </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 ? "正在输出..." : ""}</i>
        </p>
      </div>

      <form action="" onSubmit={(e) => chat(e, message)}>
        <input
          type="text"
          name="message"
          value={message}
          placeholder="在这里输出音讯并按下回车键..."
          onChange={(e) => setMessage(e.target.value)}
        />
      </form>
    </main>
  );
}
export default App;

此代码相似于上一节中的代码。然而咱们删除了 OpenAI 配置,因为在本节中咱们将不再须要它们。

此时,每当提交表单时都会弹出警报。这将在一瞬间扭转。

在聊天性能中,去掉正告音讯并输出以下内容:

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: none;
  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;
}

.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);
  color: white;
}

input:focus{outline: none;}

以下就是目前的 UI

祝贺你实现了这个我的项目!

全栈聊天机器人的工作量更大,但它帮忙咱们拆散关注点,构建更平安、更有吸引力的应用程序,并为用户提供更好的体验。所以这些致力是值得的。

你能够在这里找到这个章节的代码

总结

本教程心愿向你展现任何具备根本编程常识的人都能够构建 AI 驱动的软件。学习了如何应用 React 和 Nodejs 构建聊天机器人,咱们探讨了每种技术的优缺点。最初,咱们构建了一个既实用、平安又好看的解决方案。

浏览本教程后,你当初能够摸索 AI 的更多功能,例如图像处理和音频交互。花点工夫浏览文档,看看如何扩大咱们在这里介绍的内容。最初感激大家对本文的反对~欢送点赞珍藏,在评论区留下你的浅见 🌹🌹🌹

其余

  • 本文是翻译文,原文地址
  • 代码仓库

    • [](https://github.com/zidanDirk/react-nodejs-chatgpt-tutorial-cn)https://github.com/zidanDirk/react-nodejs-chatgpt-tutorial-cn
    • [](https://github.com/zidanDirk/react-chatgpt-tutorial-cn)https://github.com/zidanDirk/react-chatgpt-tutorial-cn
    • [](https://github.com/zidanDirk/nodejs-chatgpt-tutorial-cn)https://github.com/zidanDirk/nodejs-chatgpt-tutorial-cn
退出移动版