构建强大的人工智能助理后台!
随着人工智能技术的发展,人工智能助理有望在管理企业客户支持方面发挥越来越重要的作用。大多数企业已经在其工作流程中集成了某种人工智能。
在本文中,我们将讨论人工智能助手,重点介绍它们令人难以置信的优点和潜在缺点。
此外,我们还将提供一份全面的分步指南,指导您如何使用OpenAI和Back4app 创建基于人工智能的助手。
什么是人工智能助理?
人工智能助手是一款软件,它能接收文字或语音提示并生成回复。
除其他外,这项技术还利用了自然语言处理(NLP)和机器学习。
人工智能助手的目的是模仿人类的对话。
在本文中,我们将交替使用人工智能助理和人工智能聊天机器人这两个词。不过,有些人可能会说,助手是聊天机器人的一个更复杂的版本,它也可以执行任务。
流行的人工智能助手有ChatGPT、Claude 和Gemini。
一些人工智能助手应用包括
- 客户支持(可训练人工智能助理回答客户询问)
- 开发人员帮助(人工智能助手可生成代码,帮助开发人员高效工作)
- 教育(助理可用于教育目的和用户入职培训)
- 市场营销和分析(助理可以制作市场营销材料和分析数据)
- 娱乐(人工智能聊天机器人可以制作娱乐性或创造性的回复)
人工智能助理的优势
人工智能助手有很多好处。让我们一起来看看!
提高生产力
人工智能助手可以大大提高您的业务生产力。
它们可用于任务组织、业务运营、客户支持和营销等。
利用人工智能,您可以创建高度可扩展的自主客户支持,全天候提供服务。
此外,开发人员还可以利用人工智能助手来编写、审查和记录代码。目前已经有很多专门的工具可以实现这一目的,包括 GitHub Copilot、OpenAI Codex 和 CodePal。
易用性
人工智能助手是最容易使用的软件之一,因为它们能 “理解 “人类文字。几乎任何人,无论多么精通技术,都可以使用它们。
削减成本
通过优化工作流程和实现客户支持自动化,人工智能助理可以帮助您大幅削减成本。一些研究发现,人工智能可帮助企业削减高达 20% 的成本。
信息检索
人工智能助手的最大优势之一是其获取信息的能力。它们可以快速查询多个文档,并返回简单的用户可读响应。
此外,他们还可以在回答时附上资料来源。
得益于 OpenAI API 的最新进展,您现在可以毫不费力地使用您的业务数据训练机器人。
定制与个性化
人工智能助手是高度可定制的。只需更改指令或所谓的初始提示,就能轻松实现助手的用途重塑。
此外,人工智能助手还能根据交流对象返回个性化的回复。
例如,他们可以用用户的母语回答用户的询问,或考虑以前对话的语境。
人工智能助理的缺点
没有什么是没有缺点的。
幻觉
人工智能聊天机器人有时会生成错误或无意义的信息。出现这种情况时,我们会说聊天机器人产生了幻觉。
这背后的原因是,机器人实际上并不理解他们在说什么,他们只是根据前面的单词生成最有可能的下一个单词。
如果您想了解像 ChatGPT 这样的人工智能聊天机器人是如何工作的,请查看这篇文章。
无法执行复杂操作
人工智能助手在执行简单重复的任务时表现出色,但在被要求执行复杂任务时却一败涂地。
它们普遍缺乏常识和人类智慧。如果答案不在聊天机器人的学习材料中,它很可能会返回错误的回复。
此外,它们也不能保证获得最佳效果。
维护
为确保根据业务文档培训的聊天机器人能提供准确的最新信息,您必须定期用最新文档对其进行更新。如果不进行持续维护,聊天机器人可能会提供过时的回复。
隐私和安全问题
助理有时需要处理机密商业信息或个人用户数据。这就产生了一些道德问题,使助理有可能泄露机密信息。
如何打造人工智能助理?
在本部分教程中,我们将创建一个由 GPT 驱动的虚拟助手。
我们的虚拟助理将专门回答数学问题。它将利用线程来回答后续问题。
此外,代码的设计将便于重复使用和适应其他应用。
在后台,我们将使用OpenAI和Back4app,前台将使用React(配合TailwindCSS)。
先决条件
- 基本了解JavaScript ES6
- 具有使用React和React 挂钩的经验
- 拥有一些积分的OpenAI 账户
- 免费的Back4app 账户
目标
# | 后台 | 前端 |
1 | 创建 Back4app 应用程序 | 引导新项目 |
2 | 升级应用程序的 Node.js 版本 | 安装 TailwindCSS |
3 | 创建 OpenAI 密匙 | 编写用户界面代码 |
4 | 将秘钥添加为环境变量 | 安装和配置 Parse SDK |
5 | 创建Cloud Code功能 | 连接后台 |
开始编码吧
后台
在本教程的这一阶段,我们将负责后台。我们将创建一个 Back4app 应用程序,创建 OpenAI 密钥,将其添加为环境变量,并编写所需的Cloud Code函数。
创建 Back4app 应用程序
首先,登录您的Back4app 账户,如果您还没有账户,请创建一个。
登录后,您将被重定向到应用程序列表。单击 “创建新应用程序 “创建应用程序。
Back4app 平台允许您部署两种类型的应用程序:后端即服务(BaaS)和容器即服务(CaaS)。我们正在构建后台,因此使用 BaaS。
接下来,给应用程序起一个信息丰富的名字,将数据库设为 NoSQL,然后点击 “创建”。
等待大约三分钟,平台就会创建应用程序。Back4app 将处理从创建应用程序层到设置数据库、安全、扩展等一切事务。
完成后,您将被重定向到应用程序的数据库界面。
更改节点版本
默认情况下,Back4app 应用程序使用 Parse v4.10.4。该版本的 Parse 服务器使用 Node v14,与OpenAI 的库不兼容,后者需要 Node v18 以上。
让我们升级 Parse 服务器版本。
首先,选择侧边栏上的 “服务器设置”,然后导航到 “管理 Parse 服务器 “设置,如下图所示。
将解析服务器版本更改为5.2.3
或更新版本。
点击 “保存”,等待几分钟让 Back4app 升级服务器版本。
要验证 Node.js 版本,您可以定义以下Cloud Code函数:
Parse.Cloud.define("getNodeVersion", async(request) => {
return process.version;
});
然后,通过内置的 “API > 控制台 > REST”,向functions/getNodeVersion
发送POST
请求,触发它。
OpenAI API 密钥
接下来,让我们创建一个 OpenAI API 密钥,以便从后台连接 OpenAI。
导航至OpenAI 的仪表板,点击 “默认项目”,然后点击 “创建项目”,创建一个新项目。
给你的项目起一个描述性的名字–我用 “back4app”。然后,点击 “创建”。
OpenAI 会自动切换到新创建的项目。
接下来,在导航栏中选择 “控制面板”,然后在侧边栏中选择 “API 密钥”,进入 “API 密钥 “部分。单击 “创建新密匙 “开始 API 密匙创建过程。
将所有设置保留为默认值,然后点击 “创建密钥 “确认密钥创建。
请注意密匙,因为您只能看到一次。
请像对待密码一样安全地对待您的秘钥。如果被他人获取,可能会产生大量 OpenAI 费用。此外,我建议设置使用限制。
设置环境变量
为了避免在源代码中泄露秘密密钥,我们将把它添加为一个环境变量。
导航至 “服务器设置 > 环境变量 > 设置”。
然后像在.env文件中一样设置OPENAI_API_KEY
环境变量:
OPENAI_API_KEY=<your_openai_api_key>
確保將 <your_openai_api_key> 替換為上一個步驟中的 OpenAI 金鑰。
最后,点击 “保存 “保存环境变量。
现在,您可以像这样通过Cloud Code功能访问秘钥:
const secretKey = process.env.OPENAI_API_KEY;
console.log(secretKey);
// sk-proj-...
Cloud Code
为了实现后台逻辑,我们将使用Cloud Code函数。Cloud Code函数是 Parse Server 的一项强大功能,能让开发人员运行自定义的服务器端 JavaScript 代码。
它们可以通过 REST 或 Parse SDK 触发,也可以定时调度。
查看什么是无服务器函数?了解有关函数即服务的更多信息。
首先,在侧边栏选择 “Cloud Code > 功能与虚拟主机”,访问Cloud Code。
你会发现屏幕被分成了两部分。左边是目录结构,右边是 JavaScript 代码编辑器。默认情况下,有两个目录:
- 云文件夹,用于部署Cloud Code功能和其他自定义代码
- 用于部署静态内容(如图像、视频、图标)的公共文件夹
安装 OpenAI 库
为了与 OpenAI API 交互,我们将安装OpenAI JavaScript 库。
使用Cloud Code安装 NPM 软件包非常简单。为此,请在云文件夹中创建一个package.json文件,列出要安装的软件包。
// cloud/package.json
{
"dependencies": {
"openai": "^4.51.0"
}
}
要获取最新的
openai
软件包版本,请查看 NPM 软件包页面。
然后点击屏幕右上方的 “部署”。
如果安装成功,你应该会在云文件夹中看到一个新生成的package-lock.json。该锁定文件应包含openai
软件包。
Cloud Code功能
接下来,我们来处理Cloud Code功能。
我们将创建以下四个函数:
setup()
将创建一个虚拟助手,并将其配置保存到数据库中createThread()
将创建一个新的虚拟助理线程deleteThread(threadId)
将删除现有的虚拟助理线程addMessage(threadId, message)
将向线程添加一条消息并生成响应
将以下代码粘贴到cloud/main.js 中:
// cloud/main.js
const OpenAI = require("openai");
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const ASSISTANT_INITIAL_MESSAGE = "Hi, my name is Math Bot. How can I help you?";
const ASSISTANT_SETTINGS = {
name: "Math Bot",
instructions: "Very smart math bot that answers math questions.",
model: "gpt-3.5-turbo-0125",
tools: [],
};
Parse.Cloud.define("setup", async (request) => {
const Assistant = Parse.Object.extend("Assistant");
const query = await new Parse.Query(Assistant);
const count = await query.count();
// Check if virtual assistant already exists
if (count !== 0) {
throw new Parse.Error(
Parse.Error.VALIDATION_ERROR,
"A virtual assistant already exists!",
);
}
// Use OpenAI's API to create an assistant
const openAssistant = await openai.beta.assistants.create(
ASSISTANT_SETTINGS,
);
// Store the assistant in Back4app database
const assistant = new Assistant();
for (const key in ASSISTANT_SETTINGS) {
assistant.set(key, ASSISTANT_SETTINGS[key]);
}
assistant.set("initialMessage", ASSISTANT_INITIAL_MESSAGE);
assistant.set("assistantId", openAssistant.id);
await assistant.save();
return assistant.get("assistantId");
});
Parse.Cloud.define("createThread", async (request) => {
const thread = await openai.beta.threads.create();
return thread.id;
});
Parse.Cloud.define("deleteThread", async (request) => {
const _threadId = request.params.threadId;
return await openai.beta.threads.del(_threadId);
});
Parse.Cloud.define("addMessage", async (request) => {
const _threadId = request.params.threadId;
const _message = request.params.message;
// Verify all the parameters are provided
if (!_threadId || !_message) {
throw new Parse.Error(
Parse.Error.VALIDATION_ERROR,
"You need to provide: threadId & message.",
);
}
const Assistant = Parse.Object.extend("Assistant");
const query = await new Parse.Query(Assistant);
const count = await query.count();
// Check if a virtual assistant exists
if (count === 0) {
throw new Parse.Error(
Parse.Error.VALIDATION_ERROR,
"A virtual assistant does not exist!",
);
}
const assistant = await new Parse.Query(Assistant).first();
const assistantId = assistant.get("assistantId");
// Get the thread, add the message, and generate a response
let buffer = "";
const message = await openai.beta.threads.messages.create(
_threadId, {role: "user", content: _message},
);
let run = await openai.beta.threads.runs.createAndPoll(
_threadId, {assistant_id: assistantId},
);
// Add the last message to the buffer
if (run.status === "completed") {
const messages = await openai.beta.threads.messages.list(run.thread_id);
buffer += messages.data[0].content[0].text.value;
} else {
console.error("Failed to run the assistant.");
}
return buffer;
});
代码概览
- 代码导入并初始化 OpenAI 库。
- 然后定义助手设置(如
名称
、说明
和初始信息
)。 - 代码提供了四种Cloud Code功能,如上文所述。
- 在
setup()
中,我们获取助手和线程,然后向线程添加一条消息。然后,我们使用运行使用助手生成响应。
测试Cloud Code功能
在进入前台之前,我们必须确保后台能按预期运行。
为便于测试,我们将使用 Back4app 的内置控制台。导航至侧边栏上的 “API > Console > REST”。
首先,触发setup()
函数:
- 请求类型
POST
- 哪个端点:
函数/设置
- 使用万能钥匙:
假
- 运行方式:留空
- 查询参数:留空
这将创建一个新的助手并将其保存到数据库中。如果导航到数据库视图,就会看到助手
类现在有一行。
接下来,让我们测试一下对话端点。
POST
到functions/createThread
以创建线程。注意线程 ID。- 向
functions/addMessage
发送
一个问题,并输入以下参数{"threadId":"", "信息":"什么是 2+2?"}
。验证生成的响应是否正确。 - 使用以下参数
{"threadId":""}
删除线程。
很好,后台似乎运行良好!
前端
在本教程中,我们将引导一个新的 React 项目,安装 TailwindCSS,实现用户界面,设置 Parse SDK,并实现所需的逻辑。
创建 Vite 应用程序
首先,使用 React 模板引导一个新的Vite项目:
$ npm create vite@latest frontend -- --template react
将目录更改为新创建的文件夹并安装依赖项:
$ cd frontend
$ npm install
运行开发服务器:
$ npm run dev
打开您最喜欢的网络浏览器并导航至http://localhost:5174/。您应该会看到默认的 Vite + React 登陆页面。
TailwindCSS
为了简化我们的工作,我们将使用 TailwindCSS,这是一个以实用工具为先的 CSS 框架,让你无需离开 HTML 就能快速创建自定义设计。
该框架提供了高度可定制和响应式的样式设计方法。
请按照官方指南安装 TailwindCSS。
意见
接下来,让我们来实现用户界面。
为了使代码更有条理,我们首先要创建几个组件。首先,在src文件夹中创建一个组件文件夹,并在其中放置以下三个文件:
在此基础上,在src/assets文件夹中添加avatar.png。
此时,您的目录结构应该如下所示:
frontend/
└── src/
├── components/
│ ├── Spinner.jsx
│ ├── AssistantMessage.jsx
│ └── UserMessage.jsx
├── assets/
│ └── avatar.png
└── ...
接下来,在src/App.jsx 中输入以下代码:
// src/App.jsx
import {useEffect, useState} from "react";
import AssistantMessage from "./components/AssistantMessage.jsx";
import UserMessage from "./components/UserMessage.jsx";
import Spinner from "./components/Spinner.jsx";
function App() {
const [initialMessage, setInitialMessage] = useState(undefined);
const [loading, setLoading] = useState(true);
const [threadId, setThreadId] = useState(undefined);
const [message, setMessage] = useState("");
const [messages, setMessages] = useState([
{role: "assistant", content: "Welcome! How can I help you today?"},
{role: "user", content: "What is 2+2?"},
{role: "assistant", content: "2+2 is 4."},
]);
async function getInitialMessage() {
// TODO: get the initial message
}
async function reset(message) {
// TODO: create a new thread
}
useEffect(() => {
setLoading(false);
// TODO: get the initial message
}, []);
function onSubmit(event) {
// TODO: add the message to the thread and generate response
}
function onNewThread() {
// TODO: create a new thread
}
return (
<main className="container mx-auto py-8 px-8 md:px-32 lg:px-64 h-[100vh]">
<div className="pb-12 space-y-2">
<h1 className="text-3xl font-bold">
back4app-openai-virtual-assistant
</h1>
<p>
An AI-powered virtual assistant built using OpenAI + Back4app.
</p>
</div>
<div className="space-y-2">
{messages.map((message, index) => {
switch (message.role) {
case "assistant":
return <AssistantMessage key={index} content={message.content}/>;
case "user":
return <UserMessage key={index} content={message.content}/>;
default:
return <></>;
}
})}
{loading && <Spinner/>}
</div>
<form className="inline-block flex flex-row pt-12" onSubmit={onSubmit}>
<input
type="text"
className="w-full p-2 border border-gray-300 rounded-md outline-none"
placeholder="Type a message..."
value={message}
onChange={(event) => setMessage(event.target.value)}
/>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-600 text-white p-2 px-3 rounded-md ml-2"
>
Send
</button>
<button
type="button"
className="bg-green-500 text-white p-2 px-3 rounded-md ml-2"
onClick={onNewThread}
>
New
</button>
</form>
</main>
);
}
export default App;
这段代码创建了一个简单的用户界面,用于从消息
状态渲染消息
。此外,它还提供了一个文本框和一个按钮,用于向虚拟助手提交消息。
再次启动开发服务器并导航至http://localhost:5174/。您应该可以看到类似 ChatGPT 的用户界面。
安装 Parse SDK
要连接到基于 Back4app 的后端,我们将使用Parse SDK。
Parse SDK 使开发人员能够与基于 Parse 的后端无缝交互,从而实现高效的数据查询、用户身份验证、通知、实时数据处理等功能。
首先,通过 npm 安装 Parse:
$ npm install parse
接下来,导航到您的 Back4app 应用程序。选择侧边栏上的 “应用程序设置 > 安全性和密钥”。然后,记下 “应用程序 ID “和 “JavaScript 密钥”。
与其在源代码中公开秘钥,不如在项目根目录下创建.env文件:
VITE_BACK4APP_APPLICATION_ID=<your_back4app_application_id>
VITE_BACK4APP_JAVASCRIPT_KEY=<your_back4app_javascript_key>
确保用实际密钥替换变量。
接下来,导航到src/main.jsx,使用环境变量初始化 Parse:
// src/main.jsx
// ...
import Parse from "parse/dist/parse.min.js";
// Initialize Parse SDK using the Back4app API keys
Parse.initialize(
import.meta.env.VITE_BACK4APP_APPLICATION_ID,
import.meta.env.VITE_BACK4APP_JAVASCRIPT_KEY,
);
Parse.serverURL = "https://parseapi.back4app.com/";
ReactDOM.createRoot(document.getElementById("root")).render(
// ...
);
现在,您可以通过导入 Parse 实例在所有视图中使用它:
import Parse from "parse/dist/parse.min.js";
逻辑
最后,将src/App.jsx中的 React 钩子替换为以下内容:
// src/App.jsx
// ...
import Parse from "parse/dist/parse.min.js";
function App() {
// ...
async function getInitialMessage() {
const Assistant = Parse.Object.extend("Assistant");
const assistant = await new Parse.Query(Assistant).first();
return assistant.get("initialMessage");
}
async function reset(message) {
setMessages([
{role: "assistant", content: message},
]);
setMessage("");
const threadId = await Parse.Cloud.run("createThread");
setThreadId(threadId);
}
useEffect(() => {
(async () => {
const assistantInitialMessage = await getInitialMessage();
setInitialMessage(assistantInitialMessage);
await reset(assistantInitialMessage);
setLoading(false);
})();
}, []);
function onSubmit(event) {
event.preventDefault();
if (loading || !threadId || !message) return;
setMessages([
...messages,
{role: "user", content: message},
]);
setMessage("");
setLoading(true);
(async () => {
const response = await Parse.Cloud.run("addMessage", {threadId, message});
setMessages(messages => [
...messages,
{role: "assistant", content: response},
]);
setLoading(false);
})();
}
function onNewThread() {
if (loading || !threadId) return;
setLoading(true);
(async () => {
await reset(initialMessage);
setLoading(false);
})();
}
return (
// ...
);
}
export default App;
这段代码会处理信息并将其提交到后台。它还允许用户通过点击按钮创建新线程。
瞧!前台现在已经完成。
重新启动开发服务器并测试应用程序,确保一切正常。
如果您想部署助手的前端,请查看如何托管 React 应用程序?
结论
这篇文章教给你构建个性化人工智能助手所需的一切知识。
现在,您应该可以使用OpenAI 的助手 API和Back4app来支持和部署您的人工智能助手了、
最终源代码可在back4app-openai-virtual-assistantGitHub 代码库中获取。