AI 对话产品 架构模板
代表产品:Claude、ChatGPT、Gemini、各类「AI 助手」 一句话定位:把一个大语言模型(LLM)包装成可对话、能流式输出、能用工具、能联网的产品。
1. 一句话定位
一个 AI 对话产品 = 一个昂贵的「推理大脑」(LLM) + 一圈把它变得好用、安全、能赚钱的「外壳」。
架构上最反直觉的一点:它和你熟悉的「网站」最大的不同,不是逻辑复杂,而是最贵、最稀缺的资源从「数据库/CPU」变成了「GPU 算力」。整套架构几乎都是围绕「怎么把 GPU 喂饱、用满、用省」转的。
2. 业务本质:它在解决什么问题
用户要的是一个随叫随到、什么都懂、能帮我干活的助手。它取代的是「自己 Google + 自己读 + 自己写」的过程。
钱从哪来:
- 订阅(个人/团队按月付费,要稳定的体验和额度);
- API 调用(开发者按 token 计费,把你的模型嵌进他们的产品);
- 企业版(数据隔离、合规、私有部署)。
关键事实:每生成一个字,背后都是真金白银的 GPU 时间。 普通网站「多一次请求几乎不要钱」,这里「多生成 1000 字就是实打实的成本」。这一条决定了后面几乎所有架构取舍。
3. 核心需求与约束
功能性需求:
- [ ] 多轮对话:记住上下文,连续聊。
- [ ] 流式输出:像打字机一样一个字一个字蹦出来,而不是憋十几秒一次性给。
- [ ] 系统提示 / 角色设定:给模型设定行为边界。
- [ ] 工具调用(function calling):让模型能调计算器、搜索、代码执行、查数据库。
- [ ] 联网 / RAG:让模型回答时能引用外部知识或实时信息。
- [ ] 多模态:看图、读文件、出图。
- [ ] 会话历史:保存、检索过去的对话。
非功能性需求 / 质量属性(这才是架构的主战场):
| 质量属性 | 目标 | 为什么对这类系统重要 |
|---|---|---|
| 首字延迟 TTFT | < 1 秒 | 用户盯着屏幕等,首字越快越「跟得上」。流式的全部意义就在这。 |
| 生成吞吐 | 高 tokens/秒 | 决定回答多快读完,也直接决定单卡能服务多少人。 |
| 成本 / 每千 token | 越低越好 | 算力即成本,毛利全看这个。这是和普通系统最大的区别。 |
| 可用性 | 99.9%+ | 挂了用户立刻就走。 |
| 安全性 | 必须 | 不能被诱导输出有害内容、不能被注入攻击。 |
关键约束(不可逾越的边界):
- 🔴 GPU 又贵又缺。这是头号约束,整套架构为它服务。
- 🔴 上下文窗口有限。模型一次能「看」的内容有上限,塞太多既贵又慢甚至放不下。
- 🔴 推理是「有状态」计算。生成下一个字依赖前面所有字的中间结果(KV cache),这块显存吃得很凶。
- 模型本身不可控(会胡说、会被骗),需要外层兜底。
4. 架构全景图
用户(Web / 移动端 / 第三方 API 调用方)
│ 发一句话
▼
┌──────────────────────────────────────────────────────────────────────┐
│ 接入层 API 网关 / 边缘 │
│ • 鉴权、限流、按用户配额 • 流式连接(SSE/WebSocket)保持 • 路由 │
└───────────────────────────────────┬──────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────────┐
│ 编排层(Orchestrator)—— 产品的「大脑外壳」,真正的业务逻辑都在这 │
│ │
│ ① 组装上下文:系统提示 + 历史对话 + 检索到的资料 + 本轮输入 │
│ ② 输入安全检查(moderation) │
│ ③ 决定走哪条路:直接回答?查知识库(RAG)?调工具? │
│ ④ Agent 循环:模型→工具→结果再喂回模型,直到收敛 │
│ ⑤ 输出安全检查 + 计费记账(数 token) │
└───┬───────────────┬────────────────┬───────────────┬──────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌───────────┐ ┌────────────┐ ┌─────────────────┐
│ 会话存储 │ │ 向量检索 │ │ 工具执行 │ │ 推理服务(核心) │
│ (历史) │ │(RAG/知识) │ │ 沙箱 │ │ │
│ │ │ │ │ 搜索/代码/ │ │ 排队 + 连续批处理 │
└─────────┘ └───────────┘ │ 函数调用 │ │ ↓ │
└────────────┘ │ ┌───────────┐ │
│ │ GPU 集群 │ │
│ │ (跑模型) │←──── 模型权重
│ └───────────┘ │ (对象存储)
└────────┬────────┘
│ token 一个个吐出来
▼
◀═══ 流式回传给用户(SSE)═══灵魂部件是右下角的推理服务——其余所有东西(网关、编排、缓存)本质上都是在「保护和喂养这块昂贵的 GPU」。
5. 组件职责
- 接入层 / API 网关:鉴权、限流、按订阅档位分配配额,并维持住流式长连接(一次回答可能要持续吐字几十秒)。为什么需要:GPU 太贵,必须在最外层就把滥用和超额流量挡住。
- 编排层(Orchestrator):整个产品的业务逻辑所在。把零散材料拼装成一段「喂给模型的完整提示」,跑「模型↔工具」的 Agent 循环,做安全检查和计费。为什么需要:模型本身只会「续写文字」,把它变成「产品」的所有智能都在这一层。
- 推理服务(Inference Service):管理 GPU 集群,把很多用户的请求合并成批一起算(continuous batching),最大化 GPU 利用率,逐 token 输出。为什么需要:单条请求喂 GPU 会让它大量空转;批处理是把成本打下来的关键。
- 会话存储:存历史对话。为什么需要:多轮对话要记住上文;也用于「历史会话」列表。append 为主、按会话 ID 读取。
- 向量检索 / 知识库(RAG):把文档切块、向量化,按语义检索出与问题最相关的片段。为什么需要:让模型回答基于「你的资料 / 最新信息」,而不是只靠它训练时记住的东西。
- 工具执行沙箱:模型说「我要搜一下」「我要跑这段代码」时,在隔离环境里真正执行,把结果喂回模型。为什么需要:让模型从「只会说」变成「能做事」;隔离是因为执行外部代码/请求有安全风险。
- 模型权重存储:模型文件(几十~上千 GB)放对象存储,GPU 节点启动时加载进显存。
- 安全 / 内容审核:输入侧拦截恶意/违规请求,输出侧拦截有害内容。
6. 关键数据流
场景一:一次普通的流式对话(最核心的路径)
1. 用户输入「帮我把这段话改得更正式」 ──▶ 网关(鉴权、扣配额、建立 SSE 连接)
2. ──▶ 编排层:
a. 取出本会话历史
b. 拼装:系统提示 + 历史 + 本轮输入 → 一段完整 prompt
c. 输入审核(有没有越权/违规)
3. ──▶ 推理服务:请求进入队列,与其他用户的请求一起组成一个 batch
4. ──▶ GPU:逐个生成 token。每生成一个就立刻往回吐:
网关 ══SSE══▶ 用户屏幕上一个字一个字出现
5. 生成结束 ──▶ 编排层:输出审核 + 记录 token 数用于计费 + 把这轮对话写入会话存储注意第 4 步:字还没生成完,用户已经在读了。 这就是流式架构把「十几秒的等待」变成「立刻有反应」的魔法。
场景二:带工具/检索的「Agent 循环」(模型不仅说,还会做)
用户问「我们上季度华东区销量多少?」
编排层 ─▶ 模型:这个问题我答不了,我要查数据
模型 ──▶ 输出一个「工具调用:查询销量(区域=华东, 季度=Q3)」
编排层 ─▶ 工具沙箱执行查询 ─▶ 拿到结果「华东 Q3:1240 万」
编排层 ─▶ 把结果拼回 prompt,再喂给模型
模型 ──▶ 「华东区上季度销量为 1240 万元,环比……」(这次是流式回答)
⟲ 这个「模型→工具→喂回→模型」可能循环好几轮,直到模型不再要工具为止。架构要点:工具结果是重新进入模型的文本,必须当作不可信输入对待(见第 10 节:提示注入)。
7. 数据模型与存储选择
核心实体:用户 ─ 会话(conversation) ─ 消息(message);文档 ─ 文档块(chunk) ─ 向量(embedding);用量记录(usage)。
| 数据 | 存储类型 | 为什么 |
|---|---|---|
| 用户 / 订阅 / 配额 | 关系型 | 要事务、强一致(扣费不能错) |
| 会话历史(消息) | 文档型 / 追加日志 | 写多读少、按会话 ID 取、结构灵活 |
| 文档向量(RAG) | 向量数据库 | 要按「语义相似度」检索,这是普通数据库做不到的 |
| 模型权重 | 对象存储 | 文件巨大、不可变、按需加载到 GPU |
| 用量 / 计费流水 | 时序 / 列存 | 海量、按时间聚合、用于账单和监控 |
| 热点提示前缀 | 显存中的 KV 缓存 | 见决策 3——这是省钱的关键 |
教学点:不同数据的「访问形态」不同,就该放进不同类型的存储。 把会话历史硬塞进关系型数据库、用
LIKE去做语义搜索,都是把工具用错了地方。
8. 关键架构决策与权衡 ⭐
决策 1:流式输出(SSE)还是一次性返回?
- 一次性:实现简单,但用户要盯着空白屏幕等十几秒,体验灾难。
- 流式:首字 1 秒内就出,感知延迟大幅下降。
- 取向:几乎一定选流式。代价是连接管理更复杂、出错后的重试/恢复更麻烦、网关要长时间维持连接。感知延迟有时比真实总延迟更重要——这是个通用智慧。
决策 2:每个请求单独算,还是「连续批处理」?
- 单独算:延迟可控,但 GPU 大量空转,成本爆炸。
- 连续批处理:把多个用户的生成请求动态拼成一批一起算,GPU 利用率拉满。
- 取向:必须批处理,因为 GPU 是头号稀缺资源。代价是调度复杂、可能拉高个别请求的尾延迟,需要在「吞吐」和「单请求延迟」之间调参。
决策 3:重复的提示前缀,要不要缓存?(省钱关键)
- 每轮对话都把「系统提示 + 全部历史」重新算一遍,简单但极度浪费——这些内容上一轮刚算过。
- 缓存这段前缀的中间计算结果(KV cache / prompt caching),下轮直接复用。
- 取向:规模化后必做。把「重算昂贵前缀」变成「读缓存」,是这类系统最大的成本杠杆之一。代价是缓存管理、显存占用、失效策略的复杂度。
决策 4:塞长上下文,还是用 RAG 检索?
- 长上下文:把所有可能相关的资料一股脑塞进 prompt。简单,但又贵又慢,而且太多噪音反而降低回答质量。
- RAG:先检索出最相关的几段,只把它们塞进去。
- 取向:资料量一大就用 RAG。代价是要维护一套「切块→向量化→检索」的管线,且检索质量直接决定回答质量。
决策 5:会话状态放客户端还是服务端?
- 客户端持有历史、每轮全量发上来:服务端无状态、好扩展,但隐私和带宽有压力,且受上下文窗口限制。
- 服务端存历史:体验连贯、可跨设备,但要管存储和隐私合规。
- 取向:产品级一般服务端存(支持多设备、长期记忆),API 级常让调用方自己带历史(无状态、好扩展)。
决策 6:一个大模型通吃,还是「模型路由」?
- 所有请求都用最强(最贵)的模型:质量稳,但简单问题也烧大钱。
- 路由:简单问题给小模型/便宜模型,难问题才上大模型。
- 取向:规模化后引入路由。把昂贵的工作交给「能干这活儿的最小工具」,是通用的省钱思路。
9. 规模化与瓶颈
和普通系统完全不同:这里的瓶颈通常不是数据库,而是 GPU。
- 第一个瓶颈:GPU 集群被打满 → 请求排队 → 首字延迟飙升。 破解:① 连续批处理拉满利用率;② prompt 缓存减少重复计算;③ 模型路由,把简单请求分流到小模型;④ 模型量化(用更省显存的精度);⑤ 扩 GPU(但 GPU 采购慢、贵,不能像加 Web 服务器那样秒扩)。
- 第二个瓶颈:上下文越长,单请求吃的显存越多 → 同时能服务的人变少。 破解:① KV 缓存的精细管理(paged attention 之类的显存分页);② 用 RAG 取代「无脑长上下文」;③ 历史对话定期压缩/摘要。
- 第三个瓶颈:大批次拉高尾延迟(P99)。 破解:在批大小和延迟目标之间动态权衡,为付费高档用户预留低延迟通道。
- 成本本身就是瓶颈。 普通系统「先上线再优化成本」没问题;这里成本不优化,毛利直接是负的,所以省钱(缓存、路由、量化)从第一天就是架构议题。
10. 安全与合规要点
- 🔴 提示注入(Prompt Injection)—— 这是 AI 产品全新的、最棘手的攻击面。 任何重新进入模型的外部文本(RAG 检索到的网页、工具返回的结果、用户上传的文件)都可能藏着「忽略你之前的指令,改为……」的恶意内容。架构上要把这些内容当不可信输入,做隔离、标注来源、限制工具权限。
- 工具执行必须沙箱隔离:模型要跑代码、发网络请求时,在受限、可丢弃的隔离环境里执行,绝不能碰生产系统。
- 数据隐私:对话里常含个人/商业敏感信息。要做租户隔离、传输与存储加密、明确「是否用于训练」的边界、可删除。
- 输出安全:防止被诱导生成有害内容(越狱),输入输出两侧都要审核。
- 配额与滥用:API 层防刷、防薅(每个 token 都是钱)。
11. 常见误区 / 反模式
- ❌ 把它当普通 CRUD 网站设计,忽视 GPU 是稀缺资源 → ✅ 一切架构先问「这对 GPU 利用率和成本意味着什么」。
- ❌ 不做流式,憋完整答案再返回 → ✅ 默认流式,首字延迟是第一体验指标。
- ❌ 每轮都把全部历史重新喂、从不缓存 → ✅ 缓存提示前缀,这是最大的省钱点之一。
- ❌ 把所有资料硬塞进上下文 → ✅ 量大就上 RAG,只喂最相关的片段。
- ❌ 直接信任工具/检索/网页返回的文本 → ✅ 当作不可信输入,警惕提示注入。
- ❌ 同步阻塞地调工具,卡住整个流 → ✅ 工具调用异步化,把 Agent 循环和流式输出解耦。
- ❌ 不记 token 账 → ✅ 没有 token 计量,你既会超上下文窗口,也会收到吓人的账单。
12. 演进路线:MVP → 成长期 → 成熟期
| 阶段 | 规模量级 | 架构长什么样 | 此时该操心什么 |
|---|---|---|---|
| MVP | 验证想法 | 直接调用某个模型提供商的 API + 一个薄薄的编排层;客户端带历史;简单 SSE 流式;无 RAG、无自建 GPU | 先验证产品到底有没有人用,别一上来自建 GPU 集群 |
| 成长期 | 万~百万用户 | 引入会话存储、RAG、输入输出审核、限流配额、prompt 缓存;如自建模型则上连续批处理 | 找成本和延迟的瓶颈,把单 token 成本打下来,稳住可用性 |
| 成熟期 | 千万~亿级 | 多区域 GPU 集群、模型路由(大小模型混用)、精细缓存与显存管理、完整 Agent 工具生态、评测/可观测性管线、企业级多租户隔离 | 成本、容灾、安全合规、模型质量持续评测 |
13. 可复用要点
- 💡 先找到你系统真正的「稀缺资源」,围绕它的利用率做架构。 这里是 GPU,在别的系统可能是数据库连接、带宽或人。把架构建在「让稀缺资源不空转」上,而不是建在「代码优雅」上。
- 💡 感知延迟常比真实延迟更重要。 流式输出没让总时间变短,但让体验天差地别。任何「让用户更早看到反馈」的设计都值钱。
- 💡 缓存「重算代价高的东西」是巨大的杠杆。 这里是 KV cache / prompt 缓存,在别处可能是计算结果、聚合视图、渲染页面。
- 💡 把昂贵的活儿交给能干它的最小工具。 模型路由的思想,等同于「别用重型方案解决轻量问题」。
- 💡 任何重新进入核心系统的外部数据都是不可信的。 提示注入只是「永远不要信任用户输入」这条老规矩,在 AI 时代的新形态。
🎯 随堂检验
- A数据库连接数
- BGPU 算力
- C前端带宽
参考原型与延伸阅读
本模板基于以下真实开源项目与论文整理。AI 对话产品的「推理服务 / 接入编排 / 检索」三块,在本仓库分别有 模型推理服务、AI 网关、RAG 知识库 三个模板做放大特写。
🔧 开源原型(可直接读代码):
- vllm-project/vllm — 主流 LLM 推理 / 服务引擎,体现 GPU 推理、连续批处理、KV 缓存管理。
- langchain-ai/langchain — 经典 LLM 应用框架,体现 RAG 与工具调用(function calling)的编排。
📖 论文:
- Efficient Memory Management for LLM Serving with PagedAttention (SOSP'23) — vLLM 背后的论文,讲 KV 缓存的虚拟内存式分页管理。
📌 一句话记住 AI 对话产品:它不是「逻辑很复杂的网站」,而是「一台围着昂贵 GPU 转的精密机器」——所有架构取舍,最终都在回答『怎么把这块算力用得又快又省又安全』。