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. #构造#CF891B Gluttony

    题目 有一个长度为 \(n\) 的数列 \(a\),数字互不相同, 现在要打乱这个数列,设其为 \(b\), 使得 \(a\) 的任意真子序列与对应的 \(b\) 的任意真子序列的数字和不同 输出任意 ...

  2. #树状数组#洛谷 5677 [GZOI2017]配对统计

    题目 分析 考虑处理出所有右端点的能够匹配的左端点,然后用树状数组离线查询 代码 #include <cstdio> #include <cctype> #include &l ...

  3. 从入门到精通:C++ 学习路线指南,附详细学习计划

    C++是一种高级编程语言,广泛用于开发操作系统.应用程序.游戏和各种工具.如果你想学习这门语言,以下是一个适合初学者的学习路线: 第一步:学习C++基础知识 在学习C++之前,你需要掌握一些基础知识, ...

  4. 华为帐号为AITO问界M5助力,打造懂你的智能座舱

    12月23日,在华为冬季旗舰新品发布会上,AITO问界M5正式发布.华为赋能的AITO问界M5搭载HUAWEI DriveONE纯电驱增程平台和HarmonyOS智能座舱,并且带来华为终端云服务软硬协 ...

  5. mupdf实用操作demo,C++操作PDF文件

    前文: 最近有个项目,需要读写PDF,本来想着挺简单的,读写PDF有那么多的库可以使用,唰唰的就完成了. 忘记了我写C++的,还是在国产系统上开发的. 所以一般的东西还不好使,因为项目需要在多个架构的 ...

  6. 最全能的AI换脸软件,FaceFusion下载介绍(可直播)

    FaceFusion是一款多功能的AI换脸软件,它不仅能图片.视频换脸,还可以直播换脸,换脸效果真实.自然 与大多数换脸软件不同的是,FaceFusion不仅支持N卡处理程序(Azure),还额外提供 ...

  7. 安全工具分析系列-Londly01

    前言 原创作者:Super403,文章分析主要用于研究教学 本期研究:[Londly01-safety-tool]工具源码 简介:自动化资产探测及漏扫脚本 工具来源:https://github.co ...

  8. nginx重新整理——————http请求的11个阶段[十二]

    前言 已经到了关键的http请求的11个阶段了. 正文 概念图: 11 个阶段的处理顺序: 那么就来介绍一下: 先来了解一下postread阶段的realip这个处理,realip 是 real ip ...

  9. 淘宝推荐、视频搜索背后的检索技术竟是它!深度揭秘达摩院向量检索引擎Proxima

    简介: 淘宝搜索推荐.视频搜索的背后使用了什么样的检索技术?非结构化数据检索,向量检索,以及多模态检索,它们到底解决了什么问题?今天由阿里巴巴达摩院的科学家从业务问题出发,抽丝剥茧,深度揭秘达摩院内部 ...

  10. [FAQ] IDE: Goland or PHPStorm 分屏操作

    如图所示,文件上面点击右键,选择 Split Right 就可以在右侧分屏出编辑区. Refer:Goland下载 PHPStorm下载 Link:https://www.cnblogs.com/fa ...