Skip to content

第22章 从零构建一个生产级 RAG 系统

"The best RAG is the one that ships and keeps shipping." — 所有 SOTA 论文都不如一个能稳定迭代的 pipeline

本章要点

  • 生产 RAG 的参考架构:三条链路 + 四大服务——不绕不弯的落地蓝图
  • 四阶段交付路线:MVP(2 周)→ 离线稳定(1 个月)→ 反馈闭环(2 个月)→ 持续优化——每阶段有明确 done 标准
  • 关键代码骨架:ingest pipeline、检索链路、生成链路、评估 pipeline 四个核心 loop
  • 从 0 → DAU 10 万 的演进:架构不变、只在每个组件上逐步加能力
  • 团队配置:2-3 人起步够用、> 15 人时走专业化分工

22.1 参考架构

前 21 章的机制汇总到一个系统里、长这样:

四大服务群:

  • Gateway:鉴权 / 限流 / user_context
  • Online 检索链路:Query Understanding → Retrieve → Rerank → Pack → Generate → Cite
  • Offline 索引链路:Parse → Chunk → Embed → Index → Publish
  • Feedback:Logger → Evaluator → Memory

前 21 章每一章对应这架构里的某一段——这一章是给架构填具体选型和代码骨架。

22.2 关键组件选型(2026 年推荐)

MVP 阶段一套"不出错"的默认选型:

组件推荐备注
Web 框架FastAPI / axumPython / Rust 二选一
Embeddingbge-m3(自托管)/ text-embedding-3-small(API)中文选前
向量库Qdrant(中小)/ pgvector(复用 DB)第 11 章
BM25Qdrant 内置 / Elasticsearch选简单
Rerankbge-reranker-v2-m3第 14 章
LLMClaude Sonnet 4.6 / GPT-5 / DeepSeek V3按质量成本选
Query rewriteClaude Haiku 4.5小模型够用
评估ragas + 自建 gold set第 20 章
可观测性OpenTelemetry + Grafana标准栈
缓存Redisquery / embedding / rerank 三层
消息队列Kafka / Redpanda离线 pipeline
调度Prefect / Dagster离线 pipeline

这套组合 MVP 跑得起来、扩展性也够。大规模时只需要把某些组件升级(如 Qdrant → Milvus、Redis → Dragonfly)。

22.3 四阶段交付路线

阶段 1:MVP(2 周)

目标:能跑、能用、有 demo。

交付物:

  • 离线索引:一次性脚本、从 S3 读 100 份样本文档 → chunk → embed → 入 Qdrant
  • 在线检索:FastAPI 接口、hybrid 检索 top-10 → 喂 Sonnet → 返答案
  • 无 rerank、无 Contextual Chunk、无 rewrite
  • 简易前端(Streamlit / 一个 React 页面)

Done 标准:内部 5-10 人连续使用一周、采集 50+ badcase。

代码骨架:

python
# ingest_mvp.py
async def ingest_one(doc_path):
    doc = await parse(doc_path)       # unstructured.io
    chunks = chunk(doc, size=400, overlap=80)
    for c in chunks:
        c.vec = await embed(c.text)
    await qdrant.upsert(chunks)

# retrieve_mvp.py  
async def rag(query, user):
    q_vec = await embed(query)
    dense_hits = await qdrant.search(q_vec, filter=user_filter(user), limit=10)
    bm25_hits = await es.search(query, filter=user_filter(user), limit=10)
    merged = rrf([dense_hits, bm25_hits], k=60, top_k=5)
    prompt = pack(query, merged)
    answer = await llm.chat(prompt)
    return {"answer": answer, "citations": [c.id for c in merged]}

不到 100 行核心代码。够跑 MVP。

阶段 2:离线稳定化(1 个月)

目标:知识库能稳定每日更新、能回滚、能扩展。

交付物:

  • 离线 pipeline 用 Prefect / Dagster 编排,分段可重入(第 8 章 §8.2)
  • 版本化索引、原子切换、48 小时回滚窗口(第 4 章 §4.2)
  • 增量更新基于 content_hash(第 8 章 §8.2 方案 C)
  • 基础监控(解析成功率、索引规模、QPS、延迟)
  • 软删除 + 事件驱动(第 8 章 §8.2 避免"deleted=true 幽灵"事故)

Done 标准:连续 4 周 周度更新零事故、回滚脚本演练过一次。

阶段 3:反馈闭环和评估(2 个月)

目标:可观测、可定位、可迭代。

交付物:

  • OpenTelemetry trace(第 3 章 §3.9)
  • gold set 500 条、每日自动回归
  • ragas 评估接入、faithfulness + answer_relevance 每日看板
  • 用户 feedback 收集(thumbs up/down + 自由文本)
  • 四层评估指标(第 20 章)完整看板 + 告警
  • 初步 hybrid + rerank(bge-reranker-v2-m3)上线

Done 标准:每周能给出"本周 badcase 主要是什么类型、占比多少"的归因报告。

阶段 4:持续优化(永久)

目标:按归因报告迭代、质量和成本持续改善。

可能的优化路径:

  • Query Rewrite 和 HyDE(第 15 章)
  • Contextual Chunk(第 6 章 §6.6)
  • Rerank 微调(第 14 章 §14.5)
  • Prompt cache 和模型分层(第 21 章)
  • Agent Memory(第 18 章)
  • GraphRAG(第 19 章、如果有全局 / 多跳需求)

每次优化走归因 → 假设 → A/B → 决策 → 部署五步。数据驱动、不靠感觉。

22.4 关键代码骨架:四个 Loop

生产 RAG 的核心是四个 loop,每个 loop 独立可部署、独立演化。

Loop 1:Ingest Pipeline

python
# ingest.py (简化)
@flow(name="rag-ingest")
async def ingest_flow(doc_uris: list[str]):
    for uri in doc_uris:
        try:
            # 1. 解析
            doc = await parse_task(uri)  # cached by content_hash

            # 2. 分块
            chunks = chunk_task(doc, strategy="structured", fallback="fixed")

            # 3. Embedding (content_hash 复用 cache)
            for c in chunks:
                c.vec = await embed_task(c.text_with_context)

            # 4. Upsert + 清理旧 chunk
            await upsert_chunks(doc.id, chunks)
            await cleanup_orphan_chunks(doc.id, current_chunk_ids=[c.id for c in chunks])

            # 5. 发 event
            await event_bus.publish("doc_indexed", {"doc_id": doc.id, "chunk_count": len(chunks)})

        except Exception as e:
            await dlq.put(uri, e)

关键点:每一步都可缓存、失败入 DLQ、不阻塞其他文档。

Loop 2:Online Retrieval

python
# retrieve.py
async def retrieve(query: str, user_ctx: UserContext) -> list[Chunk]:
    # 1. Query understanding(可能并行)
    rewritten = await rewrite_task(query, user_ctx)  # 含 disambiguation + HyDE

    # 2. 并行召回
    dense_task = dense_retrieve(rewritten, user_ctx, top_k=50)
    bm25_task = bm25_retrieve(rewritten, user_ctx, top_k=50)
    dense_hits, bm25_hits = await asyncio.gather(dense_task, bm25_task)

    # 3. RRF 融合
    fused = rrf([dense_hits, bm25_hits], k=60, top_k=30)

    # 4. Rerank
    top_k = await rerank(query, fused, top_k=5)

    # 5. cache (query_hash, user_hash) -> top_k 5 分钟
    await cache.set(cache_key(query, user_ctx), top_k, ttl=300)
    return top_k

关键点:并行召回(asyncio.gather)、统一 user_ctx filter 下推到向量库和 BM25。

Loop 3:Generation + Citation

python
# generate.py
async def generate(query: str, chunks: list[Chunk], user_ctx: UserContext) -> Response:
    # 1. Context pack(U 形排列 + 结构化)
    packed = pack_context(chunks, strategy="u_shape")

    # 2. Prompt 构造(cacheable prefix + dynamic suffix)
    prompt = build_prompt(
        system=SYSTEM_PROMPT,      # cacheable
        few_shot=FEWSHOT,           # cacheable
        context=packed,             # dynamic
        query=query,                # dynamic
    )

    # 3. LLM 调用(流式)
    stream = llm.stream(prompt, cache_control="ephemeral")

    # 4. citation 验证(后处理)
    answer, citations = await parse_answer_and_citations(stream)
    grounding = await verify_grounding(answer, chunks, citations)

    # 5. 组装 response
    return Response(
        answer=answer,
        citations=citations,
        confidence=compute_confidence(grounding, chunks),
        trace_id=current_trace_id(),
    )

关键点:prompt 结构化(可 cache + 引用锚点)、grounding 后处理验证。

Loop 4:Evaluation

python
# eval.py
@schedule(cron="0 3 * * *")  # 每天凌晨 3 点
async def daily_regression():
    results = []
    for qa in load_gold_set():
        actual = await rag_full_pipeline(qa.query, qa.user_ctx)
        metrics = await ragas_eval(
            query=qa.query,
            gold_chunk_ids=qa.gold_chunks,
            actual_chunk_ids=[c.id for c in actual.retrieved],
            actual_answer=actual.answer,
            context=actual.packed_context,
        )
        results.append(metrics)

    # 上报指标
    emit_metrics(aggregate(results))

    # 告警
    if mean(results, "faithfulness") < 0.85:
        alert("Faithfulness 跌破 0.85")

关键点:每日跑、多指标聚合、低于阈值告警。

22.5 从 0 → DAU 10 万 的演进

架构不变、每个组件逐步升级:

DAU < 1000 (种子期)

  • pgvector(省)+ 单机 FastAPI
  • 无 rerank、简单 hybrid
  • 成本 < $500/月

DAU 1000 - 10000

  • Qdrant 单机、加 bge-reranker
  • Redis 三层缓存
  • 离线 pipeline 用 Prefect
  • 成本 $2000-5000/月

DAU 10000 - 100000

  • Qdrant 3 节点集群 或 Milvus
  • 微调 rerank
  • Prompt cache 上线
  • 离线 pipeline 多 worker
  • 成本 $15000-50000/月

DAU > 100000

  • Milvus 分片集群 或 Qdrant + 分片
  • 多区域部署
  • 专用 Embedding 和 Rerank 服务集群
  • Agent Memory(如果场景需要)
  • GraphRAG(如果有全局/多跳需求)
  • 成本 $100000+/月

每阶段不是推倒重来、是 在同一架构上加组件、升级配置。这是参考架构的价值——演进不需要重写核心逻辑。

22.6 团队配置演化

  • 1-2 人(MVP):全栈工程师 + 产品
  • 3-5 人(稳定期):+ 数据工程师(专门维护离线 pipeline)、+ ML 工程师(微调 rerank)
  • 6-10 人(成熟期):+ 可观测性工程师、+ 安全 / 合规工程师
  • > 15 人:按链路分组(online / offline / eval)、专业化

团队小时不要乱分工——全栈搞定一切推进快。人多后按链路拆组、每组有明确 owner。

22.7 第一天的 checklist

从零启动一个生产 RAG 项目、第一周该做的:

  • [ ] 明确业务目标(答对率、延迟、成本预算各自的硬约束)
  • [ ] 锁定知识库范围(什么文档、多大规模、更新频率)
  • [ ] 选栈(按第 22.2 节的推荐选)
  • [ ] 搭 MVP pipeline(100 份文档、一条 end-to-end)
  • [ ] 构造 50 条 gold set(真实用户问过的或人工编的)
  • [ ] 写评估脚本(ragas 最小集)
  • [ ] 画监控看板(最少 QPS、延迟、成本、faithfulness)
  • [ ] 写事故响应 runbook(第 4 章 §4.8 类型)

前 8 项做完、你有一个能迭代的基础。少任何一项、都会成为后续的瓶颈。

22.8 常见失败模式和解药

生产 RAG 项目常见的失败模式:

失败 1:追求 SOTA 忽略稳定

项目组花 2 个月实现 GraphRAG / Agent Memory,产品还没上线。解药:先出 MVP 收真实反馈,高级技术按需引入。

失败 2:没有 gold set 盲优化

改了 prompt、改了 chunk、改了 embedding、都"感觉更好"——但没回归验证。解药:gold set 优先级 = P0,任何改动先过回归。

失败 3:忽视离线链路

团队所有精力在优化在线链路、离线 pipeline 用脚本凑合——3 个月后知识库更新一次出 bug。解药:阶段 2 的工程投入不能省

失败 4:过早优化成本

MVP 阶段就纠结"这行代码会不会多花 $0.001"。质量都没到、省钱白搭。解药:先质量再成本——先证明系统有用、再降费用。

失败 5:不用真实数据

Demo 用 few-shot 精选例子跑、上线用真实用户 query 就崩。解药:MVP 开始就用真实数据(脱敏后)评估。

失败 6:没有回滚机制

索引 / 模型 / prompt 改完没办法回滚——出事故只能硬扛。解答:每项改动都有明确的回滚路径,部署前演练一次。

22.9 性能回归的常见触发器

生产 RAG 上线半年到一年、性能回归几乎必然发生。提前知道触发器、减少事故:

  • 知识库自然漂移:新文档质量下降、或旧文档失去时效相关性。召回命中率慢慢降、用户抱怨变多
  • 用户查询模式变化:产品推新功能后、用户问法从"怎么用 A"转"A vs B 的区别"——GraphRAG 能力不够会暴露
  • 第三方服务降级:Embedding API 升级导致向量空间略变、老索引和新 query 不兼容。Anthropic / OpenAI 偶有静默升级
  • 依赖库升级:LangChain / LlamaIndex 主版本升级经常改 API;某个依赖 bump 可能改变 chunking 行为
  • 部署环境变化:从 A100 迁 H100、CPU 容器换架构——推理数值精度略有差异、边缘 case 表现变化
  • 数据源污染:爬虫引入一批错误文档(网页改版、PDF 解析器 bug)、悄悄进索引后污染检索

预防靠持续的自动化评估(第 20 章)+ 关键依赖锁版本 + 变更审批流程。没有这三道防线、早晚中招。

22.10 生产 RAG 的组织学

技术之外、组织形态影响 RAG 项目能否持续。

产品 vs 工程的张力

RAG 有两条价值路径:

  • 产品路径:做用户体验、算对的答案、降低挫败感
  • 工程路径:压延迟、降成本、提吞吐

两条路经常冲突——为了 3 个点的答对率加 500ms 延迟值不值?没有产品经理 + 工程师共识、项目很容易卡在决策上。

成熟团队的做法:把三元约束(质量/延迟/成本)量化成指标、给每个指标定硬门槛。越过门槛的改动自动合入、跨门槛的停下来讨论。这比"感觉能不能上"高效。

反馈机制的组织成本

第 20 章讨论的三层评估(离线回归 / 在线采样 / 人工抽样)都需要持续人力投入

  • 人工抽样每周 4-8 小时
  • Gold set 季度刷新 1-2 天
  • Badcase 归因 review 每月一次 4 小时

这些工作没人干、评估就流于形式、数据质量会退化。团队里必须有明确的 owner 负责评估 pipeline、不能靠"大家有空看看"。

可持续的工作节奏

RAG 是马拉松、不是冲刺。推荐节奏:

  • 周一 status review(看数据、定本周优先级)
  • 周三 deep work 日(不开会、只做开发)
  • 周五 deploy + 复盘

这套节奏让质量改善是连续的、而非大起大落。

22.11 和现有业务系统的集成

生产 RAG 很少是孤立服务——需要和现有业务栈集成。集成点和对应的设计决策:

集成点 1:鉴权系统

RAG 不自己做登录——继承业务的鉴权:

  • SSO / OAuth:企业客户统一身份(Okta、Azure AD、飞书 / 钉钉)
  • JWT 传递:业务 gateway 签 JWT、RAG 服务验签读 user_context
  • 多租户边界:从 JWT 读 tenant_id、下推到向量库 filter

不要造轮子、复用现有鉴权——减 50% 实现成本、合规审计也直接继承。

集成点 2:客服 / 工单系统

客服场景 RAG 的典型集成:

  • 客户发消息 → 客服系统路由 → RAG 答初稿 → 客服人工 review → 发出
  • 命中率高的问题 → 自动闭环、不用人工
  • 命中率低的问题 → 升级人工客服 + trace 用于改进

集成靠 webhook 或 event bus——RAG 订阅"新消息"、发"候选答案"。

集成点 3:CMS / 知识库源

文档更新要驱动 RAG 索引更新:

  • CMS webhook:Confluence / Notion / SharePoint 改动 → 推 event 到 RAG 队列
  • 文件系统监听:S3 bucket 事件、OSS 对象存储通知
  • 定期全扫:兜底防止 webhook 丢

集成点 4:产品 UI

RAG 的响应 UI 不是单独页面——通常嵌入产品某处:

  • 客服聊天窗
  • 帮助中心搜索框
  • 产品内侧边栏 AI 助手
  • IDE 插件(代码 RAG)

UI 集成要关注:流式渲染 / 引用高亮跳转 / 反馈按钮 / 对话历史持久化。这些属于前端工程、但 API 设计要支持。

集成点 5:可观测性栈

复用企业已有监控:

  • 延迟 / 错误率进 Grafana + Prometheus
  • 业务埋点进分析平台(Amplitude / Mixpanel / GrowingIO)
  • 错误进 Sentry
  • Trace 进 Jaeger / Tempo

不要为 RAG 单独搭监控栈——维护不起。

22.12 长期维护的心智模型

生产 RAG 上线后的工作不是"完成了"——是"开始了"。三个心智模型:

  • 它是一个生命体:文档更新、用户行为变化、LLM 升级——系统要跟着变
  • 它是一个团队项目:一个人搞不定长期运维——必须有团队 + 明确 onboarding 文档 + 交接流程
  • 它是一个产品:不只是技术栈、还要看用户价值——功能要迭代、场景要扩展

长期健康的 RAG 有如下特征:

  • 每周有明确的迭代目标(新 chunking 策略 / 新 rerank 模型 / 新 domain 接入)
  • 每月有一次完整的归因 review
  • 每季度有一次架构健康检查(延迟漂移、成本漂移、质量漂移)
  • 每半年评估一次栈的新组件(新 Embedding 模型、新向量库版本、新 rerank 方案)

22.13 从这本书出发

这本书讲完了 RAG 的主要工程机制——但没有一本书能讲完所有细节。真正的生产经验来自你在自己项目里的:

  • 每一次 badcase 的归因
  • 每一次架构选型的权衡
  • 每一次线上事故的复盘
  • 每一次和用户对话里发现的盲点

这本书是起点不是终点。推荐把本书当作参考手册——遇到问题时翻相关章节、结合自己的上下文做决定。

22.14 合规、审计与灾难恢复

RAG 系统处理的是企业最敏感的两类数据——内部知识用户对话。这两样的合规和容灾在 POC 阶段可忽略、生产上线时是硬要求。这一节把前面章节散落的合规话题(第 7 章权限、第 18 章 memory 隐私、第 8 章增量)整合成上线前的综合视角。

合规框架的四个维度

  • 数据分级:public / internal / confidential / restricted 四级、chunk 级别打标、权限下推到向量库 filter(第 7 章)
  • 审计日志:谁在什么时间检索了什么 chunk、最终 LLM 看到了什么 context、生成了什么答案
  • 用户权利:GDPR / PIPL 要求可删除、可导出、可审计——memory 和对话历史是重灾区
  • 行业专项:医疗 HIPAA、金融等保、欧盟 AI Act 等各有细则

生产上线前这四项都要有明确的实现负责人、不能全部"以后再说"。

审计日志的最小字段集

无论什么合规框架、审计日志至少要能回答 "谁在什么时候问了什么、看到了什么、答了什么":

字段为什么必要
trace_id串联同一请求的 retrieval / generation
user_id + tenant_id定位"谁"、多租户边界
query + timestamp原始问题 + 时间
retrieved_chunk_ids + source_docsLLM 看到了哪些内部资料
prompt_hash + model + prompt_cache_hit生成阶段的决策证据
answer + citations系统给出的最终答案
user_feedback用户事后反馈(如有)

日志进对象存储(S3 / OSS)+ 索引进 OpenSearch / ClickHouse——按需查询。保留周期按合规要求:GDPR 6-12 月、金融常 5-7 年、医疗 HIPAA 6 年起。

日志本身也含敏感信息——日志的访问也要审计,这不是套娃、是合规底线。

用户权利的工程落地

GDPR / PIPL 赋予用户三项关键权利、对应三个工程能力:

  • 删除权(right to be forgotten):用户请求 → 清除所有相关数据

    • 包括 memory facts、对话历史、日志里的 user content、可能的 embedding index(需要点对点删除)
    • 典型 SLA:72 小时内完成
    • 工程实现:给每个用户一份 data map,删除时按 map 一次性清扫
  • 导出权(data portability):用户获取自己的所有数据副本

    • 包括历史对话、memory、profile
    • 通常 JSON 或 CSV 格式、打包下载链接
    • SLA:30 天内
  • 访问审计权:用户能查看"谁在什么时候访问过我的数据"

    • 对企业客户尤其重要("给我看谁用 AI 助理查过我的合同")
    • 需要预留访问日志的用户可见视图

这三项如果事后补、会发现数据散落在向量库、PG、Redis、S3、日志系统各处——初始架构设计时就要统一 user_id 路径,事后集成难度 10 倍。

灾难恢复:RPO 与 RTO 设计

灾难恢复计划要明确两个指标:

  • RPO(Recovery Point Objective):事故后能容忍丢失多少数据。典型 RAG:15 分钟到 1 小时
  • RTO(Recovery Time Objective):事故后多久能恢复服务。典型 RAG:30 分钟到 4 小时

达成这些目标靠三层备份

层级内容恢复速度成本
L1 元数据Postgres(chunk metadata / user profile)分钟级 WAL 流复制
L2 向量索引Qdrant / Milvus snapshot小时级(重建快)
L3 原始文档S3 跨区复制分钟级

L2 是重点——向量索引重建要几小时。策略是保留最近 3 个 snapshot(日级),事故时拉最近一份恢复。业务数据用 L1+L3 兜底、L2 丢了大不了重建。

灾难演练不能省

备份有但没演练过 = 相当于没备份。典型事故模式:备份 6 个月里一直跑、但从没验证过能恢复——真到需要时发现 snapshot 格式不兼容、恢复脚本半年没更新已失效。

生产 RAG 的演练节奏:

  • 月度:单组件恢复(向量库从 snapshot 恢复、PG 从 WAL 回滚)
  • 季度:完整链路恢复(从全站宕机到恢复服务)
  • 年度:多区域故障切换(primary region 整挂时切 secondary)

演练结果写进 runbook——下次事故时按 runbook 操作,而不是现场推理。

数据驻留与跨区域

欧盟客户的数据不能出欧盟、国内部分客户的数据不能出国——数据驻留要求在架构早期就决定:

  • 单区域部署 + 多租户共享存储:简单、但不支持全球客户
  • 多区域隔离部署:每个区域独立全栈(向量库、Redis、PG)、用户数据 sticky 到所属区域
  • 混合模式:元数据跨区、敏感数据本区——工程复杂

多区域的难点不是部署、是数据一致性 + 版本同步:知识库更新时所有区域索引要一致。主从复制 + 事件总线是主流方案。

合规的反模式

生产 RAG 里常见的合规反模式:

  • "先上线再补合规":初期不打 audit log、不做权限分级——等合规审查才补、代价是重写半个系统
  • 权限只在 UI 层:后端 API 不做 user_ctx filter 下推、聪明用户绕过 UI 拿到别人数据
  • 日志里留明文 PII:身份证、银行卡直接写 log——合规审计第一条就挂
  • 备份从不演练:以为 backup 脚本跑了就稳——真出事时发现不能恢复

生产上线前做一次合规 checklist 审查(ISO 27001 或公司内部 checklist),比上线后 fire-fighting 省 10 倍代价。

22.15 事故响应 playbook:RAG 的 on-call 手册

§22.8 列了失败模式、§22.9 讲了性能回归——都是事前防御。这一节补上事中响应:线上出事了怎么办。RAG 的事故特性和传统 Web 服务不同——一个 RAG 事故可能是检索错、生成错、或两者组合、用户感知是"答案不对"而非"服务 500"。没有专门的 playbook、on-call 同学只能现场摸索、MTTR 拉长到小时级。

事故的典型分类

按严重度的响应时限

级别响应时限处置团队通知范围
P015 分钟核心团队 + 安全 + 法务CTO + 合规 + 相关业务
P130 分钟on-call + 团队 lead团队全员 + 业务接入方
P22 小时on-call团队内部
P324 小时指派专人定期 review

P0 事故不等"定位清楚再动手"——先立即止损(关 feature flag、切 fallback、封用户等)、事后再慢慢查。

响应三阶段

检测:监控指标 + 告警 + 用户反馈三源头。关键是不要漏报——降级 + 告警宁可假阳多、别漏真阴。

定位:按 RAG 链路从尾到头查:

  1. 用户看到的答案 → 查 trace
  2. Trace 里的 prompt 和 context → 看检索结果合理吗
  3. 检索结果 → 看 query 是否合理
  4. query → 看请求参数

多数事故卡在前两步就能定位。第 3、4 步属于深度事故。

修复:分两档——

  • 紧急缓解:关 feature、切 fallback、回滚版本——分钟级
  • 根因修复:找到 bug、补代码、加测试——几天级

两档并行、缓解优先。

Playbook 模板

每类常见事故都应该有 playbook。例子 "LLM API 高错误率"

markdown
# Playbook: LLM API 错误率 > 5%

## 症状
- generation_error_rate > 5% 持续 2 分钟
- 用户报告"答不出来"

## 立即动作(5 分钟内)
1. 确认告警真实性:看 Grafana 的 error 分布
2. 切到 fallback 模型(Sonnet → Haiku):`config.llm.primary = "haiku"`
3. 通知业务接入方"可能质量降级"

## 深度定位(30 分钟内)
1. 查 error 类型:429 / 500 / timeout
2. 查 Anthropic status page
3. 查是否刚上线了新 prompt 或模型参数
4. 查是否被上游流量打崩(QPS 突增)

## 可能根因
- Anthropic 端故障 → 等恢复 + fallback
- rate limit 触发 → 联系 sales 扩额度 + 限流
- 新 prompt 导致返回异常 → 回滚 prompt
- 上游流量异常 → 排查上游

## 回滚步骤
- Prompt 回滚:`git revert <commit>` + deploy
- 模型回滚:config 切回
- 完全失败:启动 static fallback

## 复盘要求
- 24 小时内产出 timeline
- 1 周内补修复 + test

每个 P1+ 事故都应该有对应 playbook——没有就写、事故结束就维护。Playbook 库是团队运维能力的沉淀。

常见定位套路

  • recall 降、用户投诉答不准:查 embedding 服务版本、向量库索引版本、最近是否重建
  • 延迟涨、但错误率正常:查下游服务(向量库、rerank)的 P99、多半某个服务变慢了
  • 成本暴涨但 QPS 稳定:查 token / request 的分布、通常是 prompt 变长或 context top-k 调大
  • 某个租户频繁报错:查该租户的索引 size、metadata、是否数据异常
  • 某类 query 答错:query classifier 可能误路由、检查路由分布

这些套路不是万能的、但 80% 的事故能用它们快速定位。

事后复盘(postmortem)的要求

每个 P0/P1 事故都要写复盘文档:

  • Timeline:从事故发生到完全恢复的分钟级时间线
  • 根因:不是"XXX 坏了"、是 "为什么 XXX 坏了" 五问到底
  • 影响:多少用户、多少请求、多少金额、合规影响
  • 做对的:这次响应里哪些机制帮了忙(告警准、playbook 有效等)
  • 做错的:哪些机制没起作用、或决策慢了
  • Action items:分 P0 立即修 / P1 一月内 / P2 季度内

复盘不对人——对系统和流程。目标是"下次更快更准"、不是追责。追责文化会让事故被隐藏、损害长期运维。

On-call 值班的组织

  • 轮值:团队人均每 4-6 周值一次周、防止疲劳
  • 交接:周交接会过一遍上周事件、pending 修复项、playbook 更新
  • 培训:新 on-call 先跟班 2 周、熟悉所有主要 playbook
  • 权限:on-call 有"宣告降级"的权限、不用等 lead 批准

on-call 的核心诉求是"授权和 playbook"——没有这两样、on-call 同学被困在"不敢动" + "不知道动什么"的死循环。

事故驱动的系统演化

成熟 RAG 团队的演化 60% 由事故驱动:

  • 事故 → 复盘 → Action item → 代码/流程改进
  • 新 playbook → 下次事故 MTTR 压缩
  • Action item 积累 → 季度架构演进

没有事故就"平稳"了——往往是没发现问题而已。成熟团队每季度至少 2-3 个 P1/P2 事故是健康信号——说明告警灵敏、用户反馈通畅、团队在学。

22.16 自建 vs 商用 vs 开源:组件选择的决策框架

§22.2 给了具体组件选型推荐——但每个组件都有自建 / 商用托管 / 开源自托管 三条路。选错一个方向、后期切换代价巨大。这节给出跨组件通用的决策框架——不只是"选哪个具体产品"、而是"选哪种部署方式"。

三条路的本质区别

每条路的深层特征:

  • 自建:代码 100% 自控、工程成本极高。除非是核心差异化能力、否则不建议
  • 商用托管:上手快、运维零——但 TCO 可能远超自托管、且被厂商锁定
  • 开源自托管:需要 DevOps 能力、但长期最经济 + 可迁移

按组件的推荐默认选择

组件默认推荐原因
LLM商用 API模型更新快、自托管 GPU 贵
Embedding开源自托管(小规模用商用)可批量、成本可控
向量库开源自托管(MVP 可用托管)数据所有权敏感
Rerank开源自托管模型小、推理便宜
BM25开源(Elasticsearch / Tantivy)工程成熟、无需商用
Memory商用托管(Zep / Letta)生态年轻、自建代价高
Observability开源栈(Prometheus + Grafana)和现有运维一致
Evaluation开源(ragas / trulens)框架为主、不值得商用

这只是默认起点——按下面决策表微调。

决策表:三个问题

问 3 个问题就能大致定方向:

  1. 这个组件是不是你的核心差异化?

    • 是 → 可能要自建 / 定制
    • 否 → 直接用现成(商用或开源)
  2. 规模大到自托管有 TCO 优势吗?

    • < 小规模 → 商用(运维成本不划算)
    • 中大规模 → 开源自托管
    • 超大规模 → 可能要自建专用组件
  3. 数据 / 合规约束有多强?

    • 强(金融 / 医疗 / 政务) → 自托管优先
    • 中等 → 看区域 / 厂商承诺
    • 弱(纯内部工具) → 商用省事

三个问题拍板基本不会错。

详细 TCO 对比

向量库 为例、算一年 TCO(100 万 chunk × 1024 dim 规模):

商用托管(Pinecone / Qdrant Cloud)

  • 服务费:$300-600/月
  • 运维成本:近 0(每月 0.05 FTE ≈ $500)
  • 一年 ~$10K

开源自托管(Qdrant / Milvus)

  • 硬件:$200/月(1 台 32GB RAM 云主机)
  • 运维:0.2 FTE × 每年 $200K = $40K
  • 一年 ~$42K

商用看起来便宜? 但只在小规模——10 倍规模时:

规模商用自托管
100 万 chunk$10K$42K
1000 万 chunk$100K$60K
1 亿 chunk$500K+$200K

大规模自托管更省钱——因为商用按量几乎线性、自托管的运维 FTE 基本固定。拐点约在千万级。

厂商锁定的真实成本

商用路线的隐藏成本:锁定

典型锁定形式:

  • API 兼容性:换厂商 SDK 要重写接入代码、2-4 周
  • 数据格式:Pinecone 的向量导出到 Milvus 需要格式转换
  • 功能特性:某厂商独有的 filter / reranking 一旦用了、换走要找替代
  • 定价:厂商涨价时你只能接受(或承担迁移成本)

锁定成本不是 0——在做商用选型时要有退出计划

  • 数据能导出吗?(能 import 其他厂商)
  • API 有标准协议吗?(如 OpenAI-compatible API)
  • 定价历史稳定吗?(看 2-3 年历史、有无频繁涨价)

看起来悲观、但 3-5 年 RAG 项目周期内、厂商可能收购、停服、涨价——每一样都可能发生。

什么时候应该自建

自建是最激进选项——一般不推荐、但某些场景值得:

  • 极度规模化:运营全球性 RAG、单位成本的 5% 优化都值
  • 独有算法:用了某篇前沿论文的方法、开源实现不存在
  • 合规硬要求:某些国家 / 行业不允许任何外部组件
  • 核心 IP:这个组件的技术本身是公司价值

大多数 RAG 项目没有这些条件——自建只是徒增复杂度。

混合策略:分层选型

最成熟的 RAG 项目常是 混合

  • LLM:商用 API(Claude + GPT 双厂商、互相备份)
  • Embedding:开源自托管(bge-m3)
  • 向量库:开源自托管(Qdrant 集群)
  • Rerank:开源自托管(bge-reranker)
  • 其他:按需商用 / 开源

混合策略的好处:

  • 成本可控(大头组件自托管)
  • 核心能力不锁死(LLM 双厂商)
  • 工程复杂度 balanced

迁移的真实难度

不同组件迁移难度天差地别:

组件迁移难度典型工期
LLM(Claude ↔ GPT)易(prompt 改、API 改)1-2 周
Embedding 模型中(需要全量重 embed、§9.13)2-4 周
向量库中(数据导出 + schema 映射)4-8 周
Rerank易(模型替换)1 周
BM25 引擎中(Elasticsearch → Tantivy 等)3-6 周
Memory 系统难(状态迁移)8-12 周

规划选型时考虑迁移难度权重——难迁移的组件选型要更保守。

更新这些决策的频率

技术格局每年变化——决策不是一劳永逸:

  • LLM 市场:每季度 review(新模型 / 新定价)
  • Embedding:每半年 review(SOTA 更新)
  • 向量库:每年 review(新版本特性)
  • 其他:每年一次

不 review 就是"被过时的决策绑架"——三年前选的组件现在可能有更好的替代。

选型的组织纪律

这些决策不能一个人拍板——典型流程:

  • 小决策(单个组件):Tech Lead + 团队讨论
  • 中决策(组件换厂商):Eng Manager + 架构师 review
  • 大决策(整体技术栈方向):CTO + 工程 VP + 业务代表

明确决策文档(ADR、Architecture Decision Record)——记录为什么选、考虑过什么替代、什么时候 review。没文档的决策 6 个月后没人记得为什么——再改又从头来。

22.17 RAG 项目的 KPI 设计:北极星 + 平衡指标

前 16 节讲了架构、交付、运营——但团队怎么知道项目做得好不好?技术指标很多(recall、P99、faithfulness)——哪个才是"真北"?很多 RAG 团队跟不清自己的 KPI——一会儿追 recall、一会儿追延迟、一会儿追成本——没有统一方向。这节给 RAG 项目的 KPI 设计一套体系。

为什么 RAG 项目常没有北极星

没有统一北极星的后果:团队 7 个人、4 个方向、每个都觉得"我的方向最对"——效率低、决策慢。

三层 KPI 结构

三层的关系:工程指标改善 → 产品指标改善 → 业务指标改善。任一链条断了、说明定义有问题。

北极星指标的选择

北极星是业务层唯一最重要的指标——代表项目成败。RAG 项目的典型候选:

  • 客服 RAG:人工转接率(越低越好)、AHT(平均处理时间)、客户满意度
  • 内部知识问答:员工月均使用次数、替代人工咨询的比例
  • 研发 Copilot:代码采纳率、开发提速百分比
  • 销售 assistant:辅助成交的 deal 数、销售生产力提升

共同特点:直接和业务价值挂钩、不是工程指标的代理。

平衡指标:防止走偏

单一北极星有副作用——容易被"gaming"。平衡指标防止这个:

北极星风险平衡指标
采纳率系统拍用户马屁、满意度虚高faithfulness(答案必须基于证据)
使用次数刷次数、答案质量不重要用户满意度
转接率系统乱答、用户不转接但不满后续 NPS / 复购
代码采纳采纳了但 bug 多PR merge 率 / 后续 revert

北极星 + 至少 2 个平衡指标 = 完整 KPI 体系。单看北极星会被游戏。

按角色的 KPI

不同角色看不同指标是正常的——但都要能链回北极星:

  • 工程师:recall / P99 / cost(工程层)
  • ML 工程师:faithfulness / NDCG(工程到产品)
  • 产品:CTR / 满意度 / 追问率(产品层)
  • 业务:采纳数 / 节省时间(业务层 = 北极星)
  • CEO / 管理层:ARR / 毛利 / 留存

团队每周 review 时、每个角色看自己的层、但能说清自己指标和北极星的关系。没法说清的指标——可能不值得关注。

KPI 的演化

RAG 项目不同阶段、KPI 重心不同:

阶段 1 MVP(1-2 月)

  • 北极星:能跑通 demo、内部能用
  • 工程:基础可用性(上线时间、基础 recall)

阶段 2 稳定化(3-6 月)

  • 北极星:内部 DAU 增长、使用频次
  • 工程:P99 延迟、错误率

阶段 3 商业化(6-12 月)

  • 北极星:付费用户数、ARR
  • 工程:成本 / 用户、单位经济学

阶段 4 规模化(12+ 月)

  • 北极星:LTV / CAC、毛利
  • 工程:多租户、全球化、合规

KPI 跟着阶段换——不是一套终身用。

OKR 的具体写法

季度 OKR(Objectives + Key Results)示例:

text
Objective: Q2 把企业内部 RAG 采纳率从 30% 提到 50%

Key Results:
1. 答案满意度(thumbs up rate)从 70% 提到 82%
2. P99 延迟从 2.5s 降到 1.8s
3. 覆盖知识库从 80% 部门扩展到 95%

不是 Key Results:
× 升级到 rerank v2(这是 action、不是 result)
× recall 提 3 点(这是工程指标、不直接对应 objective)

OKR 要求 Key Results 是可测量结果——不是"做了什么"、是"达到了什么"。

KPI 的反模式

  • 指标越多越好:20 个 KPI、团队不知道优先级、全都做不好
  • 北极星选工程指标:recall 是工程指标、不是北极星——业务不关心
  • 不和 compensation 挂钩:KPI 停在口头、没约束力
  • 不更新:半年前定的 KPI、项目已经换方向、指标还没变
  • 只看均值:均值漂亮但 P99 崩、长尾用户流失

数据驱动的组织文化

好的 KPI 只是起点——需要组织文化配合:

  • 每周 review、面对数据不回避
  • 错了就承认、不粉饰
  • 数据指向什么、就做什么——不是先做再找数据支持

这种文化不是技术问题、是领导力问题——但没有它、最好的 KPI 设计也落不了地。

从评估到 KPI 的桥接

§20.18 讨论了评估到 action 的闭环——KPI 是这个闭环的上层目标

text
业务 KPI(如采纳率)

产品指标(如满意度)

工程指标(如 faithfulness)

评估 gold set + badcase

Action items

每层都要能链到上一层——否则就是"工程自 high"。

不要忘了成本维度

很多 KPI 讨论只谈"好"——但好的代价同样关键。KPI 里必须有:

  • 单位成本(cost per useful answer)
  • 团队效率(features per quarter)
  • 系统复杂度(components / tech debt)

光看"好"不看"代价"的 KPI 会导致过度工程——做了很多技术先进的东西、但性价比低。

最终:KPI 是沟通工具

KPI 不只是度量——是跨角色沟通工具。定好 KPI 后:

  • 工程师知道"我改这个能提升业务"
  • 产品知道"工程做了什么、对业务多少帮助"
  • 业务知道"系统进步到哪、下一步在哪"

没有 KPI、团队的每次讨论都要从头对齐——效率 10 倍降。这是成熟团队的分水岭之一。

22.18 新人 onboarding 到 RAG 项目

RAG 项目的复杂度让新人 onboarding成为挑战——不是单纯学 API、是理解一套复杂系统。做得好的团队、新人 1-2 周上手;做得差的、新人 2-3 月还没进入状态、质量差 10-20×。这节给出 RAG 项目 onboarding 的结构化方法——让团队成员快速贡献、知识得以传承。

Onboarding 的挑战

不做好 onboarding——新人靠自己摸索几个月、团队效率低。

三阶段 onboarding

Week 1:基础和环境

  • 读本书 ch1-4 了解 RAG 全貌
  • 了解业务(产品经理 1 小时 intro)
  • 搭好本地环境(跑通 demo)
  • 看系统架构图 / 组件清单
  • 读关键代码的骨架(不是所有、核心 loop)

Week 2:深入细节

  • 按工作方向深入(后端 / ML / 前端各读对应章节)
  • 看 recent incidents 的 postmortem
  • 跟班 on-call 观察
  • 做第一个小 task(修一个 known bug)

Week 3-4:产出

  • 独立做一个功能
  • 参加 code review 和 design review
  • 开始加入 rotation
  • 有 mentor 指导

每个阶段有明确 deliverable——不是"自学完事"。

必读资料清单

给新人的材料 package:

  • 本书:按角色重点章节
  • 内部架构文档:这个 RAG 项目的具体架构
  • 关键 postmortems:过去 1 年的事故复盘(学团队的教训)
  • Runbook:on-call 手册
  • API spec:外部 / 内部 API 文档
  • 关键论文:Contextual Retrieval、Lost in the Middle 等

按清单读——不是"有空再看"。

必会工具清单

新人要熟悉的工具:

  • 代码环境:IDE、git、CI 流程
  • 数据工具:SQL、Python / pandas
  • 监控工具:Grafana、Jaeger(看 trace)
  • 云工具:K8s、AWS / GCP CLI
  • AI 工具:LLM playground、Gradio 等

不熟的工具——先学这些、再做 RAG 的任务。

导师制(Mentor)

每个新人配 mentor:

  • 入职第一月每日 15 分钟 check-in
  • 第二月每周 1 小时 sync
  • 第三月独立后仍 available for questions

Mentor 不是只答问题——传文化和"为什么"

  • 为什么选这个向量库
  • 为什么 chunk size 是 400
  • 过去踩过什么坑

这些 why 只能口传——不是文档能完全覆盖的。

第一周的具体任务

推荐给新人的任务类型:

  • 修一个小 bug:能接触真实代码、小风险
  • 改一个小 UI:快速有成就感
  • 加一个简单指标:了解监控
  • 写一个单元测试:了解 CI

让新人第一周做:

  • 改核心 prompt(风险高、需要背景)
  • 升级依赖(可能引入 regression)
  • 重构(没背景会搞砸)

循序渐进——从小到大。

知识传承的文档

关键文档每季度 review 更新:

  • 架构决策记录(ADR):每个重要决策的背景和 trade-off
  • Postmortem 库:按时间线和类型索引
  • On-call runbook:事故响应手册
  • Glossary:术语表(避免新人不懂内部黑话)
  • FAQ:常问问题和标准答案

文档不更新 = 新人被误导——定期 review 是纪律。

知识的口传阶段

有些东西永远无法写进文档

  • 为什么 Claude 比 GPT 在我们场景好——靠实验感觉
  • 哪类 query 容易答错——靠 oncall 经验
  • 哪个团队好合作、哪个难——靠人际历史

这些靠日常对话传承——mentor / code review / 闲聊——文化的一部分。

新人的安全网

避免新人"一个错误毁掉生产":

  • 沙箱环境:新人先在 staging 试、不直连 prod
  • Code review:所有改动必过 review
  • 权限限制:新人 3 月内没有 prod 写权限
  • Rollback readiness:改动能快速回滚

这些限制保护新人也保护系统——不是不信任。

Onboarding 的反馈机制

新人入职 1 月、3 月、6 月做 retro:

  • 哪些文档有用
  • 哪些缺失
  • 哪些过时
  • 哪些工具慢

基于反馈更新 onboarding 材料——onboarding 本身是持续迭代的产品

新人的贡献里程碑

典型节奏:

  • Week 2:第一个 PR(小改动)
  • Month 1:独立完成小 feature
  • Month 3:负责一个组件(和 mentor 搭档)
  • Month 6:能 own 一块区域、帮新新人 onboard
  • Year 1:熟练、可以 mentor 新人

超出这个节奏说明有问题——要么 onboarding 太慢、要么 setting up 有问题。

Onboarding 的投入和 ROI

新人 onboarding 成本:

  • Mentor 时间:每周 3-5 小时 × 3 月 = 40-60 人时
  • 文档维护:每季度 1-2 人天
  • 新人产出损失:第 1 月接近 0、第 2-3 月 50%、第 4 月 80%

ROI:

  • 好 onboarding:3 月后新人 100% 产出
  • 差 onboarding:6-12 月才 100%、中间可能走人

每个 onboarding 成功 = 一个长期贡献者——长期 ROI 极高。

团队扩张时的 onboarding 挑战

团队从 5 人到 20 人——onboarding 的 bottleneck:

  • Mentor 不够(老人都当 mentor、没时间做项目)
  • 文档跟不上(系统变化快、文档滞后)
  • 文化稀释(老人的 "常识" 新人不知道)

应对:

  • 指定 onboarding owner:专人负责材料和流程
  • 把 mentor 时间作为正式工作:不是"义务"
  • 分层 onboarding:新人 → old 新人 → 老人、传承链

Onboarding 的文化信号

一个团队的 onboarding 质量是文化信号

  • Onboarding 好 = 团队重视人才、愿意投资
  • Onboarding 差 = "你自己搞定"、人才流失

招聘时候选人会问"onboarding 怎么样"——回答能看出团队成熟度。

反模式

  • "新人自学":只给仓库地址、爱看不看
  • Mentor 是负担:没认可、老人不愿做
  • 文档没 owner:缺失和过时无人修
  • No feedback:不问新人反馈、不改进
  • 权限太宽:新人有 prod 权限、一不小心毁坏

Onboarding 和知识传承是长期工程

Onboarding 不是 "来一个人做一次"——是组织的持续工程

  • 人员流动必然发生
  • 系统持续变化
  • 文档要跟
  • 文化要传

这项投资看不到短期 impact、长期(2-5 年)决定团队能否持续壮大。把 onboarding 做好的 RAG 团队、比没做的竞争力高两个级别

22.19 全书回顾

22 章的核心骨架:

六个部分串起一个完整知识体系。每个部分的核心 take-away 在各章的"本章小结"里——本书的末尾不再复述。

22.20 跨书关联和延伸阅读

本书和系列其他书的呼应:

  • 《LangGraph 设计与实现》:RAG 作为 Agent 的一个 node、和其他工具节点编排
  • 《Tokio 源码深度解析》:异步 runtime 底层——RAG 的在线链路大量依赖 async
  • 《Hyper 与 Tower:工业级 HTTP 栈》:RAG 的 API gateway 和 HTTP 中间件模式
  • 《Serde 元编程》:trace / schema / 数据契约的序列化基础
  • 《vLLM 推理内核深度解析》:LLM serving 侧优化——降 RAG 推理成本
  • 《MCP 协议》:Agent 如何标准化地访问 RAG 作为 tool / resource
  • 《Axum 设计与实现》:如果用 Rust 写 RAG 服务、axum 是主流选择

推荐的外部资源:

  • 论文:BEIR、MTEB、ColBERT v2、Contextual Retrieval、Lost in the Middle、HyDE、MemGPT、Microsoft GraphRAG
  • 框架:LangChain、LlamaIndex、Haystack、ragas、trulens
  • 博客:Anthropic Research、LangChain blog、LlamaIndex blog、Qdrant blog、Cohere blog

22.21 结语

RAG 从 2023 年的新概念到 2026 年已经是 AI 应用的标准基础设施。它将继续演化——随 LLM 能力、Embedding 质量、向量库性能、Agent 架构的变化而调整。但核心原则会稳定:

  • 知识带边界进入索引、按业务语义检索、按证据生成、按引用验证

这四句话是本书 22 章的压缩版。记住它们、其他的细节按需查阅。

最后给一个建议:把 RAG 系统当作一个活的项目维护——不是一次性交付。它的质量取决于你每周每月对它的关注。越持续投入、越能长期获得回报。

祝你的 RAG 项目上线顺利。Happy retrieving。

基于 VitePress 构建