31行代码,使用 ChatGPT API 和 Node 创建 CLI 聊天机器人

946 阅读6分钟

使用 ChatGPT API 和 Node.JS 创建 CLI 聊天机器人

原文: philna.sh/blog/2023/0…

ChatGPT 风靡全球,最近 OpenAI 发布了 ChatGPT API。
我花了一些时间在浏览器中使用 ChatGPT,但真正了解这些新功能的最佳方式是尝试用它构建一些东西。
有了ChatGPT API,现在正是开干的时候。

代码

我用了31行代码构建了这个小机器人。
构建了这个小机器人后,我对 这个API的能力 感到兴奋。

这里是全部代码,下面我将逐步解释。

import { createInterface } from "node:readline/promises";  
import { stdin as input, stdout as output, env } from "node:process";  
import { Configuration, OpenAIApi } from "openai";  
  
const configuration = new Configuration({ apiKey: env.OPENAI_API_KEY });  
const openai = new OpenAIApi(configuration);  
const readline = createInterface({ input, output });  
  
const chatbotType = await readline.question(  
    "What type of chatbot would you like to create? "  
);  
const messages = [{ role: "system", content: chatbotType }];  
let userInput = await readline.question("Say hello to your new assistant.\n\n");  
  
while (userInput !== ".exit") {  
    messages.push({ role: "user", content: userInput });  
    try {  
        const response = await openai.createChatCompletion({  
            messages,  
            model: "gpt-3.5-turbo",  
        });  

        const botMessage = response.data.choices[0].message;  
        if (botMessage) {  
            messages.push(botMessage);  
            userInput = await readline.question("\n" + botMessage.content + "\n\n");  
        } else {  
            userInput = await readline.question("\nNo response, try asking again\n");  
        }  
    } catch (error) {  
        console.log(error.message);  
        userInput = await readline.question("\nSomething went wrong, try asking again\n");  
    }  
}  
  
readline.close();  

可以在原文看效果

让我们深入这段代码。

开发一个ChatBot

你需要一个OpenAI平台账号来和chatGPT API进行交互。
一旦你注册完毕,从你的账户dashboard 创建一个API key

你需要安装Node,然后装一下openai这个npm包。

通过以下代码创建初始CLI项目。

mkdir chatgpt-cli  
cd chatgpt-cli  
npm init --yes  

安装openai模块:

npm install openai  

打开package.json,添加"type": "module"。
这样我们可以把这个程序当做一个ES module,可以ES的使用top level await。

创建一个index.js文件,在编辑器打开。

和openai的API进行交互

代码分为两部分,处理命令行上的输入和输出 以及处理 OpenAI API。
让我们先看看 OpenAI API 是如何工作的。

首先我们从 openai 模块导入两个类,ConfigurationOpenAIApi
Configuration 类将用于创建保存 API key的配置,
然后您可以使用该配置创建 OpenAIApi 客户端。

import { env } from "node:process";  
import { Configuration, OpenAIApi } from "openai";  
  
const configuration = new Configuration({ apiKey: env.OPENAI_API_KEY });  
const openai = new OpenAIApi(configuration);  

在本例中,我们在环境变量中存储 API key,并使用 env.OPENAI_API_ KEY 读取它。

为了与 API 交互,我们现在使用 OpenAI 客户端为我们创建聊天completions
OpenAI 的文本生成模型实际上并不与你交谈,而是接收输入并在输入后生成听起来合理的文本来 接上输入的内容,即completions。
(即它不对话,它只接话,它接的话叫做completions)。
使用 ChatGPT,模型被配置为接收一个消息列表,然后接一个completion来完成对话。
该系统中的消息可以来自 3 个不同角色,即“system”、“user”和“assistant”。
“assistant”是 ChatGPT 本身,“user”是交互的人,system允许程序(或用户,正如我们将在本例中看到的那样)提供定义助手行为方式的指令。
通过system prompts更改助手的行为方式是最有趣的事情之一,它允许您创建不同类型的assistants。

使用如上配置的 openai 对象,我们可以创建消息发送给助手并得到如下响应:

const messages = [  
    { role: "system", content: "You are a helpful assistant" },  
    { role: "user", content: "Can you suggest somewhere to eat in the centre of London?" }  
];  
const response = await openai.createChatCompletion({  
    messages,  
    model: "gpt-3.5-turbo",  
});  
console.log(response.data.choices[0].message);  
// => "Of course! London is known for its diverse and delicious food scene..."  

随着对话的进行,我们可以将用户的问题和助手的回复添加到消息数组中。
这个数组我们会随每个请求一起发送。
这就给了机器人对话的上下文,使其可以回答的更好。

要创建一个 CLI程序,我们让这段程序在接收终端上用户的输入即可。

和终端交互

Node.js 提供了 Readline 模块,可以轻松接收输入并将输出写到streams。
要和终端交互,有俩streams, 分别是 stdinstdout

我们可以从 node:process 模块中导入 stdinstdout
将它们重命名为 inputoutput 以使其更易于与 Readline 一起使用。
我们还从 node:readline 导入 createInterface 函数。

import { createInterface } from "node:readline/promises";  
import { stdin as input, stdout as output } from "node:process";  

然后我们将inputoutput流传递给 createInterface,这为我们提供了一个对象,
我们可以使用该对象 输出内容到终端 以及 从终端读取内容。
从终端读用户输入时,可以用question function函数提个问题:

const readline = createInterface({ input, output });  
  
const chatbotType = await readline.question(  
    "What type of chatbot would you like to create? "  
);  

上面的代码连接了inputoutput流。然后使用 readline 对象将问题发布到终端输出并返回一个promise。
当用户通过写入终端并按回车键进行回复时,promise将以用户编写的文本进行resolve。

完成这个cli程序

有了这两个部分,我们就可以编写所有的代码了。创建一个名为 index.js 的新文件并输入以下代码。

我们从上面描述的import语句开始:

import { createInterface } from "node:readline/promises";  
import { stdin as input, stdout as output, env } from "node:process";  
import { Configuration, OpenAIApi } from "openai";  

然后我们初始化 API 客户端和 Readline 模块:

const configuration = new Configuration({ apiKey: env.OPENAI_API_KEY });  
const openai = new OpenAIApi(configuration);  
const readline = createInterface({ input, output });  

接下来,我们问用户的第一个问题:“What type of chatbot would you like to create? ”。
我们将使用此问题的答案作为一个"service"消息 来创建一个消息数组,随着对话的进行我们将继续添加新的message。

const chatbotType = await readline.question(  
    "What type of chatbot would you like to create? "  
);  
const messages = [{ role: "system", content: chatbotType }];  

然后我们提示用户开始与聊天机器人交互并启动一个循环,当用户输入不等于字符串“.exit”时继续将输入发送到 API。
如果用户输入“.exit”,程序将结束,就像在 Node.js REPL 中一样。

let userInput = await readline.question("Say hello to your new assistant.\n\n");  
  
while (userInput !== ".exit") {  
// loop  
}  
  
readline.close();  

在循环中,我们将 userInput 作为“user”消息添加到消息数组中。
然后,在 try/catch 块中,将其发送到 OpenAI API。
我们将模型设置为“gpt-3.5-turbo”。

当我们从 API 获得响应时,我们从 response.data.choices 数组中获取消息。
如果有消息,我们将其作为“assistant”消息存储在消息数组中并将其输出给用户,等待他们再次使用 readline 输入。
如果 API 的响应中没有消息,我们会提醒用户并等待进一步的用户输入。
最后,如果向 API 发出请求时出错,我们会捕获错误、记录消息并告诉用户重试。

把这些放在一起,你就有了你的助手。

现在可以通过将 OpenAI API 密钥作为命令行上的环境传递给助手来运行它:

OPENAI_API_KEY=YOUR_API_KEY node index.js  

这将开始您与助手的互动,首先询问您想要什么样的助手。一旦你声明了它,你就可以开始和它聊天了。

做实验可以帮助我们理解

就个人而言,我实际上不确定 ChatGPT 的用处有多大。
它确实令人印象深刻,它返回文本的能力令人难以置信,就像它是由人类编写的一样。
但是,它返回不一定正确的内容,无论它如何自信地呈现该内容。

使用 ChatGPT 进行试验是我们尝试了解 它到底有多强大 的唯一方法,
因此构建一个像这样的简单聊天机器人为我们提供了进行该试验的基础。
这次我们了解到了不同的系统命令可以赋予机器人不同的个性 并使其以不同的方式响应,这是非常有趣的。

这只是开始

所以,也许我们应该进行更多尝试或实验。