5分钟快速搭建基于nodejs的chatgpt服务

写在前面

首先大家都知道,在国内是无法成功调用openapi的接口,甚至openai的官网都很难打开。所以如果想使用chatgpt的几乎是不可能,不过咱们可以抱着了解的心态去体验一下。

*阅读本文档您可以了解以下内容*

  • eggjs框架
  • egg-mysql的使用
  • openai的实例创建聊天和图片

准备工作

  • apiKey: 这是调用chatgpt的密钥。目前有两种获取方式:

    1. 通过openai的官网去申请,不过这需要一个国外的手机号。
    2. 去某宝直接购买,大概1块钱。
  • 国外服务器: chatgpt必须用国外的服务器访问。可以:去各大厂购买云服务

就绪

  • 准备环境,本文默认使用的centos7.6
  • 开发环境,nodejs >=16,目前centos只能安装node16及以下版本,所以大家安装时需要注意,不要直接安装最新的nodejs。为了方便切换,可以安装nvm来管理node版本,nvm install nodejs版本nvm use nodejs版本
  • 安装eggjs,和所需插件:
    1. npm init egg --type=simple
    2. npm install
    3. npm install egg-mysql
    4. npm install openai
    5. npm install egg-validate

说明: mysql是为了保存聊天上下文,当然你也可以保存在前端本地,validate是校验参数插件



数据库请自行创建,数据表的创建后面会写在代码中

修改配置文件

  1. config/config.default.js中添加
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ['*']
} config.cors = {
origin: '*',
allowMethods: 'GET,HEAD,POST,DELETE,PATCH'
} config.mysql = {
client: {
host: 'localhost',
port: '3306',
user: 'root',
password: 'Chat9527', // 数据库密码
database: 'chatDB', // 数据库名称
},
app: true,
agent: false,
} config.validate = {
convert: true,
widelyUndefined: true,
async formatter(ctx, error) {
ctx.status = 400;
ctx.body = {
code: 'INVALID_PARAM',
errors: error.errors,
};
},
} config.constant = {
API_KEY: 'sk-xxxx', // 你的apiKey
};
  1. config/plugin.js中添加
cors: {
enable: true,
package: 'egg-cors'
},
validate: {
enable: true,
package: 'egg-validate'
},
mysql: {
enable: true,
package: 'egg-mysql',
}

api接口

分析目前只有两个接口,一个是openai的聊天,另一个是生成图片

具体代码如下:

module.exports = app => {
const { router, controller } = app; app.beforeStart(async () => {
const ctx = app.createAnonymousContext();
await ctx.app.mysql.query(`
CREATE TABLE IF NOT EXISTS user_contexts (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id VARCHAR(255) NOT NULL,
memory INT(11) DEFAULT NULL,
affinity INT(11) DEFAULT NULL,
context TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`); });
router.post('/creatChat', controller.chat.createChat);
router.post('/creatImg', controller.chat.creatImg);
};

user_id 表示访问服务的用户;context 为聊天的记录;memory和affinity为保留字段可以不要。

openai使用

  • nodejs中使用new openai({ opentions })来创建实例;
  • 使用实例.chat.completions.create({ messages, model: "gpt-3.5-turbo", });来创建一个聊天

具体代码如下:app/controller/chat.js

const { Controller } = require('egg');
const OpenAI = require('openai'); class ChatController extends Controller {
// 创建图片
async creatImg() {
const { ctx } = this;
const { prompt, n=1, size="1024x1024" } = ctx.request.body;
const openai = new OpenAI({
apiKey: this.app.config.constant.API_KEY,
});
const response = await openai.images.generate({ prompt, n, size });
ctx.body = {
data: response.data
};
} // 创建聊天
async createChat() {
const { ctx } = this;
const { request, service } = ctx;
const { prompt, userId } = request.body;
try {
ctx.validate(this.indexRule, request.body); const openai = new OpenAI({
apiKey: this.app.config.constant.API_KEY,
}); const userContext = await service.chat.getUserContext(userId);
const messages = this.buildMessageList(userContext, prompt); const response = await openai.chat.completions.create({
messages,
model: "gpt-3.5-turbo",
}); const assistantResponse = response.choices[0].message.content.trim();
const updatedUserContext = this.updateUserContext(userContext, prompt, assistantResponse);
service.chat.updateUserContext(userId, updatedUserContext); const shouldEndConversation = this.isConversationEnding(assistantResponse);
if (shouldEndConversation) {
service.chat.deleteUserContext(userId);
ctx.body = { code: 0, message: "拜拜!" };
} else {
ctx.body = { code: 0, message: assistantResponse };
} } catch (err) {
ctx.status = 442;
ctx.body = {
code: -1,
message: '系统错误',
error: err.errors,
}
}
} // 构建消息列表
buildMessageList = (userContext, prompt) => {
return [
...userContext,
{ role: "system", content: "You are a helpful assistant that answers questions." },
{ role: "user", content: prompt }
];
} // 更新用户上下文
updateUserContext = (userContext, prompt, assistantResponse) => {
return [
...userContext,
{ role: "user", content: prompt },
{ role: "assistant", content: assistantResponse }
];
} // 判断是否结束聊天
isConversationEnding(response) {
const keywords = ["再见", "退出", "滚", "拜拜"];
return keywords.some(keyword => response.includes(keyword));
} // 定义参数校验规则
get indexRule() {
return {
userId: {
type: 'string',
required: true,
format: /^[A-Za-z0-9]+$/,
message: 'userId不能为空,且只能包含字母和数字',
},
prompt: {
type: 'string',
required: true,
max: 300,
message: 'content不能为空,且长度不能超过300',
},
};
}
} module.exports = ChatController;
  • app/service/chat.js里是数据的存储逻辑,如下:
const { Service } = require('egg');

class ChatService extends Service {

  // 获取用户上下文
async getUserContext(userId) {
const result = await this.app.mysql.select('user_contexts', {
where: { user_id: userId },
orders: [['created_at', 'desc']],
limit: 1,
});
return result[0] ? JSON.parse(result[0].context) : [];
} // 更新用户上下文
async updateUserContext(userId, context) {
const existingData = await this.app.mysql.get('user_contexts', { user_id: userId }); const record = {
user_id: userId,
context: JSON.stringify(context),
created_at: new Date(),
}; if (existingData) {
await this.app.mysql.update('user_contexts', record, {
where: { user_id: userId },
});
} else {
await this.app.mysql.insert('user_contexts', record);
} } // 删除用户上下文
async deleteUserContext(userId) {
await this.app.mysql.delete('user_contexts', {
user_id: userId
});
}
} module.exports = ChatService;

一切完成就绪

  • 使用 npm run dev 来运行服务器
  • 用Postman 访问 ip:7001/creatChat,参数 userId: '1' , prompt: '你好'
  • 使用 npm start 来后台运行服务
  • 使用 npm stop 来停止服务

花费了不止5分钟?

  • 直接克隆项目 git clone https://github.com/812781385/chatgptService.git
  • npm i
  • npm run dev

nodejs搭建chatgpt服务的更多相关文章

  1. nodejs搭建web服务教程

    nodejs搭建web服务教程 先安装nodejs 然后 命令node js文件 即可开启服务了 输出如下 Magic happens on port 9011 你查看端口可以看到tcp 0 0 :: ...

  2. nodejs搭建简单的websocket服务端

    创建websocket服务端使用了nodejs-websocket ,首先要安装nodejs-websocket,在项目的目录下: npm install nodejs-websocket 1.搭建w ...

  3. mock---前端搭建模拟服务

    在做前端开发接口的时候,往往接口都是从后端来的,这让前端很苦恼,但是有了 MockServer ,前端也可以搭建API服务了. server-mock是什么? 是一款nodejs的应用,用于搭建web ...

  4. 用nodejs搭建类似于C++的服务器后台.类似网易pomelo

    实际的情况,用nodejs跑业务,非常的快,只要用好其无阻塞和回调这两点,处理速度真的是杠杠的. 从年初开始,我用nodejs搭建了类似C++的服务器后台,也想和做同样的事情的朋友分享,本服务平台因为 ...

  5. 使用 Node.js 搭建微服务网关

    目录 Node.js 是什么 安装 node.js Node.js 入门 Node.js 应用场景 npm 镜像 使用 Node.js 搭建微服务网关 什么是微服务架构 使用 Node.js 实现反向 ...

  6. nodejs搭建web服务器初级

    nodejs搭建简单的web服务器 1.1简介 Node.js是基于Chrome JavaScript运行时建立的一个平台,实际上它是对Google Chrome V8引擎进行了封装,它主要用于创建快 ...

  7. 用nodejs搭建代理服务器

    题图 From 极客时间 From Clm 前端开发者在工作中常常遇到跨域的问题,一般我们遇到跨域问题主要使用以下办法来解决: 1.jsonp 2.cors 3.配置代理服务器. jsonp不是很灵活 ...

  8. 利用 nodeJS 搭建一个简单的Web服务器(转)

    下面的代码演示如何利用 nodeJS 搭建一个简单的Web服务器: 1. 文件 WebServer.js: //-------------------------------------------- ...

  9. 使用node+puppeteer+express搭建截图服务

    使用node+puppeteer+express搭建截图服务 转载请注明出处https://www.cnblogs.com/funnyzpc/p/14222807.html 写在之前 一开始我们的需求 ...

  10. 如何搭建DNS服务

    继NTP时间服务器后,继续搭建DNS服务,鉴于昨晚撰写时间超过预期,这次改变策略,先把自己需要用到的部分写出来(主要是基于RAC的搭建,只涉及正向和反向DNS解析),后面再添加必要的说明和阐述. 试验 ...

随机推荐

  1. C++设计模式 - 适配器模式(Adapter)

    接口隔离模式 在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题.甚至根本无法实现.采用添加一层间接(稳定)接口,来隔离本来互相紧密关联的接口是一种常见的解决方案. 典型模式 Facade P ...

  2. Vue入门笔记一

    <Vue.js项目实战>Guillaume Chau Vue核心功能概述 1.一个响应式的数据系统,能通过轻量级的虚拟DOM引擎和最少的优化工作来自动更新用户界面 2.灵活的视图声明,包括 ...

  3. #后缀数组#洛谷 4051 [JSOI2007]字符加密

    题目 分析 将字符串复制一份放入末尾,将其后缀排序之后 SA数组既然表示排名为\(i\)的后缀的起始位置, 那么只要它在\([1,len]\)范围内就是合法的, 那么输出以这个位置开头长度为\(len ...

  4. OpenHarmony社区运营报告(2022年11月)

    本月快讯 • 11月24日,第二十届中日韩三国IT局长OSS会议暨东北亚开源软件推进论坛以在线形式成功召开.经审核评选认定,OpenAtom OpenHarmony(以下简称"OpenHar ...

  5. Docker学习路线9:运行容器

    要启动一个新的容器,我们使用 docker run 命令,后跟镜像名称.基本语法如下: docker run [选项] 镜像 [COMMAND] [ARG...] 例如,要运行官方的 Nginx 镜像 ...

  6. Docker 13 网络

    Linux 网络 查看本地网络信息: [root@sail ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueu ...

  7. innoSetup打包文件编写模板

    现在打包主要是使用 innosetup 这个软件来进行打包,支持录制脚本和手动编写脚本,比较好用. 此文章主要记录手写脚本,便于后期查询,借鉴. 文档: inno setup :https://blo ...

  8. HarmonyOS后台任务管理开发指南上线!

      为什么要使用后台任务?开发过程中如何选择合适的后台任务?后台任务申请时存在哪些约束与限制? 针对开发者使用后台任务中的疑问,我们上线了概念更明确.逻辑结构更清晰的后台任务开发指南,包含具体的使用场 ...

  9. Tomcat启动闪退的10个解决小技巧

    引言 大家好!在我们日常开发中,使用Tomcat作为Web服务器是相当常见的. 然而,遇到Tomcat启动后立即闪退的问题也不是什么稀罕事. 这种情况可能会让人感到困惑和沮丧,特别是当你急需完成一个项 ...

  10. css 如何绘制正方形

    前言 如何绘制正方形的问题呢,在这里我先只写一种方式,后续补齐. 正文 写正方形有一个很特殊的地方就在于我们在写html的时候,宽是一定固定的,因为不可能溢出去,但是高就不固定了,因为可能要滑动. 问 ...