高 困难
RAG与Agent生产化实践#
一句话答案#
从 Demo 到生产的核心 Gap 不是”能不能跑”,而是可靠性、延迟、成本、可观测四个维度——面试官追问”这系统生产上会遇到什么问题”,就是在考这个。
核心要点
1. Demo vs 生产的差距全景#
| 维度 | Demo | 生产 |
|---|---|---|
| 并发 | 单用户测试 | 数百并发,需排队/限流 |
| 延迟 | 可以等 10 秒 | P99 < 3 秒,用户会离开 |
| 成本 | 不在乎 Token | 每月可能数万元,需精细控制 |
| 可靠性 | 出错重试 | 不能把幻觉返回给用户 |
| 可观测 | print 日志 | 全链路追踪 + 质量监控 |
| 数据 | 固定测试集 | 持续更新,增量索引 |
2. 可靠性工程#
幻觉检测与防护#
用户问题 → 检索 → 生成 → 幻觉检测 → 返回
↓
检测到不确定 → "抱歉,我没找到相关信息"plaintext检测手段:
- 引用验证:生成内容必须能回溯到检索到的原文片段
- 置信度阈值:检索分数低于阈值时直接拒答,而不是强行生成
- 自检 Prompt:让 LLM 自己判断”这个回答是否完全基于给定上下文”
- 关键事实校验:数字、日期、人名等做规则校验
工具调用失败的降级链路#
Agent 调用工具
├── 成功 → 继续推理
├── 超时(>5s)→ 重试 1 次(指数退避)
│ ├── 重试成功 → 继续
│ └── 重试失败 → 降级
├── 参数错误 → 不重试,让 Agent 反思修正参数
└── 工具不可用 → 降级到备选工具或直接 LLM 回答
降级策略:
Level 1: 重试(瞬时错误)
Level 2: 切换备选工具(功能等价的替代)
Level 3: 纯 LLM 回答(标注"未经工具验证")
Level 4: 人工兜底(返回"请联系人工客服")plaintext循环终止控制#
- 最大迭代次数:Agent 循环不能无限跑,设上限(如 5-10 次)
- Token 预算:单次对话设定 Token 上限,超出则总结当前进度并终止
- 相同工具调用检测:连续调用相同工具+相同参数→死循环,强制终止
3. 延迟优化#
| 策略 | 效果 | 实现 |
|---|---|---|
| 流式输出 | 首 Token 延迟 < 1s,用户感知快 | SSE / WebSocket |
| 语义缓存 | 相似问题命中缓存,跳过 LLM 调用 | 向量相似度 > 阈值 → 返回缓存 |
| 预检索 | 用户输入时就开始检索 | 前端 debounce 触发预检索 |
| Embedding 缓存 | 避免重复计算 Embedding | 文档 Hash → Embedding 映射 |
| 模型分级 | 简单问题用小模型,复杂问题用大模型 | 意图分类 → 路由到不同模型 |
延迟预算分配(以 3 秒总预算为例):
Embedding 计算: 200ms
向量检索: 100ms
重排序: 300ms
LLM 生成: 2000ms(流式首 Token < 500ms)
其他开销: 400msplaintext4. 成本控制#
Token 成本拆解:
单次 RAG 调用 ≈ 系统 Prompt(500) + 检索上下文(2000) + 用户问题(100) + 生成(500)
= ~3100 Tokenplaintext控制手段:
- Prompt 精简:系统 Prompt 越短越好,避免冗余指令
- 上下文压缩:检索后做摘要再喂给 LLM,减少 Token 消耗
- 缓存命中:语义缓存命中率每提高 10%,成本降低 10%
- 模型路由:80% 简单问题用 Haiku 级别,20% 复杂问题用 Sonnet/Opus
- 批量处理:非实时场景用 Batch API,成本可降 50%
5. 可观测性建设#
必须监控的指标:
| 指标 | 意义 | 告警条件 |
|---|---|---|
| 检索 Recall@5 | 检索质量 | 低于 0.7 |
| 生成延迟 P99 | 用户体验 | 超过 5 秒 |
| 幻觉率 | 回答可靠性 | 超过 5% |
| 缓存命中率 | 成本效率 | 低于 30% |
| Token 消耗/日 | 成本控制 | 超预算 120% |
| Agent 平均迭代次数 | 效率 | 超过 5 次 |
| 工具调用失败率 | 可靠性 | 超过 10% |
日志规范:
{
"trace_id": "xxx",
"query": "用户问题",
"retrieved_chunks": 5,
"top_chunk_score": 0.87,
"model": "claude-sonnet-4-6",
"input_tokens": 2600,
"output_tokens": 450,
"latency_ms": 2100,
"cache_hit": false
}json6. 数据更新与增量索引#
文档更新时向量怎么同步?
文档更新 → 计算文档 Hash
├── Hash 未变 → 跳过
└── Hash 变了 → 重新分块 → 重新 Embedding → 删旧向量 + 写新向量
增量策略:
- 每个向量记录 doc_id + version
- 更新时按 doc_id 删除旧版本所有 chunk 向量
- 写入新版本所有 chunk 向量
- 维护一张 doc_version 映射表做对账plaintext面试回答(2分钟版)
从 Demo 到生产的核心挑战有四个:可靠性上,要做幻觉检测(检索分数低于阈值就拒答、生成后自检引用来源)和工具调用降级链路(重试→备选工具→纯 LLM→人工兜底);延迟上,P99 目标 3 秒内,通过流式输出、语义缓存、模型分级来优化;成本上,单次 RAG 约 3000 Token,通过上下文压缩、缓存、模型路由控制,80% 简单问题用小模型;可观测性上,必须监控检索 Recall、生成延迟、幻觉率、Token 消耗等核心指标。此外还有数据更新的增量索引问题——文档更新后要按 doc_id + version 做向量的增删。
追问与易错
追问方向:
- “你的系统幻觉率多少?怎么测的?”→ 构建评测集,人工标注 + LLM-as-Judge
- “成本一个月多少?”→ 要能估算:日均调用量 × 平均 Token × 单价
- “文档删了但向量还在怎么办?”→ doc_id 映射 + 定期对账 + TTL 机制
- “并发 100 时延迟怎样?”→ 需要做压测,LLM API 本身有并发限制和排队
易错点:
- ❌ 只讲 Demo 效果不讲生产问题——面试官最想听的就是”你踩过什么坑”
- ❌ “用了 RAG 就没有幻觉”——检索质量差时 RAG 照样幻觉
- ❌ 不考虑成本——生产环境 Token 费用是真金白银