20 · RAG 与 Agent 的服务端落地
RAG 和 Agent 在笔记本里跑通只是开始,做成生产 API 才是你的目标。本篇讲「离线索引 + 在线检索 + 生成 + Agent 编排」的服务端工程化:延迟、并发、权限、成本一个都不能少。
速览卡
| 项 | 内容 |
|---|---|
| 一句话定位 | 把 RAG 与 Agent 从 Jupyter 原型变成稳定、可观测、可上线的后端服务 |
| 核心内容 | RAG 全链路(ingestion/retrieval/generation)、向量库与重排、Agent 状态与工具编排、多租户隔离、生产性能与评测 |
| 读完能回答 | RAG 和 Agent 在生产和服务端有什么区别?向量检索放在哪一层?Agent 的状态怎么管理? |
| 相关板块 | C19 · AI 服务端集成 | C13 · 缓存与 Redis | C21 · AI 服务可靠性 |
前置:先读 G 域实操 把原型跑通,本篇专注「生产化」这一跳。
一、从笔记本到生产:差在哪里
| 维度 | Jupyter 原型 | 生产服务 |
|---|---|---|
| 数据 | 手动灌几个文档 | 持续接入、增量更新、清理 |
| 检索 | 一次性查询 | 稳定延迟、缓存、重排 |
| 并发 | 单线程演示 | 多用户并发、限流、隔离 |
| 权限 | 无 | 每个租户只能检索自己的数据 |
| 评测 | 人工看 | 评测集 + 回归 |
| 观测 | 延迟/成本/错误指标 |
结论:生产 RAG 的难点不在"调模型",而在数据管道、检索质量、权限隔离、性能与成本这四个工程问题。
二、RAG 全链路:两段式架构
离线(ingestion 数据管道)
文档 → 解析/清洗 → 切片 → 向量化(embedding) → 写入向量库
在线(retrieval + generation)
用户问题 → 向量化 → 向量检索(+关键词混合) → 重排
→ 组装 Prompt(上下文+问题) → LLM 生成 → 返回(带引用)2.1 离线管道:数据质量决定上限
| 环节 | 关键点 | 常见坑 |
|---|---|---|
| 解析 | PDF/Word/网页转纯文本 | 表格、扫描件丢失语义 |
| 清洗 | 去页眉页脚、去噪声 | 脏文本污染 embedding |
| 切片 | 按语义/标题切,兼顾长度 | 切太碎丢失上下文 |
| 向量化 | 统一 embedding 模型与维度 | 新旧模型混用导致检索错乱 |
| 写入 | 幂等、去重、版本 | 重复灌库导致答案重复 |
切片是前端类比最直接的:把一篇长文档切成"组件"而不是"一坨 div"。好的切片像按区块划分的 React 组件,边界清晰、可独立复用。
2.2 在线查询:延迟预算
一条 RAG 请求的典型耗时分布:
向量化(问题) ~10-50ms → 向量检索 ~10-100ms → 重排 ~20-200ms → LLM 生成 秒级优化顺序:先压检索层(索引、缓存、混合检索),再压生成层(模型路由、Prompt 精简)。LLM 生成占大头,缓存命中是最大收益。
三、向量库选型与定位
| 方案 | 适合 | 类比 |
|---|---|---|
| PostgreSQL + pgvector | 中小数据量,已有 PG | 在现有库里加一张表 |
| 专用向量库(Milvus/Qdrant) | 千万级、高 QPS | 独立的搜索引擎 |
| 托管向量服务 | 不想运维 | 用云服务 |
默认推荐:个人全栈从 pgvector 起步(详见 DB11 · pgvector),数据量大了再考虑专用库。别一上来就上分布式向量库。
检索质量三板斧
- 混合检索:向量(语义)+ 关键词(精确)合并,见 G08
- 重排(rerank):候选 Top-50 重排成 Top-5,能明显提升相关度
- 元数据过滤:按租户/文档类型/时间先过滤再检索,既提质量又保隔离
四、Agent 的服务端化:状态与工具
Agent 比单次 RAG 多了"多轮推理 + 调用工具"的循环(原理见 G03)。服务端要解决四个新问题:
| 问题 | 服务端做法 |
|---|---|
| 状态管理 | 会话上下文存 Redis/DB,而不是内存变量 |
| 工具执行 | 工具是受控函数,参数要校验、超时要限制(见 C19) |
| 循环边界 | 最大轮数、单步超时、人工审批点 |
| 隔离与审计 | 每个租户/用户独立会话与权限,记录每次工具调用 |
请求 → 取会话上下文 → LLM 推理 → 需要工具?
├─ 否 → 更新上下文 → 返回
└─ 是 → 校验参数 → 执行工具 → 结果喂回 →(回到 LLM,直到结束或超轮数)关键心智:Agent 的"记忆"不在模型里,而在你的存储里。前端类比是:会话状态别放组件内存,要放 store + 持久化。
人工审批(Human-in-the-loop)
高风险工具(下单、发邮件、删数据)必须插一个审批点:
Agent 请求工具 → 标记 pending → 通知用户 → 用户确认 → 才执行红线:任何写操作、对外副作用、花钱的动作,默认都要有人工确认或白名单限制。
五、多租户与权限隔离
这是 RAG 服务端最容易翻车的地方:
| 层级 | 隔离方式 |
|---|---|
| 数据层 | 文档/切片带 tenant_id,检索 SQL 强制带租户过滤 |
| 接口层 | 从认证信息取 tenant_id,禁止由客户端传 |
| 模型层 | 同租户共享模型,但 Prompt/上下文只含本租户数据 |
铁律:租户 id 永远从服务端会话取,不能信任请求体。前端提交
tenantId字段的做法在安全上是反面教材。
六、性能、缓存与降级
6.1 缓存策略
| 缓存层 | 缓存什么 | 失效策略 |
|---|---|---|
| 语义缓存 | 相似问题的完整答案 | 相似度阈值 + TTL(见 C21) |
| 检索缓存 | 查询 → 检索结果 | 文档更新时清除 |
| embedding 缓存 | 相同文本的向量 | 内容不变则永久 |
6.2 降级路径
向量库挂了 → 退化为关键词检索 → 再退化为"无上下文直接回答"
模型超时 → 返回缓存答案 / 明确报错(不要静默编造)没有降级的 AI 服务,上游一抖你就全挂。 降级路径要提前设计并在上线前演练。
自检清单
- [ ] 能画出离线管道 + 在线查询两段式架构,并说出每段的关键质量点
- [ ] 能按数据量给向量库选型(pgvector vs 专用库)
- [ ] 能给检索加元数据过滤,保证租户隔离
- [ ] 能讲清 Agent 的状态存哪、工具怎么受控、审批点插在哪
- [ ] 有缓存与降级路径,上游故障时服务仍可用
常见误区
- 误区:原型跑通 = 可以上线。 没做隔离、评测、降级就上线,事故是迟早的。
- 误区:RAG 就是"文档切一切 + 调模型"。 数据管道和检索质量决定了 80% 的效果。
- 误区:Agent 状态放内存变量。 重启即丢、无法多实例扩展,必须持久化。
- 误区:租户 id 由前端传。 安全隔离必须服务端认证后自己取。
动手练习
练习 A:生产化 RAG API
把 G 域的 RAG 原型改造成 FastAPI 服务:POST /query,输入问题返回答案 + 引用切片列表。
练习 B:加租户隔离
给文档加 tenant_id,实现两个租户互不可见,并用测试断言越权查询返回空。
练习 C:Agent + 审批
实现一个带 send_email 工具(参数校验 + 审批点)的 Agent,跑通"请求 → 等待确认 → 执行 → 返回"。
相关文档
本区
- 19 · AI 服务端集成 —— LLM 调用与 tools 基础
- 21 · AI 服务可靠性 —— 语义缓存、限流、评测
- 13 · 缓存与 Redis —— 会话与缓存存储
其他域
- 02 · RAG 实战:可溯源问答系统 —— 原型与原理
- 08 · 检索进阶:混合检索与重排 —— 检索质量
- 11 · pgvector:在 Postgres 里做向量检索 —— 向量库落地