如何使用 React 和 OpenAI API 构建和部署 ChatGPT 克隆应用程序
已发表: 2023-03-13随着聊天机器人和虚拟助手的使用不断增长,许多企业和开发人员正在寻找创建自己的人工智能聊天机器人的方法。 ChatGPT 就是这样一种由 OpenAI 创建的聊天机器人,它能够进行类似人类的对话并回答范围广泛的问题。
你要建造什么
在本教程中,您将学习如何使用 React 和 OpenAI API 构建 ChatGPT 克隆应用程序。 如果您想在周末尝试一个有趣且引人入胜的项目,这是深入研究 React 和 OpenAI 的绝佳机会。
您还将了解如何直接从 GitHub 存储库部署到 Kinsta 的应用程序托管平台,该平台提供免费的.kinsta.app域,让您的项目快速上线。 借助 Kinsta 的免费试用版和 Hobby Tier,您无需任何费用即可轻松上手。
这是 ChatGPT 克隆应用程序的现场演示。
如果你想更仔细地检查这个项目,你可以访问它的 GitHub 存储库。
或者,您也可以克隆 React 应用程序启动项目,其中包含样式、Font Awesome CDN 链接、OpenAI 包和基本结构等基本元素,以帮助您入门。
要求/先决条件
本教程旨在提供“跟进”体验。 因此,建议您使用以下工具轻松编写代码:
- 对 HTML、CSS 和 JavaScript 的基本理解
- 对 React 有一定的了解
- 在您的计算机上安装 Node.js 和 npm(节点包管理器)或纱线
什么是 OpenAI API?
OpenAI API 是一个基于云的平台,允许开发人员通过 API 访问 OpenAI 的语言模型,例如 GPT-3。 它允许开发人员在他们的应用程序中添加自然语言处理功能,如文本完成、情感分析、摘要和翻译,而无需开发和训练他们的模型。
要使用 OpenAI API,开发人员必须在 OpenAI 网站上创建一个帐户并获取 API 密钥。 API 密钥用于验证 API 请求和跟踪使用情况。
获得 API 密钥后,开发人员可以使用 API 向语言模型提交文本并接收响应。
为什么反应?
React 是一个流行的 JavaScript 库,用于构建用户界面。 根据 2022 Stack Overflow 开发者调查,它是第二大最常用的 Web 技术,市场份额为 42.62%。
React 允许开发人员创建表示用户界面不同部分的声明式组件。 这些组件是使用称为 JSX 的语法定义的,它是 JavaScript 和 HTML 的组合。
由于其庞大的组件库和工具包生态系统,开发人员可以轻松地使用和集成 OpenAI API 等 API,以构建复杂的聊天界面,这使其成为构建 ChatGPT 克隆应用程序的绝佳选择。
如何设置你的 React 开发环境
安装 React 或创建 React 项目的最佳方式是使用 create-react-app 安装它。 一个先决条件是在您的计算机上安装 Node.js。 要确认您已安装 Node,请在终端中运行以下命令。
node -v
如果它提出一个版本,那么它就存在。 使用npx需要确保你的Node版本不低于v14.0.0,你的NPM版本不低于v5.6; 否则,您可能需要通过运行npm update -g
来更新它。 了解 npm 后,您现在可以通过运行以下命令来设置 React 项目:
npx create-react-app chatgpt-clone
注意: “chatgpt-clone”是我们正在创建的应用程序名称,但您可以将其更改为您选择的任何名称。
安装过程可能需要几分钟。 成功后,您可以导航到该目录并安装 Node.js OpenAI 包,使用以下命令可以方便地从 Node.js 访问 OpenAI API:
npm install openai
您现在可以运行npm start
以在localhost:3000上查看您的应用程序。
当使用create-react-app
命令创建 React 项目时,它会自动搭建一个文件夹结构。 与您相关的主要文件夹是src
文件夹,这是进行开发的地方。 默认情况下,此文件夹包含许多文件,但您应该只关心App.js 、 index.js和index.css文件。
- App.js : App.js文件是 React 应用程序中的主要组件。 它通常表示呈现应用程序中所有其他组件的顶级组件。
- index.js :此文件是 React 应用程序的入口点。 它是打开应用程序时加载的第一个文件,负责将App.js组件呈现给浏览器。
- index.css :此文件负责定义 React 应用程序的整体样式和布局。
如何使用 React 和 OpenAI API 构建 ChatGPT 克隆
ChatGPT 克隆应用程序将由两个组件组成,以使应用程序更易于理解和维护。 这两个组件是:
- 表单部分:此组件包括一个文本区域字段和一个供用户与聊天机器人交互的按钮。
- Answer Section :问题和相应的答案将存储在一个数组中并显示在该部分中。 您将按时间顺序遍历数组,首先显示最新的。
设置 ChatGPT 克隆应用程序
在本教程中,让我们首先构建应用程序界面,然后您可以实现功能,以便您的应用程序与 OpenAI API 交互。 首先创建您将在本教程中使用的两个组件。 为了进行适当的组织,您将在存储所有组件的src文件夹中创建一个组件文件夹。
表单部分组件
这是一个简单的表单,由一个textarea
和一个提交button
组成。
// components/FormSection.jsx const FormSection = () => { return ( <div className="form-section"> <textarea rows="5" className="form-control" placeholder="Ask me anything..." ></textarea> <button className="btn"> Generate Response </button> </div> ) } export default FormSection;
这是将表单导入App.js文件时预期的样子:
答案部分组件
此部分将显示所有问题和答案。 当您将此部分也导入App.js文件时,这就是该部分的样子。
您将从数组和循环中获取这些问题和答案,使您的代码更易于阅读和维护。
// components/AnswerSection.jsx const AnswerSection = () => { return ( <> <hr className="hr-line" /> <div className="answer-container"> <div className="answer-section"> <p className="question">Who is the founder of OpenAi?</p> <p className="answer">OpenAI was founded in December 2015 by Elon Musk, Sam Altman, Greg Brockman, Ilya Sutskever, Wojciech Zaremba, and John Schulman.</p> <div className="copy-icon"> <i className="fa-solid fa-copy"></i> </div> </div> </div> </> ) } export default AnswerSection;
主页
您现在已经创建了两个组件,但是当您运行您的应用程序时不会出现任何内容,因为您需要将它们导入您的App.js文件中。 对于此应用程序,您将不会实现任何形式的路由,这意味着App.js文件将用作您的应用程序的主组件/页面。
在导入组件之前,您可以添加一些内容,例如应用程序的标题和描述。
// App.js import FormSection from './components/FormSection'; import AnswerSection from './components/AnswerSection'; const App = () => { return ( <div> <div className="header-section"> <h1>ChatGPT CLONE </h1> <p> I am an automated question and answer system, designed to assist you in finding relevant information. You are welcome to ask me any queries you may have, and I will do my utmost to offer you a reliable response. Kindly keep in mind that I am a machine and operate solely based on programmed algorithms. </p> </div> <FormSection /> <AnswerSection /> </div> ); }; export default App;
在上面的代码中,这两个组件被导入并添加到应用程序中。 当您运行您的应用程序时,您的应用程序将如下所示:
添加功能并集成 OpenAI API
您现在拥有应用程序的用户界面。 下一步是使应用程序正常运行,以便它可以与 OpenAI API 交互并获得响应。 首先,您需要在提交时从表单中获取值,因为它将用于查询 OpenAI API。
从表单中获取数据
在 React 中,存储和更新数据的最佳方式是使用状态。 在功能组件中, useState()
钩子用于处理状态。 您可以创建一个状态,将表单中的值分配给该状态,并在其值发生变化时更新它。 让我们首先将useState()
挂钩导入FormSection.jsx组件,然后创建一个状态来存储和更新newQuestions
。
// components/FormSection.jsx import { useState } from 'react'; const FormSection = ({ generateResponse }) => { const [newQuestion, setNewQuestion] = useState(''); return ( // Form to submit a new question ) } export default FormSection;
接下来,您可以将textarea
字段的值分配给状态,并创建一个onChange()
事件以在输入值更改时更新状态:
<textarea rows="5" className="form-control" placeholder="Ask me anything..." value={newQuestion} onChange={(e) => setNewQuestion(e.target.value)} ></textarea>
最后,您可以创建一个onClick()
事件,以便在单击提交按钮时加载一个函数。 该方法将在App.js文件中创建,并以newQuestion
和setNewQuestion
值作为参数作为 props 传递到FormSection.jsx组件中。
<button className="btn" onClick={() => generateResponse(newQuestion, setNewQuestion)}> Generate Response </button>
您现在已经创建了一个状态来存储和更新表单值,添加了一个作为道具从App.js文件传递并处理点击事件的方法。 这是最终代码的样子:
// components/FormSection.jsx import { useState } from 'react'; const FormSection = ({ generateResponse }) => { const [newQuestion, setNewQuestion] = useState(''); return ( <div className="form-section"> <textarea rows="5" className="form-control" placeholder="Ask me anything..." value={newQuestion} onChange={(e) => setNewQuestion(e.target.value)} ></textarea> <button className="btn" onClick={() => generateResponse(newQuestion, setNewQuestion)}> Generate Response </button> </div> ) } export default FormSection;
下一步将是在App.js文件中创建一个方法来处理与 OpenAI API 交互的整个过程。
与 OpenAI API 交互
要在 React 应用程序中与 OpenAI API 交互并获取 API 密钥,您必须创建一个 OpenAI API 帐户。 您可以使用您的谷歌帐户或电子邮件在 OpenAI 网站上注册一个帐户。 要生成 API 密钥,请单击网站右上角的个人; 会出现一些选项; 单击查看 API 密钥。
单击“创建新密钥”按钮,将密钥复制到某处,就像您在此应用程序中使用它与 OpenAI 交互一样。 您现在可以通过导入 openai 包(您已经安装)以及配置方法来继续初始化 OpenAI。 然后使用生成的密钥创建一个配置,并使用它来初始化 OpenAI。
// src/App.js import { Configuration, OpenAIApi } from 'openai'; import FormSection from './components/FormSection'; import AnswerSection from './components/AnswerSection'; const App = () => { const configuration = new Configuration({ apiKey: process.env.REACT_APP_OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); return ( // Render FormSection and AnswerSection ); }; export default App;
在上面的代码中,OpenAI API 密钥作为环境变量存储在.env文件中。 您可以在应用程序的根文件夹中创建一个.env文件,并将密钥存储到变量REACT_APP_OPENAI_API_KEY
中。
// .env REACT_APP_OPENAI_API_KEY = sk-xxxxxxxxxx…
您现在可以继续在App.js文件中创建generateResponse
方法,并传入您已创建的表单中预期的两个参数,以处理请求并从 API 获取响应。
// src/App.js import FormSection from './components/FormSection'; import AnswerSection from './components/AnswerSection'; const App = () => { const generateResponse = (newQuestion, setNewQuestion) => { // Set up OpenAI API and handle response }; return ( // Render FormSection and AnswerSection ); }; export default App;
您现在可以向 OpenAI API 发送请求。 OpenAI API 可以执行许多操作,例如问答 (Q&A)、语法纠正、翻译等等。 对于这些操作中的每一个,选项都是不同的。 例如,Q&A 的引擎值为text-davinci-00
,而 SQL 翻译的引擎值为code-davinci-002
。 请随时查看 OpenAI 示例文档以了解各种示例及其选项。
对于本教程,我们只使用问答,这是该选项的样子:
{ model: "text-davinci-003", prompt: "Who is Obama?", temperature: 0, max_tokens: 100, top_p: 1, frequency_penalty: 0.0, presence_penalty: 0.0, stop: ["\"], }
注意:我更改了提示值。
提示是从表单发送的问题。 这意味着您需要从作为参数传递给generateResponse
方法的表单输入中接收它。 为此,您将定义选项,然后使用扩展运算符创建一个包含提示的完整选项:
// src/App.js import { Configuration, OpenAIApi } from 'openai'; import FormSection from './components/FormSection'; import AnswerSection from './components/AnswerSection'; const App = () => { const configuration = new Configuration({ apiKey: process.env.REACT_APP_OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); const generateResponse = async (newQuestion, setNewQuestion) => { let options = { model: 'text-davinci-003', temperature: 0, max_tokens: 100, top_p: 1, frequency_penalty: 0.0, presence_penalty: 0.0, stop: ['/'], }; let completeOptions = { ...options, prompt: newQuestion, }; }; return ( // Render FormSection and AnswerSection ); }; export default App;
至此,剩下的就是通过createCompletion
方法向 OpenAI 发送请求以获得响应。
// src/App.js import { Configuration, OpenAIApi } from 'openai'; import FormSection from './components/FormSection'; import AnswerSection from './components/AnswerSection'; import { useState } from 'react'; const App = () => { const configuration = new Configuration({ apiKey: process.env.REACT_APP_OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); const [storedValues, setStoredValues] = useState([]); const generateResponse = async (newQuestion, setNewQuestion) => { let options = { model: 'text-davinci-003', temperature: 0, max_tokens: 100, top_p: 1, frequency_penalty: 0.0, presence_penalty: 0.0, stop: ['/'], }; let completeOptions = { ...options, prompt: newQuestion, }; const response = await openai.createCompletion(completeOptions); console.log(response.data.choices[0].text); }; return ( // Render FormSection and AnswerSection ); }; export default App;
在上面的代码中,答案的文本将显示在您的控制台上。 随时通过提出任何问题来测试您的应用程序。 最后一步是创建一个状态来保存问题和答案数组,然后将此数组作为道具发送到AnswerSection组件中。 这就是App.js最终代码的样子:
// src/App.js import { Configuration, OpenAIApi } from 'openai'; import FormSection from './components/FormSection'; import AnswerSection from './components/AnswerSection'; import { useState } from 'react'; const App = () => { const configuration = new Configuration({ apiKey: process.env.REACT_APP_OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); const [storedValues, setStoredValues] = useState([]); const generateResponse = async (newQuestion, setNewQuestion) => { let options = { model: 'text-davinci-003', temperature: 0, max_tokens: 100, top_p: 1, frequency_penalty: 0.0, presence_penalty: 0.0, stop: ['/'], }; let completeOptions = { ...options, prompt: newQuestion, }; const response = await openai.createCompletion(completeOptions); if (response.data.choices) { setStoredValues([ { question: newQuestion, answer: response.data.choices[0].text, }, ...storedValues, ]); setNewQuestion(''); } }; return ( <div> <div className="header-section"> <h1>ChatGPT CLONE </h1> <p> I am an automated question and answer system, designed to assist you in finding relevant information. You are welcome to ask me any queries you may have, and I will do my utmost to offer you a reliable response. Kindly keep in mind that I am a machine and operate solely based on programmed algorithms. </p> </div> <FormSection generateResponse={generateResponse} /> <AnswerSection storedValues={storedValues} /> </div> ); }; export default App;
您现在可以编辑AnswerSection组件,使其从App.js接收 props 值并使用 JavaScript Map()
方法查看storedValues
数组:
// components/AnswerSection.jsx const AnswerSection = ({ storedValues }) => { return ( <> <hr className="hr-line" /> <div className="answer-container"> {storedValues.map((value, index) => { return ( <div className="answer-section" key={index}> <p className="question">{value.question}</p> <p className="answer">{value.answer}</p> <div className="copy-icon"> <i className="fa-solid fa-copy"></i> </div> </div> ); })} </div> </> ) } export default AnswerSection;
当您运行您的应用程序并通过提问对其进行测试时,答案将显示在下方。 但是您会注意到复制按钮不起作用。 您需要向按钮添加一个onClick()
事件,以便它触发一个方法来处理该功能。 您可以使用navigator.clipboard.writeText()
方法来处理该功能。 这就是AnswerSection组件现在的样子:
// components/AnswerSection.jsx const AnswerSection = ({ storedValues }) => { const copyText = (text) => { navigator.clipboard.writeText(text); }; return ( <> <hr className="hr-line" /> <div className="answer-container"> {storedValues.map((value, index) => { return ( <div className="answer-section" key={index}> <p className="question">{value.question}</p> <p className="answer">{value.answer}</p> <div className="copy-icon" onClick={() => copyText(value.answer)} > <i className="fa-solid fa-copy"></i> </div> </div> ); })} </div> </> ) } export default AnswerSection;
当您运行您的应用程序时,您的 ChatGPT 克隆应用程序将完美运行。 您现在可以部署您的应用程序以在线访问它并与朋友分享。
如何将 React 应用程序部署到 Kinsta
构建此应用程序并将其留在本地计算机上是不够的。 您需要在线共享它,以便其他人可以访问它。 让我们看看如何使用 GitHub 和 Kinsta 来做到这一点。
将代码推送到 GitHub
要将代码推送到 GitHub,您可以使用 Git 命令,这是管理代码更改、项目协作和维护版本历史记录的可靠且高效的方法。
推送代码的第一步是创建一个新的存储库,方法是登录您的 GitHub 帐户,单击屏幕右上角的+按钮,然后从下拉菜单中选择新建存储库。
为您的存储库命名,添加描述(可选),然后选择您希望它是公开的还是私有的。 单击创建存储库以创建它。
创建存储库后,请确保从存储库的主页获取存储库 URL,您需要使用该 URL 将代码推送到 GitHub。
打开您的终端或命令提示符并导航到包含您的项目的目录。 一条一条运行以下命令,将您的代码推送到您的 GitHub 存储库:
git init git add . git commit -m "my first commit" git remote add origin [repository URL] git push -u origin master
git init
初始化本地 Git 存储库git add .
将当前目录及其子目录中的所有文件添加到新的 Git 存储库中。 git commit -m "my first commit"
将更改提交到存储库并带有一条简短消息。 git remote add origin [repository URL]
将repository URL设置为远程仓库, git push -u origin master
将代码推送到master分支中的远程仓库(origin)。
将您的 ChatGPT Clone React 应用程序部署到 Kinsta
要将您的存储库部署到 Kinsta,请执行以下步骤:
- 在 My Kinsta 仪表板上登录或创建您的 Kinsta 帐户。
- 单击左侧边栏上的应用程序,然后单击添加服务。
- 从下拉菜单中选择应用程序以将 React 应用程序部署到 Kinsta。
- 从出现的模式中选择您希望部署的存储库。 如果您有多个分支,您可以选择要部署的分支并为应用程序指定一个名称。 在 25 个可用数据中心位置中选择一个,Kinsta 将自动检测启动命令。
- 最后,将 API 密钥推送到 GitHub 等公共主机是不安全的,它是在本地作为环境变量添加的。 托管时,您还可以使用相同的变量名称和键作为其值将其添加为环境变量。
您的应用程序将开始部署,几分钟后,将提供一个链接以访问您的应用程序的已部署版本。 在这种情况下,这是https://chatgpt-clone-g9q10.kinsta.app/注意:您可以启用自动部署,因此每当您更改代码库并将其推送到 GitHub 时,Kinsta 都会重新部署您的应用程序。
概括
OpenAI API 可用于构建广泛的潜在应用程序,从客户支持和个人助理到语言翻译和内容创建。
在本教程中,您学习了如何使用 React 和 OpenAI 构建 ChatGPT 克隆应用程序。 您可以将此应用程序/功能集成到其他应用程序中,为用户提供类似人类的对话体验。
关于 OpenAI API 可以做什么以及如何改进这个克隆应用程序,还有更多内容。 例如,您可以实现本地存储,这样即使您刷新浏览器,以前的问题和答案也不会消失。
通过 Kinsta 的免费试用和 Hobby Tier,您可以轻松开始使用我们的应用程序托管而无需支付任何费用。 那么为什么不尝试一下,看看你能创造出什么?
在下面的评论中分享您的项目和经验。