alboped e16101865d
All checks were successful
CI / ci (push) Successful in 1m26s
fix(runtime): 修复容器内路径别名导致的模块加载失败
为 Node/PM2 增加 module-alias 运行时解析,并将本地 Prisma 服务别名改为 @db,避免与 @prisma/client 冲突,确保 Docker 启动时可正确加载 dist 模块。

Made-with: Cursor
2026-04-28 06:57:10 +08:00
2026-04-01 22:57:44 +08:00
2026-04-01 22:57:44 +08:00

chat-one-service

TODO当前迭代

  • client-app短信登录 + JWT 鉴权(接入真实短信服务前先 mock
  • client-appChat 会话与消息持久化(接入 Prisma + 数据库)
  • client-app按用户限流与基础风控基于 Redis 后续补上)
  • admin-app邮箱登录与 RBAC角色/权限点基础能力)
  • admin-app平台管理接口增删改查 + 开关 + 权重)
  • admin-app用量统计与简单报表按平台 / 用户聚合)

ChatOne 服务端:基于 NestJS 11 + Fastify,整合多厂商大模型对话能力,对外提供统一的 SSEServer-Sent Events 流式输出协议,便于 Web / App 接入。

更完整的架构说明见:docs/project-solution.md。JWT 最小示例见:docs/jwt-minimal-nestjs.md

目录


技术栈

  • 框架NestJS 11@nestjs/platform-fastify
  • HTTP 客户端undici(调用各厂商 OpenAI 兼容接口)
  • 配置@nestjs/config(可选环境校验见 src/config/validation.ts,默认可在 AppModule 中关闭)
  • 日志nestjs-pino + pino-pretty(开发环境美化输出)
  • 文档Swagger默认路径 /docs
  • 安全头helmet

目录结构(概要)

src/
├── main.ts                    # 入口Fastify + 全局前缀 api + Swagger
├── app.module.ts              # 根模块
├── config/                    # 配置加载与环境校验
├── apps/
│   ├── client-app/            # 用户端(当前含 Chat SSE
│   ├── admin-app/             # 管理端(占位模块,后续扩展)
│   └── shared-domain/
│       └── ai-gateway/        # 多平台 Provider 与路由
├── prisma/                    # Prisma 封装(按需接入数据库时再挂回 AppModule
docs/
├── project-solution.md
└── jwt-minimal-nestjs.md

环境要求

  • Node.js:建议 20 LTS 及以上
  • 包管理:本项目使用 Yarn(存在 yarn.lock);亦可用 npm

安装依赖

yarn install

环境变量

在项目根目录创建 .env(该文件已在 .gitignore 中,不要提交到 Git)。

服务

变量 说明 示例
PORT 监听端口 3000
NODE_ENV 运行环境 development / production

千问DashScope OpenAI 兼容)

变量 说明
QWEN_API_KEY 千问 API Key
QWEN_BASE_URL 可选,默认 https://dashscope.aliyuncs.com/compatible-mode/v1

DeepSeek

变量 说明
DEEPSEEK_API_KEY DeepSeek API Key
DEEPSEEK_BASE_URL 可选,默认 https://api.deepseek.com/v1

火山引擎(方舟 OpenAI 兼容形态,具体以你控制台为准)

变量 说明
VOLC_API_KEY 火山引擎 API Key
VOLC_BASE_URL 可选,默认 https://ark.cn-beijing.volces.com/api/v3

Spug 推送助手(短信验证码)

Spug 推送助手 创建「短信验证码」类消息模板复制模板编号URL 路径中的 ID。模板中可使用变量 number(有效期,单位:分钟);服务端会根据 SMS_CODE_TTL_SECONDS 换算后传入(向上取整,至少为 1与 Redis 中验证码 TTL 一致。

变量 说明
SPUG_PUSH_SMS_TEMPLATE_ID 消息模板编号(必填,非 mock 时)
SPUG_PUSH_BASE_URL 可选,默认 https://push.spug.cc
SPUG_SMS_NAME 可选,模板若要求 name 变量则配置(与官方示例一致)
SMS_MOCK 可选,true 时跳过真实短信发送(本地联调用)
SMS_CODE_TTL_SECONDS 可选,短信验证码 Redis TTL默认 300

说明:当前各 Provider 对上游采用 非流式 chat/completions 调用,由网关将完整回复 切片 后以 SSE 推给客户端。后续可升级为上游真流式。


常用脚本

命令 说明
yarn start:dev 开发模式(tsx watch,改代码自动重启)
yarn build TypeScript 编译到 dist/
yarn start 运行已编译产物 dist/main.js
yarn lint ESLint需本地配置规则时生效

数据库迁移规范Prisma

开发环境变更流程

  1. 修改 prisma/schema.prisma(新增表/字段/索引等)
  2. 生成并执行迁移:
npx prisma migrate dev --name <migration_name>
  1. 如需手动更新 Prisma Client
npx prisma generate
  1. 本地验证接口与核心流程
  2. 提交代码时必须包含:
    • prisma/schema.prisma
    • prisma/migrations/**

生产环境发布流程

生产环境禁止使用 migrate dev,仅执行:

npx prisma migrate deploy

迁移命名规范

迁移名统一使用:动词_对象_说明

例如:

  • init_users
  • add_users_avatar_url
  • add_chat_sessions
  • alter_chat_messages_token_count_type

风险控制建议

  • 涉及删列、改类型、重命名时,先在测试库验证
  • 可能影响历史数据的迁移,先做备份
  • 大改动拆分为多次小迁移,避免一次性高风险变更

常用命令速查

# 生成并执行开发迁移
npx prisma migrate dev --name <name>

# 仅更新 Prisma Client
npx prisma generate

# 查看数据库状态
npx prisma migrate status

# 生产环境应用迁移
npx prisma migrate deploy

启动

开发:

yarn start:dev

默认监听:http://localhost:3000(可通过 PORT 修改)。

生产(先编译再启动):

yarn build
yarn start

API 说明

Swagger

浏览器打开:http://localhost:3000/docs

客户端认证MVP

  • POST /api/client/v1/auth/sms/send
    • 入参:{ "phone": "13800000000", "scene": "login" }
    • 返回:requestIdexpireInprovider
    • 说明:已接入 Spug 推送助手;非生产环境会额外返回 testCode 便于联调
  • POST /api/client/v1/auth/sms/login
    • 入参:{ "phone": "13800000000", "code": "xxxxxx" }
    • 返回:accessTokenrefreshTokenuser
  • POST /api/client/v1/auth/refresh
    • 入参:{ "refreshToken": "..." }
    • 返回:新的 accessTokenrefreshToken

验证码当前已接入 Redis 存储key: chatone:client:sms:code:{phone}:{scene}TTL 300 秒)。

统一 SSE Chat用户端

  • 路径POST /api/client/v1/chat/completions/stream
  • Content-Typeapplication/json
  • 响应text/event-streamSSE

请求体(示例)

{
  "model": "qwen-plus",
  "platform": "qwen",
  "messages": [
    { "role": "system", "content": "你是一个乐于助人的助手" },
    { "role": "user", "content": "你好" }
  ]
}
  • platformqwen | deepseek | volc | auto(或不传,由路由按 model 简单匹配)
  • model:各平台实际模型名或 Endpoint ID火山侧请填你在控制台配置的模型标识

SSE 事件约定

事件名 data 字段含义
meta 请求元信息:requestIdplatformmodel
delta 文本增量:{"delta":"..."}
usage Token 用量:promptTokens / completionTokens / totalTokens
done 结束:finishReason

curl 示例(流式)

先获取 token

curl -s -H "Content-Type: application/json" -X POST \
  -d '{"phone":"13800000000","code":"123456"}' \
  http://localhost:3000/api/client/v1/auth/sms/login

再带 Authorization 调用 chat

curl -N \
  -H "Authorization: Bearer 你的accessToken" \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{"platform":"qwen","model":"qwen-plus","messages":[{"role":"user","content":"你是谁"}]}' \
  http://localhost:3000/api/client/v1/chat/completions/stream

数据库与 Prisma

仓库内已包含 src/prisma/ 模块骨架。若尚未准备好 PostgreSQL 或未执行 prisma generate,请勿在 AppModule 中导入 PrismaModule,避免启动时报缺少生成客户端的错误。

接入数据库时的典型步骤:

  1. 编写 prisma/schema.prisma 并配置 DATABASE_URL
  2. 执行 npx prisma generate / yarn prisma generate
  3. src/app.module.ts 中按需 imports: [PrismaModule]

安全提示

  • 切勿将含真实 Key 的 .env 提交到版本库。
  • 若密钥曾在公开场合暴露,请在对应云厂商控制台 轮换 API Key

许可证

MIT见仓库根目录 LICENSE)。

Description
ChatOne 服务端
Readme Unlicense 415 KiB
0.2 Latest
2026-04-28 02:56:51 +08:00
Languages
TypeScript 93%
Shell 3%
JavaScript 2.5%
Dockerfile 1.5%