📑 本页目录(点开跳转)
附录A · 速查
📖 动手时开着的那一页。不重讲原理,只给「该选哪个」和「别踩哪个」。
⚠️ 上线前的逐条体检在 16 · 上线前检查单,这里不重复。
🧭 一、决策速查:该选哪个
通道:怎么把生成结果送到浏览器
| 场景 |
选 |
为什么 |
| ⭐ 绝大多数 LLM 应用 |
SSE |
单向就够、基于 HTTP、代理友好 |
| 双向实时(协作编辑、语音) |
WebSocket |
真的需要客户端持续往上说 |
| 一次性大响应、不需要边收边显示 |
普通 JSON |
别为了流式而流式 |
⚠️ 浏览器端别用 EventSource —— 带不了 Authorization header。用 fetch + ReadableStream(10 章)。
异步:长任务怎么跑
| 场景 |
选 |
边界 |
| 几秒的活、丢了无所谓 |
BackgroundTasks |
⚠️ 进程重启就丢 |
| ⭐ 中小规模、要可靠 |
数据库当队列(FOR UPDATE SKIP LOCKED) |
⭐ 被严重低估,少一个中间件 |
| 高吞吐、要分布式 worker |
Redis / RabbitMQ |
多一套要运维的东西 |
向量存哪
| 场景 |
选 |
| ⭐ 百万级以内 + 需要按业务字段过滤 |
pgvector(和业务数据同库) |
| 千万级以上 / QPS 很高 / 向量本来就和业务分离 |
专用向量库 |
⚠️ 决定性问题不是数据量,是 ⭐ 「向量和业务数据要不要保持一致」(07 章)。
认证
| 场景 |
选 |
| ⭐ 绝大多数情况 |
OAuth 第三方登录 或 托管认证服务 |
| 有明确合规要求必须自己存 |
自建(⚠️ 哈希、重置、撞库、合规,坑很深) |
部署
| 场景 |
选 |
| ⭐ 默认 |
能跑常驻容器的 PaaS 🗓️ |
| 已有云基建、要精细控制 |
云容器服务 |
| 极致成本 / 特殊合规 |
自己的 VPS + Nginx |
🗓️ 这里不点平台名字——名字每年都在换,要记的是判据(01 章第六节那五条):
常驻进程 / 单请求超时 ≥ 5 分钟 / 不缓冲响应体 / 能设环境变量 / 自带 HTTPS 域名。
⚠️ Serverless 默认踩掉前三条,AI 应用上它多半会栽(14 章)。
⚠️ 二、常见陷阱清单(按会咬到你的顺序)
💸 成本类(最贵)
| 陷阱 |
正确做法 |
| 💀 只做了限流没做配额 |
限流管「每分钟几次」,配额管「每月多少钱」—— 两件事(12) |
| 💀 没有全局熔断 |
代码 bug 死循环调 API 能一夜烧穿预算。⭐ 写完要把阈值调成 0.01 真触发一次 |
| ⚠️ 客户端断开后端不停 |
用户关了页面你还在生成,钱照付(05) |
| ⚠️ 前端自动重发 |
每次重发都是一次真金白银的新调用(10) |
| ⚠️ 成本不分维度记 |
只知道总账单涨了,不知道是谁、哪个功能(04 · 12) |
🔒 安全类
| 陷阱 |
正确做法 |
💀 忘了 WHERE tenant_id |
⭐ 靠结构保证,不靠记得写(08) |
| 💀 渲染 Markdown 不做净化 |
模型输出是不可信输入;间接注入可让 A 的文档在 B 浏览器里执行 HTML(10) |
| ⚠️ token 放 query 参数 |
会进服务器日志、代理日志、浏览器历史(10) |
| ⚠️ 密钥进日志 / 进错误上报 |
⭐ API key 泄露 = 别人拿你的钱调模型(13) |
| ⚠️ prompt 和回复原样进日志 |
隐私、体积、合规(15) |
⏱ 超时与并发类
| 陷阱 |
正确做法 |
| 💀 把 LLM 调用包在数据库事务里 |
一个请求 3 秒,连接被占 3 秒,并发一上来就崩(06) |
| ⚠️ async 函数里写同步阻塞调用 |
把整个事件循环卡死(03) |
| ⚠️ 只设一个超时 |
⭐ 连接超时和读取超时是两个数,流式下后者要特别处理(04) |
| ⚠️ 连接池配错 |
并发一上来先耗尽的往往是它(06) |
| ⚠️ 重试用黑名单 |
⭐ 用白名单:只重试 429/5xx/网络,400 和内容策略拒绝绝不重试(04) |
🌊 流式类
| 陷阱 |
正确做法 |
| 💀 反向代理缓冲吃掉流式 |
Nginx proxy_buffering off;压缩中间件和云平台也会吃(05 · 14) |
| ⚠️ 流式下想返回 500 |
头已经发出去了,改不了 —— ⭐ 错误只能作为流里的一帧(05) |
💀 流式错误帧忘了带 trace_id |
非流式时它在那个 500 的 JSON 里,流式那个 JSON 压根不发 —— 用户只能说「回答到一半崩了」,⭐ 你查无可查(05 · 10) |
💀 TextDecoder 不加 stream: true |
多字节字符被网络切开会解成 �,间歇性出现极难查(10) |
| ⚠️ 把一个 chunk 当一帧 |
网络分块和 SSE 帧毫无对应关系,必须 buffer 按 \n\n 切(10) |
| ⚠️ 强行滚动到底部 |
用户往回翻时会被拽回去,根本选不中文本(09 · 10) |
🗄️ 数据类
| 陷阱 |
正确做法 |
| ⚠️ IVFFlat 在空表上建索引 |
必须先有数据(靠聚类),空表上建完再灌数据效果极差且不报错(07) |
| ⚠️ 距离运算符选错 |
<=> 余弦 / <-> L2 / <#> 内积,选错不报错只是检索更差(07) |
⚠️ 不存 embedding_model 列 |
将来换模型时连「哪些要重算」都查不出来(07) |
| ⚠️ 没有迁移工具 |
上线中的表加字段会锁死(06) |
| ⚠️ 任务不做幂等 |
重试和 worker 崩溃会让它执行两次 —— 用户被扣两次钱(11) |
📦 部署类
| 陷阱 |
正确做法 |
| ⚠️ Dockerfile 层缓存顺序错 |
先 COPY 依赖清单再装、最后 COPY 代码,否则改一行全部重装(14) |
| ⚠️ 没有优雅关闭 |
部署时正在流式的请求被硬切(14) |
| ⚠️ 健康检查只有一种 |
⭐ liveness(要不要重启)和 readiness(能不能接流量)是两回事(14) |
| ⚠️ 只看平均延迟 |
⭐ LLM 延迟长尾极重,必须看 p95/p99;⚠️ 百分位不能平均(15) |
📐 三、AI 应用该看的四个指标
| 指标 |
是什么 |
为什么重要 |
| ⭐⭐ TTFT(首字延迟) |
从请求到第一个字 |
决定用户觉得它「在动」还是「卡住了」 |
| 总时长 |
到最后一个字 |
影响并发和连接占用 |
| token 用量 |
输入 + 输出分开记 |
成本的直接来源 |
| 错误率按类型分 |
429 / 超时 / 5xx / 内容策略 分开 |
⭐ 混在一起就看不出该修哪个 |
⚠️ 四个都要看 p95/p99,不是平均值。
🔤 四、SSE 帧格式(全板块统一)
data: {"type":"delta","text":"你"}
data: {"type":"delta","text":"好"}
data: {"type":"usage","in":120,"out":8}
data: {"type":"error","message":"upstream timeout","trace_id":"a1b2c3d4e5f6"}
data: {"type":"done"}
⚠️ 每帧后面是空行(\n\n)。⭐ 一开始就分帧,以后加东西(用量、工具状态、错误)不用重写前端。
⭐ 帧类型放在 JSON 负载的 type 里,不用 SSE 的 event: 行 —— 前端是 fetch + ReadableStream 手动解析(EventSource 带不了 Authorization),而 event: 行只对 EventSource 有意义,手动解析器只能多写一套状态机或整行丢掉。放进负载,一行 JSON.parse 拿到全部信息,解析路径只有一条。
⚠️ 两个容易写错的地方:结束帧是 {"type":"done"} 不是 [DONE](后者不是合法 JSON,会让统一的 JSON.parse 抛 SyntaxError);错误帧字段名是 message 不是 code(前端拿它是要直接显示给人看的)。⚠️ message 里别塞异常原文(05 · 10)。
⭐⭐ 错误帧必须带 trace_id,这条在流式里最容易漏:非流式出错时 trace_id 在那个 500 的 JSON 里;⚠️ 流式的状态码在第一个字发出去时就定死成 200 了,那个 JSON 根本不会发出来,所以它只能作为错误帧的一个字段送过来,前端也要专门接住并显示。分工是 ⭐ message 给人看(一句人话)、trace_id 给你查(日志里对应完整细节)——03 章立的原则、16 章的验收项,都要靠它在流式这条路上也成立。
🗂 五、哪个概念在哪一章
| 找什么 |
去哪 |
| 两小时上线一个能用的 |
01 |
| 全景架构图、四件 AI 特有的难事 |
02 |
| async 在解什么、依赖注入、错误形状 |
03 |
| ⭐ 资源怎么划、方法怎么选、该返哪个状态码 |
03b |
⭐ 幂等、Idempotency-Key 协议、ETag / 条件请求 |
03c |
| 超时/重试/成本记账/缓存/假客户端 |
04 |
| SSE、缓冲坑、流式下的错误、断连 |
05 |
| 表设计、索引、迁移、连接池、事务边界 |
06 |
| ⭐ 游标分页、深翻页、过滤与排序白名单 |
06b |
| pgvector、索引选型、过滤+向量、换模型 |
07 |
| ⭐ 文件上传、413、预签名直传、传完怎么触发 |
07b |
| 认证三条路、会话、⭐ 多租户隔离 |
08 |
⭐⭐ 同源策略、CORS 预检、* + 凭证那个坑 |
08b |
| ⭐⭐ CSRF 的防线、XSS 三种形态、Content-Security-Policy |
08c |
⭐ OAuth2 授权码流程、state、PKCE、OIDC |
08d |
| ⭐ JWT 三段结构、四种绕过、吊销 |
08e |
| 不用框架的前端、AI 前端三个特殊点 |
09 |
| 收流、边流边渲染、滚动跟随、停止生成 |
10 |
| 三档队列、幂等、死信、毒药消息 |
11 |
| ⭐⭐ 三层护栏、令牌桶、熔断、成本归因 |
12 |
| 环境变量、密钥三档、多环境 |
13 |
| Dockerfile、compose、部署三选、优雅关闭 |
14 |
| 结构化日志、request_id、四个指标、告警 |
15 |
| ⭐⭐ 怎么测「同样输入不同输出」、FakeLLM、CI 里不烧钱 |
15b |
| ⭐ 上线前 6 组检查,每条带验证方法 |
16 |
| 五个动手项目 |
17 |
| ⭐ 换成 Node / Go / Java,这套东西各叫什么 |
附录B |
🔗 六、跨教程速查
| 想找 |
去哪 |
⭐ 分界 |
| 结构化输出、护栏怎么设计 |
智能体工程 16c |
那边讲设计,本板块讲工程链路 |
| 推理引擎怎么选(vLLM/SGLang) |
AI基础设施 20 |
那边是怎么选引擎,本板块是应用怎么调它 |
| 自建模型、OpenAI 兼容接口 |
全景导论 07 |
|
| RAG 策略(切分/重排/评估) |
全景导论 08 |
那边讲策略,本板块 07 讲怎么存进库 |
| HNSW / IVF 的原理 |
推荐算法 10 |
那边讲为什么快,本板块讲该选哪个 |
| 模型漂移、AB、重训 |
模型上线之后 |
⭐⭐ 本板块 15 章管服务健不健康,那一套管模型准不准 |
| 提示注入、沙箱 |
智能体工程 15 |
本板块 10 章那个「文档藏 HTML」是它的一个具体形态 |
| 数据脱敏、隐私留存 |
数据这一关 19 |
本板块 08/15 章涉及时链过去 |
| 告警为什么没人看 |
模型上线之后 08 |
本板块 15 章的告警判据来自那里 |
打卡记录保存在你的浏览器里,首页能看到总进度