面试知识库

19 · 对标主流企业文档 Agent 的改造报告#

目的:不为现有实现辩护,而是从成熟主流产品(Anthropic、Glean、RAGFlow、Google Vertex、ChatGPT/Claude agentic search)的真实工程实现里挑能直接学的,对 DocMind 做步骤合并、精简、替换。允许大刀阔斧。

调研时间:2026-06。来源见文末。


0 · 执行摘要#

DocMind 当前是一个预定义推理(predefined-reasoning)型 RAG 管线:4 道前置闸 + 7 阶段主管线 + 4 条路径 Mode + 大量 flag 短路。索引侧已经对齐了主流的大部分最佳实践(MinerU 版面解析、Markdown-aware 切分、父子双层切块、HyDE、Hybrid+RRF+CrossEncoder+MMR+CRAG)。

真正值得对标改造的,不是”再加功能”,而是”把重复造的轮子合并掉、把软实现替换成强实现”。 核心三刀:

优先级改造一句话主要收益
P0[n] 引用 → 结构化 span 级 citations用 Claude Citations / Vertex grounding 的方式做强 grounding可点击溯源 + 抗幻觉,顺带砍掉自反思一半逻辑
P0索引期加 Contextual Retrieval每个子块嵌入前用小模型补一句全局上下文检索失败率 ↓49%(叠加 rerank ↓67%,Anthropic 实测)
P1三条 bespoke 检索分支 → 1 个 agentic 工具循环(仅复杂查询)MULTI_HOP / DECOMPOSED / CRAG-web 合并成”模型自驱搜索”删大量手写编排,复杂问答质量上限提高
P1自反思子系统 大幅精简跑题护栏/否定正则/重写 → 靠 citations 覆盖率判定Stage 7 复杂度砍半,少 1~2 次 LLM
P112 字段巨型分类器 瘦身只留 scope + complexity + rewrite少维护 5 个驱动 bespoke 分支的字段
P2语义答案缓存 → 检索缓存 + prompt caching别再回放整段答案去掉跨用户/陈旧答案风险,命中率不再被隔离条件压死
P2检索层权限下推 + eval 护栏 + 使用反馈信号Glean 式 permission-at-retrieval / 点击反馈安全合规 + 让上面的大改可被量化验证

1 · 主流成熟产品的工程范式(调研结论)#

范式 A:Anthropic「Building Effective Agents」——简单可组合 > 复杂框架#

  • 最成功的实现不是用复杂框架,而是用简单可组合的模式(prompt chaining / routing / parallelization / orchestrator-workers / evaluator-optimizer)。
  • 明确区分两类系统:Workflow(预定义代码路径,可预测)vs Agent(模型自驱工具,灵活)。从”增强型 LLM”起步,只在需要时加复杂度
  • 警告:框架/层层抽象会掩盖底层 prompt、增加调试难度、诱导”过度设计”。
  • → 对 DocMind 的启示:现在的管线是典型的”accreted workflow”——很多分支是同一能力的重复手写。该合并。

范式 B:Anthropic Contextual Retrieval——索引期补上下文是最高 ROI 的检索增强#

  • 切块会丢上下文。解法:嵌入前用小模型给每个 chunk 前置一句”它在全文里是什么”(Contextual Embeddings + Contextual BM25)。
  • 实测:检索失败率 ↓49%,叠加 reranker ↓67%。成本用小模型 + prompt caching 压住。
  • 标准检索栈:dense+sparse → RRF → 取 ~150 → rerank 到 ~20 → 喂 LLM。
  • 「先想清楚要不要 RAG」:知识库 < ~20 万 token 就直接塞进上下文 + prompt caching,别上 RAG。

范式 C:搜索即工具 / Agentic Search——把检索栈”解绑”给模型编排#

  • 单次 RAG(query→top-k→answer)已是过去式。主流转向多轮 agentic search:plan → 检索 → 读 → 再检索 → 给初稿打分 → 决定要不要再查。
  • Claude Code 直接抛弃独立 RAG,用 grep/view 让模型自己找上下文;ChatGPT Deep Research 把 plan/子查询/反思直接暴露在 UI。
  • 关键动作:底层检索原语变成”薄工具”,由一个聪明模型统一编排,而不是 reranker/分类器/融合器各自为政、互相看不见全局。
  • 成本现实:agentic 比传统 RAG 贵 ~10×、主要赢在复杂/多跳/对比题 → 简单题路由到传统管线,复杂题才上 agent。Azure「agentic retrieval」= LLM 拆子查询→并行→各自语义重排→合并。

范式 D:强 Grounding / 结构化引用——Claude Citations & Vertex Grounding#

  • 不再让模型在正文里手写 [n],而是 API 层返回结构化 span 级引用
    • Claude Citations:把回答切成多个 text block,被支撑的 block 带 citations 数组,句子级粒度,索引指向源文档字符/页/块区间;引用的源文本不计 output token。流式有 citations_delta。还有 search_result content 类型专为动态 RAG。
    • Vertex/Gemini grounding:单独的 groundingMetadatagroundingChunks 源 + groundingSupports 把答案 span 链回源,带 segment.startIndex/endIndex)。
  • 价值:每个论断都能溯源到具体句子;“无引用即未 grounding”天然成为抗幻觉机制。

范式 E:Glean——企业级的”检索之外”工程#

  • 中央索引而非联邦搜索(联邦搜索受各 app API 限速 + 排序差)。
  • 知识图谱(人/内容/活动)做实体消歧 + 个性化。
  • 排序信号超越语义相似度:文档热度、编辑/访问次数、部门亲和、用户 pin/star,且按用户/工作组加权。
  • 权限在检索层强制(不是只在 UI 挡)。
  • 反馈闭环:采集点击/使用信号回灌排序。

范式 F:RAGFlow / 层级检索——索引期 LLM 富化 + 父子块#

  • DeepDoc 深度版面解析(表格/图/段落),模板化切块。
  • 父子切块(大父块保上下文、小子块保召回)+ TOC 增强(给每个 chunk 附章节信息)。
  • 索引期 LLM 富化:auto_keywordsauto_questions(给每个 chunk 生成”它能回答的问题”再嵌入,提升 query→chunk 匹配)、metadata 抽取,结果 Redis 缓存避免重复 LLM。
  • 注意反例:NAACL 2025 发现固定 200 词切块常与语义切块持平——复杂方案要用 eval 证明,别想当然

2 · DocMind 现状对照(诚实清单)#

✅ 已对齐主流(不要重做)#

能力对应主流范式DocMind 实现
版面解析RAGFlow DeepDocMinerUClient + DocumentExtractor(PDF/PPT/图→Markdown)
结构感知切块Markdown-awareTextChunker:表格/代码原子保留、heading 面包屑、frontmatter/版本/日期抽取
父子双层块RAGFlow parent-childchunkWithParents(1500/400) → ParentChunkResolverRetrievalWorker 已接入
Hybrid + 融合 + 重排Anthropic 检索栈向量+BM25 → RRF → CrossEncoder(gte-rerank) → MMR → 压缩
查询自适应Adaptive RAGQueryUnderstanding 分类 + RetrievalPlanner 规则选工具
检索质量自评CRAGRetrievalGrader 分档 + AMBIGUOUS 触发 web 补强
查询期 HyDEHyDEGenerator(仅 FUZZY 时)
多跳/拆解Self-Ask / 并行子查询MULTI_HOP(HopAnswerExtractor) / DECOMPOSED
可观测Deep Research 透明化SSE 全阶段事件 + Langfuse OTel span + 置信度分档
记忆ChatGPT memoryRedis preference/fact/context + recall always-on

❌ 真实差距(改造靶点)#

差距主流怎么做DocMind 现状
索引期上下文增强Contextual Retrieval(LLM 生成 per-chunk 上下文)只有静态 heading breadcrumb,无语义化上下文
结构化引用Claude/Vertex span 级 citations[n](prompt 约定,SelfReflection/PromptAssembler 手拼,会引错号)
复杂问答编排一个 agentic 工具循环三条 bespoke 手写分支(多跳循环 / 并行 fan-out / CRAG-web 回溯)各写各的
抗幻觉机制grounding 内生(无引用即不可信)独立自反思子系统:4 维打分 + 跑题正则 + 否定矛盾正则 + 条件重写(重、易误报、多耗 LLM)
缓存层次prompt caching / 检索缓存答案级语义缓存回放(跨用户风险→加严格隔离→命中率被压死)
权限检索层强制MCP 无鉴权、kbIds 可穿透(CLAUDE.md 自述)
排序信号热度/活动/pin/反馈闭环仅语义相似度,无使用信号
eval 护栏golden set + 持续评测 gate 改动有评测设计文档(09/10),未见接入 CI 作为改动护栏

3 · 改造方案(按优先级)#

每条结构:主流怎么做 → 你现状 → 怎么改(合并/精简/替换) → 收益 → 风险。

【P0-1】软 [n] 引用 → 结构化 span 级 citations#

  • 主流:Claude Citations API(search_result content 类型,句子级,引用源文本不计 output token)/ Vertex groundingSupports
  • 现状PromptAssembler 把 chunk 编号塞进 prompt,靠 LLM 在正文写 [n]SelfReflection 再校验编号一致性——脆弱。
  • 怎么改(替换)
    1. 检索结果按 chunk 切成带稳定 id 的”证据块”,生成时要求模型对每个论断产出 {claim_span, evidence_ids}(结构化输出,而非正文 [n])。
    2. 后端把 evidence_ids 映射回 sources,前端渲染可点击行内引用(已有 source 卡片,复用)。
    3. 置信度直接由”有引用支撑的句子占比”算,不再靠独立反思打分。
  • 收益:真正可溯源;“无引用的句子”= 自动低置信,天然抗幻觉;UX 对齐 NotebookLM/Perplexity。
  • 风险:qwen-plus 结构化输出稳定性需测;用 schema 约束 + 解析失败降级到旧 [n]

【P0-2】索引期加 Contextual Retrieval(最高 ROI 的索引增强)#

  • 主流:Anthropic——嵌入前给每个 chunk 前置一句”它在全文里讲什么”(Contextual Embeddings + Contextual BM25),↓49%/↓67% 检索失败。
  • 现状TextChunker 的 breadcrumb 是静态标题拼接,不含语义上下文;父块已有,正好当”全文上下文”输入。
  • 怎么改(增强,复用已有件)
    1. DocumentProcessTask 切出子块后,对每个子块调小模型生成 1 句上下文(输入:父块或文档摘要 + 子块),prompt-cache 父块降本(RAGFlow 同款 Redis 缓存避免重复 LLM)。
    2. 把”上下文句 + 原文”一起嵌入,并写进 BM25 Lucene 字段(Contextual BM25)。
    3. 可选叠加 RAGFlow auto_questions:给 chunk 生成”它能回答的问题”再嵌入。
  • 收益:召回质量直接提升,且对你”实体名被语义近邻淹没”的老问题(代码里有注释提到 Claude Code vs Claude)特别有效。
  • 风险:索引成本/时间上升 → 用小模型 + 批处理 + 仅对正文块做;先用 eval 证明增益(见 NAACL 反例)。

【P1-1】三条 bespoke 检索分支 → 1 个 agentic 工具循环(仅复杂查询)#

  • 主流:搜索即工具;复杂题用模型自驱的”检索→读→再检索→自评”循环;简单题走传统管线(成本路由)。
  • 现状SupervisorAgenthandleSequentialMultiHop(手写跳循环 + HopAnswerExtractor)、handleDecomposedRetrieval(并行 fan-out + 子问题 web 补强)、handleStandardRetrieval 的 CRAG-web 回溯——三套控制流在重复实现”按需再检索”
  • 怎么改(合并/替换)
    • 保留 handleStandardRetrieval 作为 SIMPLE/factoid 的一次性快路径(便宜、可缓存)。
    • 把 MULTI_HOP + DECOMPOSED + CRAG-web 合并成一个 agenticSearch(query) 工具循环:暴露 doc_search(q,kb) / web_search(q) 两个薄工具,让模型自己决定拆/跳/补 web/停止;HopAnswerExtractor、子问题 merger、web-fallback 逻辑全部消失(模型自然完成)。
    • complexity 路由:SIMPLE→快路径,MEDIUM/COMPLEX/multiHop/comparison→agentic 循环。
  • 收益:删掉数百行手写编排;复杂/多跳/对比题质量上限提高;新增能力(如”先查 A 再决定查不查 B”)零成本获得。
  • 风险:qwen-plus 做长 agentic 循环可靠性弱于 Claude/GPT → 两个选项:(a) 复杂路径单独配更强模型;(b) 折中——保留确定性编排但把三分支抽象成统一”迭代检索器 + 停止判定”,先减重复、不全交给模型。建议先做 (b),eval 达标后再试 (a)。

【P1-2】自反思子系统大幅精简#

  • 主流:grounding 内生于 citations;很少再单独跑一遍反思 LLM(延迟成本)。evaluator-optimizer 只在”有明确评测标准且迭代有可量化收益”时用。
  • 现状SelfReflection = 4 维 LLM 打分 + topicMismatch 正则护栏 + detectDenialContradiction 否定矛盾正则 + 条件重写 + denialOnlyFalseAlarm 误报豁免——补丁叠补丁。
  • 怎么改(精简/替换)
    • 有了 P0-1 的 citations 覆盖率:置信度 = 引用覆盖率 × rerank top-1,删掉独立 4 维打分。
    • topicMismatch 跑题 → 用 CRAG tier=LOW + 引用覆盖率≈0 表达,删正则护栏。
    • detectDenialContradiction 否定矛盾 → citations 强制后,“否认源里存在的实体”会因无法引用而暴露,删正则。
    • 重写仅保留为可选 evaluator-optimizer,且只在引用覆盖率低且 CRAG≥AMBIGUOUS 时触发。
  • 收益:Stage 7 复杂度砍半,常规问答少 1~2 次 LLM,去掉一批易误报的正则。
  • 风险:需 eval 确认”citations 覆盖率”和旧反思置信度相关性 → A/B 对比。

【P1-3】12 字段巨型分类器瘦身#

  • 主流:routing 只做”分到哪条路”,不背负下游所有决策。
  • 现状QueryClassification 12 字段(intent/complexity/specificity/timeAware/memoryAware/needDecompose/multiHop/isAmbiguous/scope/…)+ 确定性正则后处理 + 单独 decompose 调用,很多字段只为驱动 bespoke 分支
  • 怎么改(精简):P1-1 落地后,needDecompose/multiHop/timeAware 这些让 agentic 循环运行时自己判断,分类器只留 scope(路由)+ complexity(快路径 vs agent)+ rewritten(指代消解)。isAmbiguous 并入 complexity。
  • 收益:prompt 更短更稳、少维护 5 个字段及其正则后处理与单测。
  • 风险:决策从”显式可观测”变”模型内隐” → 用 agent trace 把模型的拆/跳决策 log 出来补偿可观测性。

【P2-1】语义答案缓存 → 检索缓存 + prompt caching#

  • 主流:缓存在 prompt/检索层(Anthropic prompt caching),不回放整段答案(答案个性化/含记忆)。
  • 现状SemanticCacheService 回放整段答案;为防串答加了 userId+kb 严格相等校验——安全但命中率被压到很低,且绕过新鲜反思。
  • 怎么改(替换/降级)
    1. 主用 prompt caching:稳定的 system/检索上下文做缓存,省 token 但每次仍真生成。
    2. 需要复用就缓存**检索结果(chunks)**而非答案——命中后仍走生成+citations,保持新鲜与个性化。
    3. 若保留答案缓存,仅用于明确的 FAQ 去重场景,前端显式标注”常见问题快答”。
  • 收益:去掉跨用户/陈旧答案风险;命中率不再被隔离条件锁死。
  • 风险:纯生成省得少 → 接受(正确性 > 省那几次)。

【P2-2】检索层权限下推 + eval 护栏 + 反馈信号#

  • 权限(Glean):把 kbIds 归属校验下推到 RetrievalWorker/Milvus 过滤,userId 从 auth context 注入,MCP 端点加 JWT/API-Key(CLAUDE.md 已列为生产加固项)。
  • eval 护栏:把 09/10 的评测集做成 CI gate——上面每条大改都先用 golden set 量化(命中率/答案正确率/引用准确率/延迟/成本),避免”改了感觉好但没数据”。这是大刀阔斧的前提。
  • 反馈信号(Glean):前端”有用/没用”+ 来源点击回灌,作为 rerank 之外的轻量排序信号(先记录,再用)。

4 · 收敛后的目标架构(before → after)#

净效果:删 3 条手写检索分支、删大半自反思、删答案回放缓存、瘦身分类器加 1 个 agentic 循环、加 Contextual Retrieval、加结构化 citations。组件更少、能力更强、更对齐主流。


5 · 落地顺序(先建护栏再大改)#

  1. 第 0 步(护栏):把评测集接入 CI,确立基线指标(命中率/正确率/引用准确率/P95 延迟/每问成本)。没有这步,后面的”合并/替换”无法证明不退化。
  2. P0-1 结构化 citations(独立、低风险、收益立现,且为精简反思铺路)。
  3. P0-2 Contextual Retrieval(索引侧独立改,eval 验证增益)。
  4. P1-2 精简自反思(依赖 P0-1 的覆盖率信号)。
  5. P1-1 agentic 循环(先做折中版”统一迭代检索器”,再视模型能力上完全自驱)→ 随后 P1-3 分类器瘦身
  6. P2 缓存/权限/反馈,按运营需要排期。

附 · 调研来源#