面试知识库
困难

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)
其他开销:        400ms
plaintext

4. 成本控制#

Token 成本拆解:

单次 RAG 调用 ≈ 系统 Prompt(500) + 检索上下文(2000) + 用户问题(100) + 生成(500)
           = ~3100 Token
plaintext

控制手段:

  • 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
}
json

6. 数据更新与增量索引#

文档更新时向量怎么同步?

文档更新 → 计算文档 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 费用是真金白银