Easy Chat AI 是一套多端 AI 应用平台。它同时包含对话、创作、绘图、技能、语音、二维码、会员、充值和分销等业务,因此架构重点不是简单转发模型 API,而是让生成任务、用户权益、费用扣减和结果资产保持一致。
物理项目与交付物
| 目录 | 技术与形态 | 主要职责 | 交付方式 |
|---|---|---|---|
admin |
Vue 3、Element Plus、Pinia | AI 配置、模型成本、对话与绘图记录、创作模板、技能、会员、财务和营销 | 静态管理站 |
pc |
Vue 3、Nuxt、Element Plus | 对话、创作、绘图、思维导图、二维码、广场、会员和用户中心 | SSR 服务或静态产物 |
uniapp |
Vue 3、uni-app、Pinia | H5、小程序和 App 的创作、技能、登录与用户入口 | 多渠道构建产物 |
server |
PHP、ThinkPHP 6、多应用模式 | 业务 API、模型适配、支付、存储、队列、回调和任务 Worker | PHP-FPM、队列进程和定时任务 |
docker |
容器配置 | 数据库、缓存和应用环境编排 | 本地或服务器容器环境 |
后台、PC 和移动端都只调用平台自己的 API。模型密钥、供应商地址、计费单价和内容安全配置只能存在于服务端。
总体拓扑
flowchart TB Admin[admin
运营后台] --> AdminAPI[adminapi] PC[pc
桌面用户端] --> API[api] Uni[uniapp
移动端] --> API API --> Scene[对话 / 创作 / 绘图
技能 / 语音 / 二维码] AdminAPI --> Config[模型 / Key / 成本
会员 / 敏感词配置] Scene --> Orchestrator[AI 编排与适配层] Config --> Orchestrator Orchestrator --> Chat[同步或流式模型] Orchestrator --> Queue[Redis Queue] Queue --> Worker[Dalle / MJ / SD / YJ Worker] Chat --> Providers[OpenAI / Azure / Claude
Gemini / 国内模型等] Worker --> Providers Worker --> Callback[Discord / 查询 / 回调] Scene --> Billing[会员 / 额度 / 消费流水] Scene --> DB[(MySQL)] Queue --> Cache[(Redis)] Worker --> Storage[对象存储]
服务端应用与调用边界
| 应用或层 | 主要职责 | 不能承担的职责 |
|---|---|---|
adminapi |
模型与 Key 配置、成本规则、内容管理、会员、财务、绘图记录和运营 | 不代替用户身份发起生成 |
api |
用户登录、对话、创作、绘图、技能、语音、支付和作品交互 | 不向客户端返回供应商密钥 |
common/model |
会话、创作、绘图任务、会员、充值和用户流水等业务事实 | 不直接调用远端模型 |
common/service/chat |
统一对话接口与多供应商实现 | 不修改会员订单和余额 |
common/service/draw |
绘图驱动、参数转换和渠道差异 | 不决定用户是否有生成资格 |
job |
DALL-E、Midjourney、Stable Diffusion、意间等异步任务 | 不接收浏览器会话作为可信身份 |
业务层先完成身份、权益和内容检查,再调用模型适配层。适配器只负责把统一请求转换为供应商协议,并把返回值转换成平台的统一结果。
主要领域模块
| 领域 | 已有对象 | 关键规则 |
|---|---|---|
| 对话 | ChatRecords、分类、收藏、PV |
保存角色、上下文和模型参数;历史消息必须属于当前用户 |
| 创作 | CreationModel、分类、收藏 |
模板负责业务输入,最终提示词在服务端组装 |
| 绘图 | DrawTask、DrawRecords、提示词、示例、广场 |
任务与作品分开;失败、重试和公开状态分别记录 |
| 技能 | Skill、SkillCategory |
技能定义提示结构、输入字段、模型能力和可用范围 |
| 会员与计费 | 套餐、权益、订单、用户会员、充值、账户流水 | 每次消费必须可追溯到生成业务号 |
| 营销 | 分销申请、分销订单、提现、卡密、签到与邀请 | 营销奖励不能直接覆盖 AI 消费流水 |
| 内容资产 | 广场、收藏、点赞、文件和语音 | 原始输入、生成结果、缩略图和公开作品分层保存 |
二维码、思维导图和语音看起来是独立页面,但仍遵守同一条业务链:验证权益、创建业务记录、执行生成、保存资产、结算消费。
模型适配与路由
源码已经存在统一聊天接口以及 OpenAI、Azure OpenAI、Claude、DeepSeek、Gemini、GLM、豆包、混元、Kimi、MiniMax、通义、文心、讯飞星火等服务实现。绘图侧通过 DrawDriver 和多种 Engine 接入 DALL-E、Midjourney、Stable Diffusion 等渠道。
模型路由至少需要考虑:
- 场景要求的是文本、视觉、语音还是绘图能力;
- 用户套餐是否允许使用该模型;
- 模型是否启用、Key 是否有额度、当前渠道是否健康;
- 输入长度、最大输出、温度、图片尺寸等参数是否合法;
- 模型成本、平台售价和本次预估消费如何计算;
- 主渠道失败时能否切换备用渠道,以及切换是否会重复计费。
模型名称不应直接等于供应商请求地址。推荐使用稳定的内部模型 ID,配置能力、供应商、远端模型名、成本规则和优先级,业务记录保存内部 ID 与当时的价格快照。
同步、流式与异步任务
对话与文本创作
短文本可以同步返回;长对话适合使用 SSE 或流式响应。服务端先创建消息记录并预留额度,再开始流式输出。客户端断开不代表模型停止执行,服务端仍需记录最终状态和实际用量。
流中间结果不应逐字符写数据库,可以在内存或 Redis 聚合,完成后一次落库;需要实时恢复时按固定时间窗口保存检查点。
绘图与长任务
绘图任务由 QueueService 推入队列,DalleJob、MjJob、SdJob 和 YjJob 负责不同渠道。Midjourney 还通过 Discord 提交、监听和事件处理器接收 Imagine、Upscale、Variation、Outpaint 等动作。
1 | created -> queued -> submitted -> processing -> succeeded |
任务记录需要保存平台任务号、供应商任务号、尝试次数、下次重试时间、错误分类和结果文件。Worker 可重复执行,但同一个平台任务只能产生一次有效扣费和一组最终作品。
会员、额度与计费一致性
一次 AI 请求涉及“资格”和“结算”两个阶段:
- 检查登录状态、会员有效期、功能权益和余额;
- 根据模型与参数生成成本和售价快照;
- 创建生成记录,并预扣或冻结本次额度;
- 调用同步模型或提交异步任务;
- 成功后按实际用量确认消费,失败则释放预留;
- 写用户账户流水,关联会话、消息或绘图任务号。
不能只在前端显示“剩余额度”后直接调用模型。并发请求需要事务、行锁或原子扣减;供应商回调和 Worker 重试必须使用消费业务号保证幂等。
模型成本配置用于运营核算,不应回写历史订单。历史记录保存当时的输入量、输出量、图片规格、成本单价、销售单价和最终金额,才能按模型、渠道和用户进行毛利分析。
内容安全与隐私
- 用户输入先经过长度、文件类型、敏感词和场景参数校验;
- 公开广场内容需要单独审核,生成成功不等于允许公开;
- 日志不记录完整 Token、API Key、身份证明或私密对话正文;
- 上传文件使用随机对象 Key,访问下载接口时重新校验所有权;
- 外部模型可能保存请求内容,隐私政策和场景配置需要说明数据去向;
- 删除账户时区分立即删除的个人信息与因支付、审计需要保留的记录。
数据、缓存与存储
| 设施 | 保存内容 | 设计注意点 |
|---|---|---|
| MySQL | 用户、会话、消息、任务、作品、会员、订单和流水 | 生成状态和消费流水都要可审计 |
| Redis | 队列、短期锁、流式状态、频率限制和热点配置 | Key 包含用户与业务号,设置明确 TTL |
| 对象存储 | 上传图片、生成图片、音频和派生文件 | 数据库保存对象 Key、归属、类型和生命周期 |
| 模型服务 | 文本、图像和语音生成 | 设置超时、并发上限、重试边界和供应商熔断 |
| 支付与微信 | 充值、会员购买和登录渠道 | 回调验签、幂等处理、原始报文脱敏 |
部署与故障域
| 运行单元 | 扩缩容特点 | 主要故障影响 |
|---|---|---|
| 三个前端 | 独立发布和缓存 | 页面不可用,不影响正在运行的 Worker |
| HTTP API | 无状态扩容 | 新请求和历史查询失败 |
| 流式 API | 长连接、单独超时和连接数规划 | 流中断,需要客户端按消息号恢复 |
| 队列 Worker | 按供应商或任务类型分组扩容 | 生成延迟,任务状态保持可恢复 |
| Discord/回调监听 | 长驻进程,单独健康检查 | MJ 结果延迟,可由主动查询补偿 |
| MySQL / Redis | 事实库与调度设施 | MySQL 故障停止计费;Redis 故障暂停新异步任务 |
| 对象存储 | 与 API 分离 | 结果上传失败时任务进入可重试状态 |
当前架构债务与改进顺序
- 统一模型契约:把聊天、绘图和语音的请求、错误与用量字段标准化,减少业务层判断供应商;
- 计费幂等:生成记录、预扣、确认和退回使用同一业务号,并补充并发与重试测试;
- 任务状态机:禁止 Job 直接随意写状态,为超时、回调、重试和人工终止定义合法转换;
- 渠道治理:增加 Key 池健康度、限流、成本、成功率和故障切换记录;
- 内容安全:把输入校验、模型审核和公开审核拆成可追踪步骤;
- 隐私保护:对提示词、对话、上传文件和日志建立保留周期与删除策略;
- 版本升级:ThinkPHP 6、旧版 Axios 与不同前端依赖需要分阶段升级,避免和模型迁移同时进行。
同步对话与异步绘图的详细状态转换,可继续阅读AI 请求与任务流程。