RAG与Agent工程 · AI Agent

RAG 与 Agent 工程

核心定位

RAG 的本质是:

代码块TEXT · 1 行收起展开
先检索可信资料,再让模型基于资料回答。

它解决的是“模型不知道你的私有知识”的问题,不解决所有 Agent 问题。RAG 负责知识进入上下文;Agent 负责什么时候检索、是否调用工具、如何多步执行、如何记忆和评测。

标准链路

RAG 双链路:离线建库 + 在线回答 不要把 RAG 看成一次检索;它有索引链路和查询链路。

离线索引 Docs Loader Parser Chunker

Vector Metadata

在线查询 Question Rewrite Recall Rerank Answer

RAG 质量漏斗 资料覆盖:有没有正确资料 切块质量:证据是否完整 召回质量:能不能找到 生成质量:是否忠实引用

后端工程视角

RAG 模块后端类比关键问题必留字段
Loader文件导入 / ETL编码、增量扫描、失败重试source_path, mtime, hash
ParserDTO 转换Markdown/PDF/HTML 结构保留title, headings, raw_text
Chunker数据切分块大小、标题路径、上下文丢失chunk_id, title_path, start_line
Embedder外部 API 调用批处理、限流、缓存、成本embedding_model, vector_dim
Vector Store索引库过滤、更新、删除、重建chunk_id, embedding
Retriever查询服务TopK、混合检索、rerankscore, rank, query
Generator业务服务Prompt、引用、拒答used_sources, answer
Evaluator测试系统回归集、指标、错误归因eval_case_id, pass/fail

Obsidian 切块策略

Markdown 不适合按固定字符硬切。建议按标题结构切:

Markdown 结构化切块 Markdown Frontmatter 标题树 标题块 过长? 段落切分 写元数据
代码块JAVA · 10 行收起展开
final class NoteChunk {
    String chunkId;       // 稳定 ID,建议 sourcePath + headingPath + hash
    String sourcePath;    // 原始 Markdown 路径,用于引用和回跳
    String titlePath;     // 标题层级,例如 AI Agent > MCP > Tool
    int startLine;        // 起始行,便于定位
    int endLine;          // 结束行,便于定位
    String content;       // chunk 正文
    String hash;          // 判断内容是否变化
    List<String> tags;    // frontmatter 或正文标签
}

切块样例与边界判断

同一篇 Markdown 里,标题、列表、代码块和表格都不能随便切碎。切块的目标是让证据“刚好能回答问题”,不是让 chunk 数量看起来很多。

代码块TEXT · 6 行收起展开
# MCP 专题学习笔记
## Tool 设计原则
坏工具:run_command(command: string)
问题:权限过大、参数无边界。
## 安全边界
路径越权:resolve 后必须在白名单目录内。
切法chunk 内容结果
按 200 字硬切可能把“坏工具”和“问题”切开证据碎,模型看不懂原因
按 H2 切Tool 设计原则 成为完整块能回答工具为什么要收敛
H2 太长再按段落切保留父标题路径既控 token,又不丢语义
表格整体保留不拆表头和行引用时字段含义完整
代码块JAVA · 7 行收起展开
final class ChunkBoundaryRule {
    int maxChars;              // 单个 chunk 最大字符数,防止上下文膨胀
    int overlapChars;          // 段落二次切分时保留少量重叠
    boolean keepTableTogether; // 表格不拆开,否则列含义会丢失
    boolean keepCodeTogether;  // 代码块不拆开,否则字段注释会丢失
    boolean includeParentPath; // 每个 chunk 附带 H1/H2/H3 路径
}

检索策略

策略解决什么适合场景风险
Vector Search语义相似问法和笔记措辞不同关键词精确命中弱
BM25 / Keyword精确词匹配类名、术语、文件名同义表达召回弱
Metadata Filter限定范围只搜 AI Agent 或 Java过滤过严会漏
Rerank重排候选TopK 噪声多成本增加
Parent Context补父标题/相邻段chunk 太碎上下文变长
Citation Check强制引用证据防编造答案可能变保守

推荐最小链路:

代码块TEXT · 1 行收起展开
BM25 top20 + Vector top20 -> merge -> metadata filter -> rerank top5 -> context builder

RAG 与 Agent 的关系

RAG 是 Agent 的知识子系统 Agent 需要知识? 直接处理 Query Retriever Evidence 证据够? 回答/拒答
能力RAG 负责Agent 负责
找资料chunk、embedding、召回、重排决定是否需要找
控制上下文提供候选证据分配 token 预算
生成答案不负责最终语言要求引用和拒答
多步任务不负责规划、工具、状态机
记忆更新不一定负责决定是否写入长期记忆

典型失败模式

失败表现根因修复
召回错找到相似但无关片段embedding 只看语义近加 BM25、metadata、rerank
证据碎片段看似相关但无法回答chunk 太小或丢标题保留标题路径和父块
证据噪topK 太多,答案跑偏上下文污染rerank + topK 限制
编造没资料也回答prompt 没拒答策略强制“资料不足则拒答”
引用假引用不支持结论citation 未校验answer-source consistency check
索引旧改笔记后答旧内容无增量更新hash + mtime 重建
难复盘不知道错在哪没 trace记录 query、chunks、scores

评测体系

quadrantChart
    title RAG 评测象限
    x-axis 低召回 --> 高召回
    y-axis 低忠实 --> 高忠实
    quadrant-1 好系统
    quadrant-2 资料找得到但会乱写
    quadrant-3 完全不可用
    quadrant-4 回答谨慎但找不到资料
    "理想 RAG": [0.85, 0.9]
    "只向量检索": [0.55, 0.65]
    "无引用生成": [0.75, 0.35]
    "过度拒答": [0.3, 0.85]
指标问题采集方式
Recall@K正确资料是否进 topK标注 expected source
MRR正确资料排第几看 rank
Faithfulness答案是否被证据支持人工/规则/Judge
Citation Accuracy引用是否真实支持句子抽查引用
Refusal Quality无资料时是否拒答负例问题
Latency用户等多久trace
Costembedding + rerank + LLM 成本usage log

最小数据表

代码块JAVA · 10 行收起展开
final class RagTrace {
    String traceId;             // 一次问答链路 ID
    String originalQuestion;    // 用户原问题
    String rewrittenQuery;      // 检索改写后的 query
    List<String> recalledIds;   // 初召回 chunk
    List<String> rerankedIds;   // 重排后 chunk
    List<String> usedSources;   // 最终答案引用来源
    boolean refused;            // 是否拒答
    long latencyMs;             // 总耗时
}

检索调试手册

RAG 出错时不要直接改 prompt。先看 trace,判断错误发生在资料、切块、召回、重排、上下文还是生成阶段。

RAG Debug:先定位,再修复 Question Trace Chunk? Evidence? Faithful? Recall fix Chunk fix Prompt fix Pass no no no yes / yes / yes
症状先看字段常见根因优先修复
完全找不到资料recalledIds, scorequery 改写差、索引旧加 BM25、重建索引
找到相邻但没答案titlePath, startLinechunk 太碎或丢父标题parent context
topK 有答案但没用rerankedIdsrerank 排错规则重排或 rerank 模型
答案混入无关内容usedSourcescontext 太噪限 topK,去重,压缩
引用不支持结论answer, usedSources生成阶段偷换概念citation check
没资料却回答refusedprompt 缺拒答约束增加负例 eval

评测数据集设计

20 个问题只是起步,关键是覆盖失败模式。每个 eval case 都要有期望来源、拒答标记和评价规则。

代码块JSONC · 8 行收起展开
{
  "id": "rag-mcp-001",                         // 稳定用例 ID,方便回归对比
  "question": "MCP 的 Tool 和 Resource 区别是什么?",
  "expectedSources": ["01-MCP专题学习笔记.md"], // 至少应命中的笔记或 chunk
  "mustCite": true,                             // 是否要求回答带来源
  "shouldRefuse": false,                        // 负例问题应设为 true
  "checks": ["source_hit", "faithful", "clear"]
}
用例类型目标通过标准
事实定位找到明确段落expected source 进 top5
跨文档综合合并多篇笔记每个关键结论有来源
操作建议给出下一步建议能追溯到项目路线
负例拒答防编造说明资料不足,不硬答
引用一致性防假引用引用片段支持对应句子

引用一致性检查

引用不是装饰。答案中的关键句必须能被某个 source 支持,否则就是“带引用的编造”。

检查项合格不合格
来源存在路径和标题可打开引用不存在的文件
句子支持source 能证明结论source 只主题相近
范围合适引用到具体标题或行只引用整个目录
冲突处理多来源冲突时说明只选一个有利来源
资料不足明确拒答或追问用常识补全私有事实

RAG 调参顺序

RAG 失败时不要同时改 chunk、embedding、prompt、topK。每次只改一个变量,否则你不知道哪一步真的生效。推荐按下面顺序排查:

顺序先问什么看什么证据常见修复
1正确资料有没有进索引sourcePathhashupdatedAt重建索引、修正 ignore 规则
2query 能不能召回正确文档recalledIds、BM25/vector scorequery rewrite、BM25 + vector 混合
3chunk 是否保留必要上下文titlePath、父标题、相邻段落parent context、按标题切块
4rerank 是否把正确资料排前rerankedIds、rerank reason规则 rerank、标题权重、来源权重
5prompt 是否把证据放清楚prompt snapshot、source 编号统一 source 格式,要求引用
6模型是否忠实使用证据answer-check、citation-check增加拒答约束和负例 eval
7输出是否可验收final answer、citations、traceschema 校验、引用一致性检查

一条高质量 RetrievedChunk 不只是正文片段,至少要带这些字段:

字段为什么必须有
chunkIdeval 和 trace 能定位同一片段
sourcePath用户能打开原文
titlePath模型知道片段在文档结构里的位置
startLine/endLineDebug 时能精确回到笔记
score判断召回是否可信
retriever区分 BM25、vector、hybrid、manual
contentHash判断索引是否过期

RAG 的调参记录也要进 trace。至少记录:

代码块JSONC · 9 行收起展开
{
  "query": "MCP 和 RAG 的区别",                 // 用户原始问题。
  "rewrite": ["MCP tool protocol", "RAG retrieval evidence"], // 查询改写结果,用于扩大召回。
  "topK": 8,                                  // 初召回数量,太小容易漏证据,太大增加噪声。
  "retriever": "hybrid",                      // 检索器版本:向量、关键词或混合检索。
  "rerank": "title+score",                    // 重排策略,说明最终证据如何排序。
  "selectedChunkIds": ["01-mcp-309", "02-rag-199"], // 进入最终上下文的 chunk。
  "refused": false                            // 是否因为证据不足而拒答。
}

个人知识库 Agent MVP

模块功能验收
Indexer索引 技术栈/AI Agent Markdown修改文件后能增量更新
Retriever混合检索 + rerank正确笔记进入 top5
Answerer带引用回答每段关键结论有来源
Refuser资料不足拒答不存在的问题不编
Trace保存检索链路能看到 query、score、source
Eval固定问题集改 prompt 后可对比

20 个评测问题怎么设计

类型数量例子
明确事实5MCP 的 tool/resource/prompt 区别是什么
跨笔记综合5Java 后端怎么迁移到 Agent 工程
操作建议4现在应该先做哪个 Agent 项目
负例拒答3笔记里没有的具体产品参数
引用检查3要求回答附来源路径和标题

最小实现顺序

  1. Markdown parser:按标题切 chunk。
  2. Metadata DB:保存路径、标题、hash、更新时间。
  3. Embedding:批量生成向量,支持缓存。
  4. Retriever:BM25 + vector 初召回。
  5. Rerank:先用规则重排,再接模型重排。
  6. Prompt:强制引用和资料不足拒答。
  7. Trace:记录 query、chunks、scores、answer。
  8. Eval:固定 20 个问题回归。

RAG 验收门槛

门槛最低标准失败就先别进入下一步
索引新鲜度修改笔记后能增量更新回答旧内容
召回命中事实类问题 expected source 进 top5topK 全无关
引用忠实关键结论有可打开来源引用只主题相近
拒答能力负例问题不编造用常识硬答
Trace 可复盘保存 query、chunk、score、answer只保存最终答案
Eval 可回归改策略后能比较 pass/fail没有固定数据集

核心判断

RAG 的难点不在“把资料塞给模型”,而在:

代码块TEXT · 1 行收起展开
资料能更新,检索能命中,证据能引用,答案能拒答,错误能复盘。