如何用OpenAI、ChatGPT、Node.js和React搭建一個AI聊天機器人

如何用OpenAI、ChatGPT、Node.js和React搭建一個AI聊天機器人

文章目录

  • 前提條件
  • 如何用Node.js建立一個CLI聊天AI應用程式
  • 如何使用React建立一個聊天應用程式
  • 如何結合React和Node.js來製作一個全棧式的聊天AI軟體
  • 如何設定專案
  • 如何搭建伺服器
  • 如何建立端點
  • 如何從前端連線到後端
  • 小結

如何用OpenAI、ChatGPT、Node.js和React搭建一個AI聊天機器人

人工智慧(AI)最近一直在掀起波瀾,ChatGPTChat 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模組匯入 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金鑰中找到你的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聊天

與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)個引數(emessage),像這樣:

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的情況下按預期工作

聊天機器人在沒有CSS的情況下按預期工作

這看起來很酷!但新增一些造型會讓它看起來像WhatsAppMessenger一樣吸引人。用以下內容替換 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工作

聊天機器人如期使用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的輸出

來自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

樣式設計前的全棧聊天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工作

全棧式聊天機器人如期使用CSS工作

恭喜你完成了這個專案!全棧聊天機器人的工作更多,但它幫助我們分離了關注點,建立了一個更安全和有吸引力的應用程式,併為使用者提供了更好的體驗。所以,這些努力是值得的。你可以在GitHub上找到這一部分的程式碼。

小結

本教學希望向你展示,任何具有基本程式設計知識的人都可以構建人工智慧驅動的軟體。你學會了如何使用React和Nodejs構建一個聊天機器人,我們還討論了每種技術的利弊。最後,我們建立了一個既實用、安全又有視覺吸引力的解決方案。讀完本教學後,你現在可以探索AI的功能,如影象處理和音訊互動。花點時間瀏覽一下文件,看看你可以如何擴充套件我們在這裡涉及的內容。

評論留言