<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RAG 原理与实践 on 扎塔-Zata</title><link>https://www.zata.cc/tags/rag-%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E8%B7%B5/</link><description>Recent content in RAG 原理与实践 on 扎塔-Zata</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>扎塔-Zata</copyright><lastBuildDate>Thu, 24 Sep 2026 17:09:06 +0800</lastBuildDate><atom:link href="https://www.zata.cc/tags/rag-%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E8%B7%B5/index.xml" rel="self" type="application/rss+xml"/><item><title>RAG生产实践：常见坑、性能优化与迭代路线图</title><link>https://www.zata.cc/p/rag%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E5%B8%B8%E8%A7%81%E5%9D%91%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B8%8E%E8%BF%AD%E4%BB%A3%E8%B7%AF%E7%BA%BF%E5%9B%BE/</link><pubDate>Wed, 25 Mar 2026 15:55:00 +0800</pubDate><guid>https://www.zata.cc/p/rag%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E5%B8%B8%E8%A7%81%E5%9D%91%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B8%8E%E8%BF%AD%E4%BB%A3%E8%B7%AF%E7%BA%BF%E5%9B%BE/</guid><description>&lt;img src="https://www.zata.cc/p/rag%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E5%B8%B8%E8%A7%81%E5%9D%91%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B8%8E%E8%BF%AD%E4%BB%A3%E8%B7%AF%E7%BA%BF%E5%9B%BE/images/index/index.png" alt="Featured image of post RAG生产实践：常见坑、性能优化与迭代路线图" />&lt;p>RAG 的 Demo 很容易做，生产环境却很容易失控。&lt;/p>
&lt;p>一开始你可能只要：&lt;/p>
&lt;ul>
&lt;li>一个 embedding 模型&lt;/li>
&lt;li>一个向量库&lt;/li>
&lt;li>一个聊天模型&lt;/li>
&lt;/ul>
&lt;p>但真到线上，问题会迅速变成：&lt;/p>
&lt;ul>
&lt;li>更新怎么做&lt;/li>
&lt;li>成本怎么控&lt;/li>
&lt;li>延迟怎么降&lt;/li>
&lt;li>数据怎么隔离&lt;/li>
&lt;li>错误怎么排查&lt;/li>
&lt;li>版本怎么回归&lt;/li>
&lt;/ul>
&lt;p>所以生产级 RAG 的重点是&amp;quot;工程稳定性&amp;quot;，不只是&amp;quot;回答效果&amp;quot;。&lt;/p>
&lt;p>这篇文章会讲：&lt;/p>
&lt;ul>
&lt;li>生产环境最常见的坑&lt;/li>
&lt;li>性能优化的思路&lt;/li>
&lt;li>一个可执行的迭代路线&lt;/li>
&lt;/ul>
&lt;h2 id="一最常见的-10-个坑">一、最常见的 10 个坑
&lt;/h2>&lt;h3 id="坑-1把所有文档放进一个大集合">坑 1：把所有文档放进一个大集合
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>公司有产品文档、技术规范、内部 wiki、销售话术、HR 制度……全部丢进一个向量库。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>用户问&amp;quot;API 超时怎么配置&amp;quot;，检索结果混入了销售话术（因为提到了&amp;quot;时间&amp;quot;）、HR 制度（因为提到了&amp;quot;加班时间&amp;quot;）。正确答案被噪声淹没。&lt;/p>
&lt;p>&lt;strong>原理&lt;/strong>：&lt;/p>
&lt;p>向量检索基于语义相似度。&amp;ldquo;时间&amp;quot;这个概念在很多文档里都出现，如果检索范围太大，语义相似的噪声也会被召回。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>按业务边界拆分 source，检索时指定来源。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">知识库结构：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── product_docs/ # 产品文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── api_specs/ # API 规范
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── internal_wiki/ # 内部 wiki
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── hr_policies/ # HR 制度
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">检索时：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">filter = {&amp;#34;source&amp;#34;: &amp;#34;api_specs&amp;#34;}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>效果&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置&lt;/th>
&lt;th>Recall@5&lt;/th>
&lt;th>噪声比例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>全量检索&lt;/td>
&lt;td>58%&lt;/td>
&lt;td>62%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>按 source 过滤&lt;/td>
&lt;td>84%&lt;/td>
&lt;td>18%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="坑-2chunk-没有业务上下文">坑 2：chunk 没有业务上下文
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>按段落切分后，某个 chunk 只剩一句话：&amp;ldquo;将旋钮调至 3 档，等待指示灯变绿。&amp;rdquo;&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>用户问&amp;quot;ZK-200 怎么校准&amp;rdquo;，这个 chunk 不会召回。因为产品名、设备类型、操作名称都在标题里——被切掉了。&lt;/p>
&lt;p>&lt;strong>原理&lt;/strong>：&lt;/p>
&lt;p>Embedding 只能看到 chunk 内部的文字。如果 chunk 里没有&amp;quot;ZK-200&amp;quot;和&amp;quot;校准&amp;quot;这些关键词，向量就不会和这些问题相似。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>把父级标题拼到 chunk 前面：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始 chunk：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;将旋钮调至 3 档，等待指示灯变绿。&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">补充上下文：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;【ZK-200 操作手册 &amp;gt; 2. 使用方法 &amp;gt; 2.3 校准流程】
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">将旋钮调至 3 档，等待指示灯变绿。&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>效果&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置&lt;/th>
&lt;th>Recall@5&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>原始 chunk&lt;/td>
&lt;td>41%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>补充上下文后&lt;/td>
&lt;td>78%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>这是 RAG 里性价比最高的优化之一：成本几乎为零，效果翻倍。&lt;/p>
&lt;h3 id="坑-3只做-dense-search">坑 3：只做 dense search
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>用户问&amp;quot;错误码 E0028 是什么意思&amp;quot;，向量检索召回的是&amp;quot;常见错误码及解决方案&amp;quot;这种泛泛而谈的文档，而不是精确包含&amp;quot;E0028&amp;quot;的那段。&lt;/p>
&lt;p>&lt;strong>原理&lt;/strong>：&lt;/p>
&lt;p>向量检索擅长语义相似，不擅长精确匹配。&amp;ldquo;E0028&amp;quot;作为一个编号，在向量空间里没有特殊意义，它只是一个 token。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>引入 BM25 或 sparse 检索，做混合检索。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">混合检索：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">向量检索 → 召回语义相似的文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BM25 检索 → 召回包含精确关键词的文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RRF 融合 → 合并两路结果
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>效果&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>检索方式&lt;/th>
&lt;th>精确匹配查询 Recall@5&lt;/th>
&lt;th>语义查询 Recall@5&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>向量检索&lt;/td>
&lt;td>47%&lt;/td>
&lt;td>82%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>BM25&lt;/td>
&lt;td>76%&lt;/td>
&lt;td>58%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>混合检索&lt;/td>
&lt;td>84%&lt;/td>
&lt;td>85%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="坑-4假-rerank">坑 4：假 rerank
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>代码里写着&amp;quot;rerank&amp;rdquo;，但只是把向量分数重新排了一次序。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">def rerank(candidates):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> return sorted(candidates, key=lambda x: x[&amp;#39;score&amp;#39;], reverse=True)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>这不是真正的 rerank，只是把已有的分数重新排序，效果和没有 rerank 一样。&lt;/p>
&lt;p>&lt;strong>原理&lt;/strong>：&lt;/p>
&lt;p>真正的 Rerank 需要用 Cross-Encoder：&lt;/p>
&lt;ul>
&lt;li>把 Query 和每个候选 Document 拼在一起&lt;/li>
&lt;li>丢进 Transformer，让模型学习两者的交互&lt;/li>
&lt;li>输出新的相关性分数&lt;/li>
&lt;/ul>
&lt;p>这比双塔结构的向量检索更精确，因为 Query 和 Document 能充分交互。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>使用真正的 Cross-Encoder 模型：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">候选文档 → Cross-Encoder → 新分数 → 重新排序
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>效果&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置&lt;/th>
&lt;th>Recall@5&lt;/th>
&lt;th>正确答案平均排名&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>无 Rerank&lt;/td>
&lt;td>72%&lt;/td>
&lt;td>4.2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>假 Rerank&lt;/td>
&lt;td>72%&lt;/td>
&lt;td>4.1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>真 Rerank&lt;/td>
&lt;td>88%&lt;/td>
&lt;td>1.8&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="坑-5top_k-和阈值写死">坑 5：top_k 和阈值写死
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>所有场景都用固定的 top_k=5 和 score_threshold=0.3。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>简单问题：只需要 3 个候选就够了，多余的候选增加噪声&lt;/li>
&lt;li>复杂问题：需要 10 个候选才能覆盖，5 个不够&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>原理&lt;/strong>：&lt;/p>
&lt;p>检索参数取决于问题的复杂度、文档的分布、embedding 模型的特性。不同场景的最优参数不同。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>参数可配置，甚至动态调整：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">简单事实问题 → top_k=3, threshold=0.5（少而精）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">复杂问题 → top_k=15, threshold=0（多召回）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">对比类问题 → top_k=20（需要更多信息）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="坑-6没有-context-budget-设计">坑 6：没有 context budget 设计
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>检索到 15 个 chunk，全部塞进 prompt，总共 12000 tokens。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>成本高：token 消耗大&lt;/li>
&lt;li>延迟高：模型处理慢&lt;/li>
&lt;li>效果差：内容太长，模型注意力分散（Lost in the Middle 问题）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>原理&lt;/strong>：&lt;/p>
&lt;p>LLM 的注意力机制在长文本上会分散。研究表明，当相关信息在 prompt 中间位置时，模型更容易忽略它。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>设计 context budget：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">预算：4000 tokens
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">组装策略：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 优先高分 chunk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 控制 token 总量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 必要时截断过长的 chunk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4. 保持来源多样性（不同 source 的 chunk 都有）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>经验值&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>场景&lt;/th>
&lt;th>推荐 token 预算&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>简单问答&lt;/td>
&lt;td>2000-3000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>复杂问答&lt;/td>
&lt;td>3000-5000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>文档总结&lt;/td>
&lt;td>5000-8000&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="坑-7文档更新了索引没同步">坑 7：文档更新了，索引没同步
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>周一用户问&amp;quot;报销流程&amp;quot;，答案正确。周三财务更新了报销规范，周五用户再问，答案还是旧的。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>文档更新后，向量库没有同步，还在用旧版本。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>建立版本管理机制：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">方案 1：定时全量同步
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 每天凌晨重建索引
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 简单但成本高
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">方案 2：增量更新
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 监控文档变更
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 只更新变化的文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 复杂但成本低
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">方案 3：版本标记
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 每个文档有版本号
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 检索时检查版本是否最新
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 过期则重新索引
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>关键&lt;/strong>：保留文档的 hash 或时间戳，便于判断是否需要更新。&lt;/p>
&lt;h3 id="坑-8没有证据引用">坑 8：没有证据引用
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>模型回答：&amp;ldquo;报销需要提交发票和审批单。&amp;rdquo;&lt;/p>
&lt;p>用户：&amp;ldquo;这个答案依据是什么？&amp;rdquo;&lt;/p>
&lt;p>系统无法回答。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>答案和来源脱节，用户无法验证答案的可信度。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>Prompt 中强制要求引用：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">要求：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 答案必须基于参考资料
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 回答时标注引用来源，格式：[来源: 文档名 &amp;gt; 章节]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 如果不确定，说明不确定
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>答案示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">报销需要提交发票和审批单 [来源: 财务规范 &amp;gt; 3.2 报销流程]。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>好处&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>用户可以验证答案&lt;/li>
&lt;li>系统可以追溯错误&lt;/li>
&lt;li>增加答案可信度&lt;/li>
&lt;/ul>
&lt;h3 id="坑-9没有离线-benchmark">坑 9：没有离线 benchmark
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>开发者说&amp;quot;效果提升了&amp;quot;，产品说&amp;quot;感觉变差了&amp;quot;，谁也说服不了谁。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>没有客观的评价标准，优化靠主观感受。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>建立固定 benchmark：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">评测集：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 50-100 个问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 每个问题有期望召回的 chunk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 每个问题有参考答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">定期评测：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 每次改动后跑 benchmark
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 对比历史版本
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 设置阈值（如 Recall@5 &amp;gt; 80%）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>原则&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>评测集要隔离，不参与训练&lt;/li>
&lt;li>定期从线上采样真实问题，更新评测集&lt;/li>
&lt;li>多指标综合评估&lt;/li>
&lt;/ul>
&lt;h3 id="坑-10没有-inspect-能力">坑 10：没有 inspect 能力
&lt;/h3>&lt;p>&lt;strong>现象&lt;/strong>：&lt;/p>
&lt;p>答案错了，不知道是检索错、排序错、还是模型错。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：&lt;/p>
&lt;p>无法定位问题，优化靠猜。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：&lt;/p>
&lt;p>保留每次请求的 Trace：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Trace 包含：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 用户问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 检索候选（top-10）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Rerank 结果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 最终 prompt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 模型答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">有 Inspect 页面，可以查看每一步的中间结果。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>好处&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>快速定位问题&lt;/li>
&lt;li>积累 bad cases&lt;/li>
&lt;li>指导优化方向&lt;/li>
&lt;/ul>
&lt;h2 id="二性能优化的思路">二、性能优化的思路
&lt;/h2>&lt;h3 id="延迟分析">延迟分析
&lt;/h3>&lt;p>一个典型 RAG 请求的延迟分布：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">总延迟：400-600ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── Query Embedding：30-50ms（5-10%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── 向量检索：30-50ms（5-10%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── BM25 检索：10-20ms（2-5%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── RRF 融合：&amp;lt;5ms（&amp;lt;1%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── Rerank：150-200ms（30-50%）← 主要瓶颈
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── Prompt 组装：&amp;lt;10ms（&amp;lt;1%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── LLM 生成：150-300ms（30-50%）← 主要瓶颈
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>两个主要瓶颈：&lt;strong>Rerank&lt;/strong> 和 &lt;strong>LLM 生成&lt;/strong>。&lt;/p>
&lt;h3 id="rerank-优化">Rerank 优化
&lt;/h3>&lt;p>&lt;strong>思路 1：减少候选数量&lt;/strong>&lt;/p>
&lt;p>Rerank 的计算量与候选数量成正比。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">100 个候选 × Cross-Encoder ≈ 200ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">30 个候选 × Cross-Encoder ≈ 70ms
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>但不能减太少，否则会漏掉正确答案。建议：&lt;/p>
&lt;ul>
&lt;li>召回 50-100 个&lt;/li>
&lt;li>Rerank 前 20-30 个&lt;/li>
&lt;li>输出 top 5-10 个&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>思路 2：用更快的模型&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模型&lt;/th>
&lt;th>延迟（100 候选）&lt;/th>
&lt;th>Recall@5&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>bge-reranker-large&lt;/td>
&lt;td>~180ms&lt;/td>
&lt;td>88%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bge-reranker-base&lt;/td>
&lt;td>~95ms&lt;/td>
&lt;td>85%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ms-marco-MiniLM&lt;/td>
&lt;td>~45ms&lt;/td>
&lt;td>80%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>速度和效果的权衡。&lt;/p>
&lt;p>&lt;strong>思路 3：跳过简单问题&lt;/strong>&lt;/p>
&lt;p>对于简单问题，可能不需要 Rerank：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">简单问题（候选集中度高）→ 跳过 Rerank
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">复杂问题（候选分散）→ 需要 Rerank
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>判断标准：看 top-5 候选的分数分布。如果第一名分数远高于其他，说明检索已经足够准确。&lt;/p>
&lt;h3 id="llm-优化">LLM 优化
&lt;/h3>&lt;p>&lt;strong>思路 1：用更快的模型&lt;/strong>&lt;/p>
&lt;p>GPT-4o-mini 比 GPT-4o 快 3-5 倍，成本是 1/10。&lt;/p>
&lt;p>对于大部分 RAG 场景，mini 版足够用。&lt;/p>
&lt;p>&lt;strong>思路 2：流式输出&lt;/strong>&lt;/p>
&lt;p>不要等完整答案生成，边生成边返回：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">传统模式：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户等待 → 完整答案 → 一次返回（延迟高）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">流式模式：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户等待 → 第一个字 → 第二个字 → ...（感知延迟低）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>流式不会减少实际延迟，但能改善用户体验。&lt;/p>
&lt;p>&lt;strong>思路 3：缓存热门 query&lt;/strong>&lt;/p>
&lt;p>相同问题直接返回缓存：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">热门问题 TOP 100：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;报销流程&amp;#34; → 缓存答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;API 认证&amp;#34; → 缓存答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">命中率：10-30%
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">节省：10-30% 的 LLM 调用
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="检索优化">检索优化
&lt;/h3>&lt;p>&lt;strong>思路 1：缓存 query embedding&lt;/strong>&lt;/p>
&lt;p>同一个问题的 embedding 可以缓存：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Query → Embedding（40ms）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Query（重复）→ 缓存（&amp;lt;1ms）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>思路 2：预计算&lt;/strong>&lt;/p>
&lt;p>某些场景可以预计算：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">FAQ 场景：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 预计算每个 FAQ 的 embedding
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 预计算每个 FAQ 的最佳答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 用户问题直接匹配 FAQ
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">适合问题集合固定的场景。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>思路 3：减少召回数量&lt;/strong>&lt;/p>
&lt;p>如果检索质量已经很高，可以减少召回数量：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">top-50 → top-30
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">节省：向量检索和 Rerank 的时间
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">风险：可能漏掉正确答案
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="三成本优化">三、成本优化
&lt;/h2>&lt;h3 id="token-消耗分析">Token 消耗分析
&lt;/h3>&lt;p>单次请求的 token 消耗：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">输入 token：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Query：20-50
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Chunks（5个）：2000-5000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- System prompt：100-200
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">总输入：2000-6000 tokens
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">输出 token：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Answer：100-500
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">按 GPT-4o-mini 定价：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">输入：$0.15/1M tokens
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">输出：$0.60/1M tokens
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">单次请求成本：$0.0003-0.001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">日均 10000 次 → 月成本：$100-300
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="成本优化思路">成本优化思路
&lt;/h3>&lt;p>&lt;strong>1. 控制上下文长度&lt;/strong>&lt;/p>
&lt;p>上下文太长不仅成本高，效果还差。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">经验值：3000-4000 tokens
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">超过预算时：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 截断过长的 chunk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 减少进入 prompt 的 chunk 数量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 优先保留高分的 chunk
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. 用更便宜的模型&lt;/strong>&lt;/p>
&lt;p>GPT-4o-mini 的成本是 GPT-4o 的 1/10，效果差距不大。&lt;/p>
&lt;p>&lt;strong>3. 缓存热门问题&lt;/strong>&lt;/p>
&lt;p>10-30% 的请求是重复问题，直接返回缓存。&lt;/p>
&lt;p>&lt;strong>4. 优化 prompt&lt;/strong>&lt;/p>
&lt;p>去掉冗余的 prompt 内容，精简指令。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">差的 prompt（冗长）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;你是一个非常专业的技术文档助手，你的任务是根据用户提供的参考资料
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">来回答用户的问题。请注意，你的回答必须严格基于参考资料...&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">好的 prompt（精简）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;根据参考资料回答问题。答案必须基于资料，标注来源[数字]。&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="四迭代路线图">四、迭代路线图
&lt;/h2>&lt;h3 id="v1能跑通1-2-周">V1：能跑通（1-2 周）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：回答对 60% 的核心问题&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">配置：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 基础 chunking（按段落）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 纯向量检索（top_k=5）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 基础 prompt + 引用要求
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">验收：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 能回答常见问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 有引用来源
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 能 demo 演示
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>不要做&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>不要全量导入所有文档&lt;/li>
&lt;li>不要追求复杂架构&lt;/li>
&lt;li>不要过度优化&lt;/li>
&lt;/ul>
&lt;h3 id="v2能诊断2-3-周">V2：能诊断（2-3 周）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：知道为什么对/错&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">配置：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Inspect 页面（看检索候选）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Metadata 过滤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 参数可配置
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 离线评测集（50 条）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">验收：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 能看到检索的 top-10
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 能定位问题在哪一层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 有 Recall@5 指标
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="v3能优化3-4-周">V3：能优化（3-4 周）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：召回率 80%+&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">配置：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Hybrid Retrieval（向量 + BM25）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 真 Rerank
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Chunking 优化（补充上下文）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 评测集扩展（100 条）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">验收：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Recall@5 &amp;gt; 80%
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 能回答复杂问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Bad cases 持续跟踪
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="v4能运营持续">V4：能运营（持续）
&lt;/h3>&lt;p>&lt;strong>目标&lt;/strong>：持续监控、持续迭代&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">配置：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Trace 存储
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 监控大盘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 告警规则
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 用户反馈收集
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- CI/CD 集成
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">验收：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 有质量监控
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 能快速定位线上问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 每次改动有回归测试
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="收益递减规律">收益递减规律
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">60% → 80%：基础优化（chunking、混合检索）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">80% → 90%：系统优化（Rerank、prompt 调优）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">90% → 95%：高级优化（query rewrite、模型微调）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">95% → 99%：难度极大，投入产出比低
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">建议：先做到 85%，再决定是否值得继续投入。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="五团队协作">五、团队协作
&lt;/h2>&lt;h3 id="角色分工">角色分工
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">产品/运营：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 定义知识边界
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 收集 bad cases
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 标注评测集
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 用户反馈归类
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">算法/NLP：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Embedding 模型选择
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Rerank 模型调优
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Chunking 方案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 高级策略
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">后端工程师：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Ingestion pipeline
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 向量库维护
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Trace/Inspect 系统
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 性能优化
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 监控告警
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="协作流程">协作流程
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">日常迭代：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 产品收集 bad cases
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 算法分析问题（定位到哪一层）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 算法 + 后端共同优化
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4. 跑 benchmark 验证
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5. 上线 + 监控
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="问题归属">问题归属
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题&lt;/th>
&lt;th>归属&lt;/th>
&lt;th>方向&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>召不回正确内容&lt;/td>
&lt;td>算法&lt;/td>
&lt;td>Chunking、检索策略&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>候选噪声多&lt;/td>
&lt;td>算法&lt;/td>
&lt;td>Rerank、过滤&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>答案格式不对&lt;/td>
&lt;td>算法&lt;/td>
&lt;td>Prompt&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>延迟高&lt;/td>
&lt;td>后端&lt;/td>
&lt;td>缓存、异步&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>系统不稳定&lt;/td>
&lt;td>后端&lt;/td>
&lt;td>稳定性&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>模型幻觉&lt;/td>
&lt;td>算法&lt;/td>
&lt;td>Prompt、模型选择&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>知识库没更新&lt;/td>
&lt;td>产品/运营&lt;/td>
&lt;td>文档维护流程&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="六判断系统成熟度">六、判断系统成熟度
&lt;/h2>&lt;p>如果满足以下条件，说明系统开始成熟：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">□ 知道每次回答用了哪些证据
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> （有 Inspect，能追溯）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 能复现错误回答的完整链路
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> （有 Trace 存储）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 有固定 benchmark
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> （定期跑，有阈值）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 能对比不同版本的质量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> （有版本管理，能 A/B）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 知道下一步优化哪一层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> （有监控，不是盲调）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果这 5 条还做不到，最应该投入的不是&amp;quot;换更强模型&amp;quot;，而是把&lt;strong>检索、Inspect 和评测体系&lt;/strong>补完整。&lt;/p>
&lt;h2 id="七系列总结">七、系列总结
&lt;/h2>&lt;p>这四篇文章回答了 RAG 的核心问题：&lt;/p>
&lt;p>&lt;strong>入门&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>RAG 的本质：把知识从参数里剥离出来&lt;/li>
&lt;li>Embedding 的原理：对比学习、向量空间&lt;/li>
&lt;li>向量检索的局限：对精确匹配不稳定&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>进阶&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Chunking：按语义切分 + 补充上下文&lt;/li>
&lt;li>混合检索：向量 + BM25 + RRF 融合&lt;/li>
&lt;li>Rerank：Cross-Encoder 做真正的精排&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>评测&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>分层评测：检索、重排、组装、生成&lt;/li>
&lt;li>LLM-as-Judge：让大模型评判答案质量&lt;/li>
&lt;li>Inspect：保留完整 Trace，定位单次问题&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>生产&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>常见坑：上下文丢失、假 rerank、无引用&lt;/li>
&lt;li>性能优化：缓存、模型选择、候选数量控制&lt;/li>
&lt;li>迭代路线：从能跑到能运营&lt;/li>
&lt;/ul>
&lt;p>RAG 不是银弹，但它是目前让 LLM 接地气的最实用方案。关键在于：&lt;strong>不要追求一步到位，而是建立可迭代的能力&lt;/strong>。&lt;/p>
&lt;hr>
&lt;p>&lt;strong>后续可以深入的方向&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>Query Rewrite 和 Query Decomposition&lt;/li>
&lt;li>Contextual Retrieval（Anthropic 的方法）&lt;/li>
&lt;li>多租户与权限设计&lt;/li>
&lt;li>RAG 与 Agent 的结合&lt;/li>
&lt;li>多模态 RAG（图片、表格）&lt;/li>
&lt;/ol></description></item><item><title>RAG评测与 Inspect：如何知道问题出在检索、重排还是生成</title><link>https://www.zata.cc/p/rag%E8%AF%84%E6%B5%8B%E4%B8%8E-inspect%E5%A6%82%E4%BD%95%E7%9F%A5%E9%81%93%E9%97%AE%E9%A2%98%E5%87%BA%E5%9C%A8%E6%A3%80%E7%B4%A2%E9%87%8D%E6%8E%92%E8%BF%98%E6%98%AF%E7%94%9F%E6%88%90/</link><pubDate>Wed, 25 Mar 2026 15:50:00 +0800</pubDate><guid>https://www.zata.cc/p/rag%E8%AF%84%E6%B5%8B%E4%B8%8E-inspect%E5%A6%82%E4%BD%95%E7%9F%A5%E9%81%93%E9%97%AE%E9%A2%98%E5%87%BA%E5%9C%A8%E6%A3%80%E7%B4%A2%E9%87%8D%E6%8E%92%E8%BF%98%E6%98%AF%E7%94%9F%E6%88%90/</guid><description>&lt;img src="https://www.zata.cc/p/rag%E8%AF%84%E6%B5%8B%E4%B8%8E-inspect%E5%A6%82%E4%BD%95%E7%9F%A5%E9%81%93%E9%97%AE%E9%A2%98%E5%87%BA%E5%9C%A8%E6%A3%80%E7%B4%A2%E9%87%8D%E6%8E%92%E8%BF%98%E6%98%AF%E7%94%9F%E6%88%90/images/index/index.png" alt="Featured image of post RAG评测与 Inspect：如何知道问题出在检索、重排还是生成" />&lt;p>很多 RAG 项目最开始都能跑起来，但一到线上就会卡在一个非常现实的问题上：&lt;/p>
&lt;p>用户说答案不对，可你根本不知道问题出在：&lt;/p>
&lt;ol>
&lt;li>没召回到正确内容&lt;/li>
&lt;li>召回到了，但排序不对&lt;/li>
&lt;li>排好了，但没进最终 prompt&lt;/li>
&lt;li>进了 prompt，但模型没用&lt;/li>
&lt;li>模型用了，但引用展示错了&lt;/li>
&lt;/ol>
&lt;p>所以 RAG 一定不能只做&amp;quot;生成结果观测&amp;quot;，还要做&amp;quot;阶段化 inspect&amp;quot;。&lt;/p>
&lt;p>这篇文章会讲：&lt;/p>
&lt;ul>
&lt;li>如何分层定位问题&lt;/li>
&lt;li>检索层和生成层的评测指标&lt;/li>
&lt;li>LLM-as-a-Judge 的原理&lt;/li>
&lt;li>Inspect 系统的设计思路&lt;/li>
&lt;/ul>
&lt;h2 id="一为什么评测这么难">一、为什么评测这么难
&lt;/h2>&lt;p>RAG 的评测比传统检索或传统 NLP 都复杂，因为它是多阶段的 pipeline。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">用户问题 → 检索 → 重排 → 组装 → 生成 → 答案
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最终答案错了，可能的原因：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">❌ 检索层：正确内容根本没召回
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 重排层：正确内容召回但被排到后面
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 组装层：正确内容被截断或过滤掉了
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 生成层：模型无视证据自由发挥
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果不分阶段评测，你只能知道&amp;quot;答案错了&amp;quot;，但不知道&amp;quot;为什么错&amp;quot;。&lt;/p>
&lt;h3 id="一个真实的问题定位案例">一个真实的问题定位案例
&lt;/h3>&lt;p>用户投诉：&amp;ldquo;问错误码 401 的意思，答案完全不对。&amp;rdquo;&lt;/p>
&lt;p>&lt;strong>定位过程&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">第 1 步：检查检索层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 用户问题：&amp;#34;错误码 401 是什么意思&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 检索候选 top-10：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 1. 常见 HTTP 错误码列表
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 2. 认证失败怎么办
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 3. 权限问题排查
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 8. 错误码详解：401 Unauthorized ← 正确答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结论：正确答案在候选里，但排第 8
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 2 步：检查重排层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Rerank 后：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 1. 错误码详解：401 Unauthorized ← 正确答案排到第 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 2. 常见 HTTP 错误码列表
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结论：重排正常
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 3 步：检查组装层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 最终进入 prompt 的 chunk：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 1. 错误码详解：401 Unauthorized ✅
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 2. 常见 HTTP 错误码列表 ✅
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 3. 认证失败怎么办 ✅
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结论：组装正常
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 4 步：检查生成层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Prompt 包含正确证据
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 模型输出：&amp;#34;错误码 401 表示服务器内部错误...&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结论：模型幻觉！401 是认证错误，不是服务器内部错误
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">最终诊断：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">✅ 检索层：正常
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">✅ 重排层：正常
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">✅ 组装层：正常
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 生成层：模型无视证据，产生幻觉
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">解决方案：优化 prompt，强化&amp;#34;必须依据证据&amp;#34;的约束
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这就是为什么需要分阶段评测——不同阶段的问题，解决方案完全不同。&lt;/p>
&lt;h2 id="二问题分层框架">二、问题分层框架
&lt;/h2>&lt;p>建议用下面这套分层框架，每层有明确的责任边界和常见问题：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 第 1 层：检索层（Retrieval） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 职责：从知识库中召回候选内容 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 常见问题： │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 正确 chunk 不在候选里 → chunking、embedding、检索策略 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 正确 chunk 排名太低 → 混合检索、Rerank │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 候选噪声太多 → metadata 过滤、召回数量调整 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 评测指标：Recall@K、MRR │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 第 2 层：重排层（Rerank） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 职责：对候选重新排序，提升相关性 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 常见问题： │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 正确 chunk 被排到后面 → Rerank 模型问题 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ Rerank 效果不明显 → 模型选择、候选数量 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 评测指标：排序提升比例、NDCG │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 第 3 层：上下文组装层（Context Assembly） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 职责：控制进入 prompt 的内容和数量 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 常见问题： │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 正确 chunk 被截断 → 调整 token 预算 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 正确 chunk 被过滤 → 检查过滤规则 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 内容太长噪声多 → 优化组装策略 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 评测指标：正确 chunk 进入 prompt 的比例 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 第 4 层：生成层（Generation） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 职责：基于证据生成答案 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 常见问题： │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 模型无视证据 → Prompt 优化 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 产生幻觉 → 强化约束、Few-shot │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 引用错误 → 后处理校验 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 评测指标：答案正确率、幻觉率、引用准确率 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="分层的意义">分层的意义
&lt;/h3>&lt;p>每一层的问题，需要不同的解决方案：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题层&lt;/th>
&lt;th>典型问题&lt;/th>
&lt;th>解决方向&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>检索层&lt;/td>
&lt;td>召不回正确内容&lt;/td>
&lt;td>Chunking、混合检索&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>重排层&lt;/td>
&lt;td>排序不对&lt;/td>
&lt;td>Rerank 模型&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>组装层&lt;/td>
&lt;td>内容被过滤&lt;/td>
&lt;td>组装策略、预算调整&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>生成层&lt;/td>
&lt;td>模型幻觉&lt;/td>
&lt;td>Prompt 优化、模型选择&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>不分层的问题&lt;/strong>：你发现答案错了，只能&amp;quot;盲调&amp;quot;——换模型、调参数，但不知道调的是哪个环节。&lt;/p>
&lt;p>&lt;strong>分层的好处&lt;/strong>：知道问题在哪一层，定向优化。&lt;/p>
&lt;h2 id="三检索层评测">三、检索层评测
&lt;/h2>&lt;p>检索层的核心问题是：&lt;strong>正确的 chunk 召回了吗？排得够靠前吗？&lt;/strong>&lt;/p>
&lt;h3 id="recallk">Recall@K
&lt;/h3>&lt;p>最直观的指标：正确答案是否在前 K 个候选里。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Recall@K = 正确答案在前 K 的请求数 / 总请求数
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">评测集 100 个问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">每个问题有 1-3 个正确 chunk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Recall@5 = 82/100 = 82%（82 个问题的正确 chunk 在前 5）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Recall@10 = 91/100 = 91%（91 个问题的正确 chunk 在前 10）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>解读&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>Recall@5 &amp;gt; 80%：检索质量良好&lt;/li>
&lt;li>Recall@5 &amp;lt; 60%：检索需要优化&lt;/li>
&lt;li>Recall@5 ≈ Recall@10：排序效果好（正确答案排在前面）&lt;/li>
&lt;li>Recall@5 &amp;laquo; Recall@10：排序效果差（正确答案在后面）&lt;/li>
&lt;/ul>
&lt;h3 id="mrrmean-reciprocal-rank">MRR（Mean Reciprocal Rank）
&lt;/h3>&lt;p>Recall@K 只看&amp;quot;是否在前 K&amp;quot;，MRR 还看&amp;quot;具体排第几&amp;quot;。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">MRR = Σ (1 / 正确答案的排名) / 总请求数
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">问题 1：正确答案排第 1 → 1/1 = 1.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题 2：正确答案排第 3 → 1/3 = 0.33
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题 3：正确答案排第 5 → 1/5 = 0.20
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题 4：正确答案未召回 → 1/∞ = 0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">MRR = (1.0 + 0.33 + 0.20 + 0) / 4 = 0.38
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>解读&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>MRR &amp;gt; 0.6：排序质量好&lt;/li>
&lt;li>MRR &amp;lt; 0.4：排序需要优化&lt;/li>
&lt;/ul>
&lt;h3 id="ndcgnormalized-discounted-cumulative-gain">NDCG（Normalized Discounted Cumulative Gain）
&lt;/h3>&lt;p>更精细的指标，考虑多个正确答案的情况。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">DCG = Σ (2^rel_i - 1) / log2(i + 1)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">其中：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- rel_i：第 i 个位置的相关性（1=相关，0=不相关）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- i：排名位置
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NDCG = DCG / IDCG
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">IDCG 是理想情况下的 DCG（所有相关文档都排在最前面）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>直觉&lt;/strong>：正确答案排得越靠前，分数越高；排在后面会被惩罚（除以 log）。&lt;/p>
&lt;h3 id="不同指标的选择">不同指标的选择
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>指标&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;th>优点&lt;/th>
&lt;th>缺点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Recall@K&lt;/td>
&lt;td>只关心是否召回&lt;/td>
&lt;td>直观、易解释&lt;/td>
&lt;td>不关心具体排名&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MRR&lt;/td>
&lt;td>关心正确答案的排名&lt;/td>
&lt;td>考虑排名&lt;/td>
&lt;td>只考虑第一个正确答案&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>NDCG&lt;/td>
&lt;td>有多个正确答案&lt;/td>
&lt;td>全面&lt;/td>
&lt;td>计算复杂&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>建议&lt;/strong>：日常用 Recall@5 + Recall@10，深入分析用 MRR 和 NDCG。&lt;/p>
&lt;h2 id="四生成层评测">四、生成层评测
&lt;/h2>&lt;p>检索层评测相对客观，生成层评测更主观——&amp;ldquo;答案好不好&amp;quot;没有标准答案。&lt;/p>
&lt;h3 id="传统指标">传统指标
&lt;/h3>&lt;p>&lt;strong>1. BLEU / ROUGE&lt;/strong>&lt;/p>
&lt;p>来自机器翻译和摘要领域，计算模型输出和参考答案的 n-gram 重叠度。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">BLEU-1: 单词重叠
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BLEU-2: 二元组重叠
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ROUGE-L: 最长公共子序列
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>问题&lt;/strong>：RAG 答案不追求和参考答案&amp;quot;字面相似&amp;rdquo;，而是追求&amp;quot;语义正确&amp;quot;。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">参考答案：&amp;#34;使用 Bearer Token 认证&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">模型答案：&amp;#34;认证方式是 Bearer Token&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BLEU 分数不高，但语义完全正确。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. BERTScore&lt;/strong>&lt;/p>
&lt;p>用 BERT 编码后计算语义相似度。比 n-gram 更好，但对 RAG 仍不够精确。&lt;/p>
&lt;h3 id="llm-as-a-judge">LLM-as-a-Judge
&lt;/h3>&lt;p>让大模型来评判答案质量，是目前最实用的方法。&lt;/p>
&lt;p>&lt;strong>思路&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">输入：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 用户问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 参考答案（可选）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 模型答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 证据内容（检索到的 chunk）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">输出：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 分数（1-5）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 是否正确
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 是否有幻觉
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 具体问题
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Prompt 设计&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">你是一个答案质量评判专家。请评判以下答案的质量。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题：{question}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">参考资料：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{context}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">参考答案：{expected_answer}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">模型答案：{actual_answer}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">请评判：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 正确性（1-5分）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 是否包含幻觉（编造参考资料中没有的信息）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 是否遗漏关键信息
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4. 引用是否正确
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">以 JSON 格式输出：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;score&amp;#34;: 1-5,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;is_correct&amp;#34;: true/false,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;has_hallucination&amp;#34;: true/false,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;issues&amp;#34;: [&amp;#34;问题1&amp;#34;, &amp;#34;问题2&amp;#34;],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;explanation&amp;#34;: &amp;#34;评分理由&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>为什么有效&lt;/strong>？&lt;/p>
&lt;p>LLM 本身有很强的语义理解能力，能判断&amp;quot;语义相似&amp;quot;而非&amp;quot;字面相似&amp;quot;。而且 LLM 能理解上下文，判断答案是否&amp;quot;基于证据&amp;quot;。&lt;/p>
&lt;p>&lt;strong>注意事项&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>评判模型要强&lt;/strong>：用 GPT-4 或 Claude，不要用小模型&lt;/li>
&lt;li>&lt;strong>避免自我评判&lt;/strong>：生成模型和评判模型要不同&lt;/li>
&lt;li>&lt;strong>Few-shot 示例&lt;/strong>：给几个评分示例，提高一致性&lt;/li>
&lt;li>&lt;strong>多次评判取平均&lt;/strong>：减少随机性&lt;/li>
&lt;/ol>
&lt;h3 id="评测指标的层次">评测指标的层次
&lt;/h3>&lt;p>生成层评测应该回答几个不同的问题：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题&lt;/th>
&lt;th>指标&lt;/th>
&lt;th>怎么测&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>答案对吗？&lt;/td>
&lt;td>正确率&lt;/td>
&lt;td>LLM 评判 + 人工抽查&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有幻觉吗？&lt;/td>
&lt;td>幻觉率&lt;/td>
&lt;td>检查答案是否超出证据范围&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>引用对吗？&lt;/td>
&lt;td>引用准确率&lt;/td>
&lt;td>检查引用的 chunk 是否支持答案&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>用户满意吗？&lt;/td>
&lt;td>满意度&lt;/td>
&lt;td>用户反馈&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>幻觉检测&lt;/strong>是最重要的，因为 RAG 的核心价值是&amp;quot;有据可查&amp;quot;。&lt;/p>
&lt;h3 id="幻觉检测的方法">幻觉检测的方法
&lt;/h3>&lt;p>&lt;strong>方法 1：LLM 评判&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Prompt：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;以下答案是否包含参考资料中没有的信息？&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">答案：{answer}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">参考资料：{context}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">请指出答案中的每一句话，并判断是否有证据支持。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>方法 2：NLI（自然语言推理）&lt;/strong>&lt;/p>
&lt;p>用 NLI 模型判断答案和证据之间的关系：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">前提（证据）：&amp;#34;Token 有效期为 24 小时&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">假设（答案）：&amp;#34;Token 有效期为 48 小时&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">NLI 输出：Contradiction（矛盾）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>方法 3：关键词匹配&lt;/strong>&lt;/p>
&lt;p>简单但粗糙：检查答案中的关键信息是否在证据中出现。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">答案：&amp;#34;API 超时时间是 30 秒&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">证据：&amp;#34;API 的默认超时时间为 30 秒&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">匹配：✅（&amp;#34;超时&amp;#34;、&amp;#34;30&amp;#34;、&amp;#34;秒&amp;#34;都在证据中）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="五离线评测-vs-在线评测">五、离线评测 vs 在线评测
&lt;/h2>&lt;h3 id="离线评测">离线评测
&lt;/h3>&lt;p>&lt;strong>目的&lt;/strong>：在上线前验证系统质量&lt;/p>
&lt;p>&lt;strong>方法&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>准备评测集（50-100 条）&lt;/li>
&lt;li>定期跑评测&lt;/li>
&lt;li>对比不同版本&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>评测集构建&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">评测集应该包含：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 核心问题（30%）：业务最常见的问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 边界问题（30%）：难度高、容易出错的
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 长尾问题（20%）：覆盖更多场景
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 坏案例（20%）：之前出过问题的
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">每条评测数据：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;id&amp;#34;: &amp;#34;eval_001&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;question&amp;#34;: &amp;#34;API 的认证方式是什么&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;expected_chunks&amp;#34;: [&amp;#34;chunk_012&amp;#34;], // 期望召回的 chunk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;expected_answer&amp;#34;: &amp;#34;Bearer Token&amp;#34;, // 参考答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;category&amp;#34;: &amp;#34;技术问题&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;difficulty&amp;#34;: &amp;#34;easy&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>评测流程&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">1. 运行 RAG 系统，获取结果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 计算检索指标（Recall@K、MRR）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 计算生成指标（正确率、幻觉率）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4. 汇总报告
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5. 对比历史版本
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="在线评测">在线评测
&lt;/h3>&lt;p>&lt;strong>目的&lt;/strong>：在生产环境持续监控&lt;/p>
&lt;p>&lt;strong>方法&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>用户反馈&lt;/strong>：点赞/点踩、修改问题、人工标注&lt;/li>
&lt;li>&lt;strong>自动评分&lt;/strong>：用 LLM 对线上答案打分&lt;/li>
&lt;li>&lt;strong>行为分析&lt;/strong>：用户是否追问、是否放弃&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>采样策略&lt;/strong>：&lt;/p>
&lt;p>不是所有请求都需要详细评测（成本高）。建议：&lt;/p>
&lt;ul>
&lt;li>100% 记录基本信息（延迟、召回数量）&lt;/li>
&lt;li>10% 详细评分（LLM 评判）&lt;/li>
&lt;li>1% 人工审核&lt;/li>
&lt;/ul>
&lt;h3 id="评测陷阱">评测陷阱
&lt;/h3>&lt;p>&lt;strong>陷阱 1：评测集泄露&lt;/strong>&lt;/p>
&lt;p>训练 Embedding 模型或 Rerank 模型时，不小心用了评测集里的内容。评测分数虚高，线上效果差。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：评测集严格隔离，不参与任何训练。&lt;/p>
&lt;p>&lt;strong>陷阱 2：评测集不代表真实&lt;/strong>&lt;/p>
&lt;p>评测集都是&amp;quot;理想问题&amp;quot;，线上用户的问题五花八门：口语化、错别字、表达不清。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：定期从线上采样真实问题，加入评测集。&lt;/p>
&lt;p>&lt;strong>陷阱 3：只看单一指标&lt;/strong>&lt;/p>
&lt;p>只看 Recall@5，可能忽略了答案质量。检索到了，但答案仍然不好。&lt;/p>
&lt;p>&lt;strong>解决&lt;/strong>：多指标综合评估，建立指标大盘。&lt;/p>
&lt;h2 id="六inspect-系统定位单次问题">六、Inspect 系统：定位单次问题
&lt;/h2>&lt;p>评测解决&amp;quot;系统整体质量&amp;quot;，Inspect 解决&amp;quot;某次请求为什么出错&amp;quot;。&lt;/p>
&lt;h3 id="inspect-系统的核心能力">Inspect 系统的核心能力
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>能力&lt;/th>
&lt;th>回答的问题&lt;/th>
&lt;th>需要的数据&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>检索可视化&lt;/td>
&lt;td>召回了什么？排第几？&lt;/td>
&lt;td>候选列表、分数&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>重排对比&lt;/td>
&lt;td>Rerank 前后有什么变化？&lt;/td>
&lt;td>重排前后列表&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Prompt 快照&lt;/td>
&lt;td>模型看到了什么？&lt;/td>
&lt;td>最终 prompt&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>引用追溯&lt;/td>
&lt;td>答案来自哪？&lt;/td>
&lt;td>引用的 chunk&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="trace-的数据结构">Trace 的数据结构
&lt;/h3>&lt;p>每次请求都应该保存完整的 Trace：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Trace 结构：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;trace_id&amp;#34;: &amp;#34;唯一标识&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;timestamp&amp;#34;: &amp;#34;请求时间&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;query&amp;#34;: &amp;#34;用户问题&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;retrieval&amp;#34;: {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;dense_results&amp;#34;: [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {&amp;#34;chunk_id&amp;#34;: &amp;#34;xxx&amp;#34;, &amp;#34;score&amp;#34;: 0.82, &amp;#34;rank&amp;#34;: 1},
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;bm25_results&amp;#34;: [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {&amp;#34;chunk_id&amp;#34;: &amp;#34;xxx&amp;#34;, &amp;#34;score&amp;#34;: 5.2, &amp;#34;rank&amp;#34;: 1},
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;merged_results&amp;#34;: [...], // RRF 融合后
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;reranked_results&amp;#34;: [...] // Rerank 后
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> },
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;context&amp;#34;: {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;final_chunks&amp;#34;: [...], // 最终进入 prompt 的
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;prompt&amp;#34;: &amp;#34;...&amp;#34;, // 完整 prompt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;token_count&amp;#34;: 3200
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> },
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;generation&amp;#34;: {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;answer&amp;#34;: &amp;#34;模型回答&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;citations&amp;#34;: [...],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;model&amp;#34;: &amp;#34;gpt-4o-mini&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> },
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;latency&amp;#34;: {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;total_ms&amp;#34;: 450,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;retrieval_ms&amp;#34;: 50,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;rerank_ms&amp;#34;: 180,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;generation_ms&amp;#34;: 220
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="inspect-页面的设计">Inspect 页面的设计
&lt;/h3>&lt;p>一个实用的 Inspect 页面应该包含：&lt;/p>
&lt;p>&lt;strong>1. 概览区&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">问题：错误码 401 是什么意思
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">答案：401 表示认证失败...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">耗时：450ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">状态：❌ 答案错误（模型幻觉）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. 检索区&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Dense 检索结果：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">#1 [0.82] 常见 HTTP 错误码
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">#2 [0.79] 认证失败怎么办
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">#8 [0.65] 错误码详解：401 ← 正确答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BM25 检索结果：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">#1 [5.2] 错误码详解：401 ← 正确答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">#2 [4.8] 常见 HTTP 错误码
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Rerank 后：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">#1 [0.92] 错误码详解：401 ← 正确答案排到第 1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>3. Prompt 区&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">最终进入 Prompt 的 chunk：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[1] 错误码详解：401 Unauthorized
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Token 无效或已过期...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[2] 常见 HTTP 错误码
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">完整 Prompt：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[显示完整 prompt 内容]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>4. 评分区&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">检索是否正确：✅
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">答案是否正确：❌
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">是否有幻觉：✅（模型说&amp;#34;服务器内部错误&amp;#34;）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">备注：________________
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="trace-的存储">Trace 的存储
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>方案&lt;/th>
&lt;th>优点&lt;/th>
&lt;th>缺点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>SQLite&lt;/td>
&lt;td>简单、本地&lt;/td>
&lt;td>不适合大规模&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PostgreSQL&lt;/td>
&lt;td>功能强&lt;/td>
&lt;td>需要运维&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Elasticsearch&lt;/td>
&lt;td>搜索方便&lt;/td>
&lt;td>成本高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>专用平台（LangSmith、Langfuse）&lt;/td>
&lt;td>功能全&lt;/td>
&lt;td>可能有成本&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>建议&lt;/strong>：小规模用 SQLite/PostgreSQL，大规模用专用平台。&lt;/p>
&lt;h2 id="七排障流程">七、排障流程
&lt;/h2>&lt;p>当你发现某个问题回答不对时，按这个流程排查：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">第 1 步：获取 Trace ID
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">从用户反馈或日志中获取
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 2 步：检查检索层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">正确 chunk 是否在候选里？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 不在候选：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 检查 chunking（是否被切碎）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 检查 embedding（是否理解正确）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 检索策略（是否需要混合检索）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">✅ 在候选但排名靠后：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 继续检查重排层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 3 步：检查重排层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Rerank 后排名是否提升？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 排名下降或不变：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → Rerank 模型可能不适合这个场景
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 考虑换模型或调整权重
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">✅ 排名提升但仍不在 top-5：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 召回数量不够
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 增加召回数量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 4 步：检查组装层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">正确 chunk 是否进入 prompt？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 未进入：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 被截断：调整 token 预算
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 被过滤：检查过滤规则
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">✅ 已进入：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 继续检查生成层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 5 步：检查生成层
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">模型是否正确使用证据？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 模型无视证据：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 强化 prompt 约束
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 添加 Few-shot 示例
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 模型幻觉：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 明确&amp;#34;不确定时说明不确定&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 后处理校验
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❌ 引用错误：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 优化引用格式要求
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → 后处理修正
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="八本文小结">八、本文小结
&lt;/h2>&lt;p>RAG 要做到可迭代，必须建立完整的评测和观测体系：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>能力&lt;/th>
&lt;th>解决的问题&lt;/th>
&lt;th>核心方法&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>分层评测&lt;/td>
&lt;td>定位问题在哪一层&lt;/td>
&lt;td>Recall@K、LLM-as-Judge&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>离线评测&lt;/td>
&lt;td>验证系统质量&lt;/td>
&lt;td>评测集 + 定期跑分&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>在线评测&lt;/td>
&lt;td>监控生产质量&lt;/td>
&lt;td>采样 + 自动评分&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Inspect&lt;/td>
&lt;td>定位单次问题&lt;/td>
&lt;td>Trace + 可视化&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>核心建议&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>先建评测集&lt;/strong>：没有评测集，优化都是盲人摸象&lt;/li>
&lt;li>&lt;strong>分层评测&lt;/strong>：检索和生成分开评，知道优化哪一层&lt;/li>
&lt;li>&lt;strong>保留 Trace&lt;/strong>：每次请求都记录中间结果&lt;/li>
&lt;li>&lt;strong>持续监控&lt;/strong>：建立指标大盘，设置告警&lt;/li>
&lt;/ol>
&lt;p>只有这样，才能从&amp;quot;会用 RAG&amp;quot;走到&amp;quot;会调 RAG&amp;quot;。&lt;/p>
&lt;p>下一篇会讲生产环境最常见的坑，以及一条可执行的迭代路线。&lt;/p></description></item><item><title>RAG进阶：Chunking、召回、Hybrid Search 与 Rerank</title><link>https://www.zata.cc/p/rag%E8%BF%9B%E9%98%B6chunking%E5%8F%AC%E5%9B%9Ehybrid-search-%E4%B8%8E-rerank/</link><pubDate>Wed, 25 Mar 2026 15:45:00 +0800</pubDate><guid>https://www.zata.cc/p/rag%E8%BF%9B%E9%98%B6chunking%E5%8F%AC%E5%9B%9Ehybrid-search-%E4%B8%8E-rerank/</guid><description>&lt;img src="https://www.zata.cc/p/rag%E8%BF%9B%E9%98%B6chunking%E5%8F%AC%E5%9B%9Ehybrid-search-%E4%B8%8E-rerank/images/index/index.png" alt="Featured image of post RAG进阶：Chunking、召回、Hybrid Search 与 Rerank" />&lt;p>很多人第一次做 RAG，默认流程都是：&lt;/p>
&lt;ol>
&lt;li>文档切 chunk&lt;/li>
&lt;li>生成 embedding&lt;/li>
&lt;li>向量检索 top_k&lt;/li>
&lt;li>拼 prompt&lt;/li>
&lt;li>让模型回答&lt;/li>
&lt;/ol>
&lt;p>这条路径能跑，但往往不稳。真正让 RAG 质量提升一个台阶的，通常是三件事：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>chunking 做得更合理&lt;/strong> — 切出来的 chunk 能独立成为证据&lt;/li>
&lt;li>&lt;strong>召回从单路 dense 变成多路召回&lt;/strong> — 结合语义和关键词&lt;/li>
&lt;li>&lt;strong>用真正的 rerank 做精排&lt;/strong> — 不是简单重排，而是用 cross-encoder 重新打分&lt;/li>
&lt;/ul>
&lt;p>这篇文章会深入讲这三个环节的算法原理。&lt;/p>
&lt;h2 id="一chunking为什么切短一点不简单">一、Chunking：为什么&amp;quot;切短一点&amp;quot;不简单
&lt;/h2>&lt;p>Chunking 的目标不是凑 embedding 输入长度，而是让&amp;quot;一个 chunk 刚好能独立成为证据&amp;quot;。&lt;/p>
&lt;h3 id="好的-chunk-应该满足什么">好的 Chunk 应该满足什么
&lt;/h3>&lt;p>四个标准：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>语义完整&lt;/strong> — 一个 chunk 能回答一个独立的问题&lt;/li>
&lt;li>&lt;strong>粒度适中&lt;/strong> — 太大噪声多，太小信息不够&lt;/li>
&lt;li>&lt;strong>上下文自洽&lt;/strong> — 不依赖外部信息也能理解&lt;/li>
&lt;li>&lt;strong>可追溯&lt;/strong> — 知道来自哪个文档、哪个章节&lt;/li>
&lt;/ol>
&lt;h3 id="固定长度切分的问题">固定长度切分的问题
&lt;/h3>&lt;p>最简单的做法是按字符数切：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">每 500 个字符切一段
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>问题：&lt;/p>
&lt;p>&lt;strong>问题 1：语义被切断&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原文：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;所有 API 请求必须在 Header 中携带 Bearer Token。Token 有效期为 24 小时，
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">过期后需重新获取。获取方式：调用 /auth/token 接口，传入 client_id
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">和 client_secret。&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">固定切分后，某个 chunk 可能变成：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;过期后需重新获取。获取方式：调用 /auth/token 接口，传入 client_id&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户问&amp;#34;Token 有效期多久？&amp;#34;，这个 chunk 不会召回。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>问题 2：上下文丢失&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原文：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;### 2.3 校准流程
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">将旋钮调至 3 档，等待指示灯变为绿色后松开。&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">按段落切分后：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;将旋钮调至 3 档，等待指示灯变为绿色后松开。&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户问&amp;#34;ZK-200 怎么校准&amp;#34;，这个 chunk 不会召回。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">因为&amp;#34;ZK-200&amp;#34;在标题里，&amp;#34;校准&amp;#34;在章节名里——都被切掉了。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="语义切分的思路">语义切分的思路
&lt;/h3>&lt;p>更好的方法是&lt;strong>按文档的自然结构切分&lt;/strong>：&lt;/p>
&lt;p>&lt;strong>1. 按 Markdown 标题切分&lt;/strong>&lt;/p>
&lt;p>Markdown 文档有天然的层级结构：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl"># 一级标题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 二级标题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">### 三级标题
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>切分策略：每个标题下的内容作为一个 chunk，并保留标题作为上下文。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Chunk 1:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">【API 规范 &amp;gt; 2. 认证 &amp;gt; 2.1 认证方式】
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">所有 API 请求必须在 Header 中携带 Bearer Token...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Chunk 2:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">【API 规范 &amp;gt; 2. 认证 &amp;gt; 2.2 Token 获取】
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">调用 /auth/token 接口获取 Token...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. 按段落切分&lt;/strong>&lt;/p>
&lt;p>对于没有明确结构的文档，按段落切分比按字符数好：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">段落边界通常是语义边界。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">一个段落讲一个观点，不会把一句话切两半。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>3. 语义切分（高级）&lt;/strong>&lt;/p>
&lt;p>用 Embedding 模型判断相邻段落的语义相似度：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">步骤：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 把文档按句子切分
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 计算相邻句子的 embedding 相似度
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 相似度低的地方 = 语义边界，切分
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>直觉：如果两句话语义相似度低，说明在讲不同的话题，应该分开。&lt;/p>
&lt;p>代价：计算量大，不一定比结构化切分更好。&lt;/p>
&lt;h3 id="contextual-chunking最重要的一步">Contextual Chunking：最重要的一步
&lt;/h3>&lt;p>无论用什么切分方法，都建议做一步：&lt;strong>把父级标题拼到 chunk 前面。&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始 chunk：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;将旋钮调至 3 档，等待指示灯变为绿色后松开。&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">补充上下文后：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;【ZK-200 操作手册 &amp;gt; 2. 使用方法 &amp;gt; 2.3 校准流程】
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">将旋钮调至 3 档，等待指示灯变为绿色后松开。&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>为什么有效？&lt;/p>
&lt;p>&lt;strong>原理&lt;/strong>：Embedding 模型会把整个 chunk 编码成一个向量。如果 chunk 里包含&amp;quot;ZK-200&amp;quot;和&amp;quot;校准&amp;quot;，当用户问&amp;quot;ZK-200 怎么校准&amp;quot;时，相似度就会高。&lt;/p>
&lt;p>&lt;strong>实测效果&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置&lt;/th>
&lt;th>Recall@5&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>原始 chunk&lt;/td>
&lt;td>41%&lt;/td>
&lt;td>大量 chunk 缺上下文&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>补充标题上下文&lt;/td>
&lt;td>78%&lt;/td>
&lt;td>效果翻倍&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>成本几乎为零，但效果提升明显。这是 RAG 里性价比最高的优化之一。&lt;/p>
&lt;h3 id="chunk-粒度的权衡">Chunk 粒度的权衡
&lt;/h3>&lt;p>太大 vs 太小：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题&lt;/th>
&lt;th>太大（1000+ 字）&lt;/th>
&lt;th>太小（&amp;lt;100 字）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>噪声&lt;/td>
&lt;td>噪声多，关键信息被埋&lt;/td>
&lt;td>信息不够，上下文缺失&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>检索&lt;/td>
&lt;td>容易召回不相关内容&lt;/td>
&lt;td>可能召回片段，语义不完整&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>成本&lt;/td>
&lt;td>Token 消耗大&lt;/td>
&lt;td>Chunk 数量多，索引大&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>经验值&lt;/strong>：300-500 tokens（中文约 200-350 字）&lt;/p>
&lt;p>但比长度更重要的是&lt;strong>语义完整性&lt;/strong>。宁可长度不均，也不要语义被切断。&lt;/p>
&lt;h3 id="不同文档类型的切分策略">不同文档类型的切分策略
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>文档类型&lt;/th>
&lt;th>推荐策略&lt;/th>
&lt;th>原因&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>FAQ&lt;/td>
&lt;td>一条一 chunk&lt;/td>
&lt;td>每条 FAQ 天然独立&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>技术文档&lt;/td>
&lt;td>按标题/小节&lt;/td>
&lt;td>标题是天然语义边界&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>产品手册&lt;/td>
&lt;td>按操作步骤&lt;/td>
&lt;td>一个步骤一个 chunk&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>合同/法规&lt;/td>
&lt;td>按条款&lt;/td>
&lt;td>每条条款有独立法律意义&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>对话记录&lt;/td>
&lt;td>按问答对&lt;/td>
&lt;td>一问一答是完整语义单元&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="二bm25关键词检索的经典算法">二、BM25：关键词检索的经典算法
&lt;/h2>&lt;p>向量检索擅长语义相似，但对精确匹配不稳定。解决方案是引入关键词检索。&lt;/p>
&lt;p>最经典的关键词检索算法是 &lt;strong>BM25&lt;/strong>（Best Matching 25）。&lt;/p>
&lt;h3 id="bm25-的原理">BM25 的原理
&lt;/h3>&lt;p>BM25 是 TF-IDF 的改进版。先理解 TF-IDF：&lt;/p>
&lt;p>&lt;strong>TF-IDF = TF × IDF&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>TF（Term Frequency）&lt;/strong>：词在文档中出现的次数&lt;/p>
&lt;ul>
&lt;li>出现越多，越重要？不完全是，需要惩罚高频词&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>IDF（Inverse Document Frequency）&lt;/strong>：词的稀有程度&lt;/p>
&lt;ul>
&lt;li>在所有文档中很少出现 → 区分度高 → 权重高&lt;/li>
&lt;li>在所有文档中都出现（如&amp;quot;的&amp;quot;、&amp;ldquo;是&amp;rdquo;）→ 区分度低 → 权重低&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>问题&lt;/strong>：TF 会过度奖励高频词。一个词出现 10 次不代表比出现 1 次重要 10 倍。&lt;/p>
&lt;p>&lt;strong>BM25 的改进&lt;/strong>：对 TF 做饱和处理。&lt;/p>
&lt;h3 id="bm25-公式">BM25 公式
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">score(D, Q) = Σ IDF(qi) × (f(qi, D) × (k1 + 1)) / (f(qi, D) + k1 × (1 - b + b × |D|/avgdl))
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">其中：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- D：文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Q：查询（包含多个词 q1, q2, ...）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- qi：查询中的第 i 个词
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- f(qi, D)：词 qi 在文档 D 中的词频
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- |D|：文档 D 的长度
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- avgdl：平均文档长度
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- k1：词频饱和参数（通常 1.2-2.0）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- b：长度归一化参数（通常 0.75）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">IDF(qi) = log((N - n(qi) + 0.5) / (n(qi) + 0.5) + 1)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- N：总文档数
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- n(qi)：包含词 qi 的文档数
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>直觉理解&lt;/strong>：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>词频饱和&lt;/strong>：&lt;code>(f × (k1+1)) / (f + k1)&lt;/code> 是一个饱和函数。当 f 很大时，增长变慢。一个词出现 10 次，权重不是 10 倍，而是趋于 k1+1。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>长度归一化&lt;/strong>：长文档天然有更高的词频，需要惩罚。&lt;code>|D|/avgdl&lt;/code> 是相对长度，通过参数 b 控制惩罚程度。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>IDF 奖励稀有词&lt;/strong>：在少数文档中出现的词，IDF 高，权重高。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="bm25-的特点">BM25 的特点
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>优点&lt;/th>
&lt;th>缺点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>对精确匹配敏感&lt;/td>
&lt;td>不理解语义&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>对编号、术语稳定&lt;/td>
&lt;td>同义词问题（&amp;ldquo;电脑&amp;quot;和&amp;quot;计算机&amp;quot;是两个词）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>计算快，可解释&lt;/td>
&lt;td>需要分词（中文需要额外的分词步骤）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>不需要训练&lt;/td>
&lt;td>不适合自然语言问题&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>适用场景&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>用户查询包含编号、版本号、专业术语&lt;/li>
&lt;li>文档中有大量缩写、代码&lt;/li>
&lt;li>需要精确匹配的场景&lt;/li>
&lt;/ul>
&lt;h3 id="中文分词">中文分词
&lt;/h3>&lt;p>BM25 依赖词的边界。英文天然有空格分隔，中文需要额外的分词步骤。&lt;/p>
&lt;p>常用分词工具：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>工具&lt;/th>
&lt;th>特点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>jieba&lt;/td>
&lt;td>最流行，词典+HMM&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>pkuseg&lt;/td>
&lt;td>北大出品，准确率高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>HanLP&lt;/td>
&lt;td>功能全，支持多种任务&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>分词质量直接影响 BM25 效果。比如：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">&amp;#34;用户体验设计&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">分词 1：用户 / 体验 / 设计（三个词）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">分词 2：用户体验 / 设计（两个词）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">分词 3：用户 / 体验设计（两个词）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">不同的分词，检索结果不同。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="三hybrid-retrieval语义--关键词">三、Hybrid Retrieval：语义 + 关键词
&lt;/h2>&lt;p>向量检索和 BM25 各有优劣，互补性很强。&lt;/p>
&lt;h3 id="为什么需要混合">为什么需要混合
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">向量检索：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 擅长：语义相似、同义词、自然语言问题
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 弱项：精确匹配、编号、专业术语
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BM25：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 擅长：精确匹配、编号、专业术语
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 弱项：语义理解、同义词、自然语言问题
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>实测对比&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>查询类型&lt;/th>
&lt;th>向量检索 Recall@5&lt;/th>
&lt;th>BM25 Recall@5&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>语义查询（&amp;ldquo;怎么获取令牌&amp;rdquo;）&lt;/td>
&lt;td>82%&lt;/td>
&lt;td>58%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>精确匹配（&amp;ldquo;错误码 401&amp;rdquo;）&lt;/td>
&lt;td>47%&lt;/td>
&lt;td>76%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>编号查询（&amp;ldquo;版本 v2.3.1&amp;rdquo;）&lt;/td>
&lt;td>38%&lt;/td>
&lt;td>69%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>混合查询（&amp;ldquo;API v2 认证方式&amp;rdquo;）&lt;/td>
&lt;td>64%&lt;/td>
&lt;td>71%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>没有哪种方法在所有场景下都最优。混合检索可以兼顾两者。&lt;/p>
&lt;h3 id="混合检索的架构">混合检索的架构
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Query
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─── 向量检索 ──→ Dense 候选集（top-50）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─── BM25 检索 ──→ Sparse 候选集（top-50）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─── Metadata 过滤 ──→ 过滤后的候选集
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 结果融合
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Rerank（可选）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 最终结果（top-5）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="结果融合rrfreciprocal-rank-fusion">结果融合：RRF（Reciprocal Rank Fusion）
&lt;/h3>&lt;p>两路检索结果怎么合并？简单的方法是按分数加权，但问题：向量分数和 BM25 分数不在同一个尺度，不好比较。&lt;/p>
&lt;p>更优雅的方法是 &lt;strong>RRF（Reciprocal Rank Fusion）&lt;/strong>：不依赖分数，只依赖排名。&lt;/p>
&lt;p>&lt;strong>RRF 公式&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">RRF_score(d) = Σ 1 / (k + rank_i(d))
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">其中：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- d：文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- rank_i(d)：文档 d 在第 i 路检索中的排名
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- k：平滑参数（通常取 60）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>直觉&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>排名第 1 的文档得分：1/(60+1) ≈ 0.0164&lt;/li>
&lt;li>排名第 2 的文档得分：1/(60+2) ≈ 0.0159&lt;/li>
&lt;li>排名第 10 的文档得分：1/(60+10) ≈ 0.0143&lt;/li>
&lt;/ul>
&lt;p>排名越高，得分越高，但差距被平滑。k 越大，不同排名之间的得分差距越小。&lt;/p>
&lt;p>&lt;strong>为什么有效&lt;/strong>？&lt;/p>
&lt;ol>
&lt;li>&lt;strong>不依赖分数&lt;/strong>：避免了分数归一化的问题&lt;/li>
&lt;li>&lt;strong>鲁棒性强&lt;/strong>：单路检索的异常高分不会主导结果&lt;/li>
&lt;li>&lt;strong>简单高效&lt;/strong>：只需要排名信息，计算量小&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>示例&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Query：&amp;#34;错误码 401&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">向量检索结果：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. Doc_A（向量分数 0.82）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. Doc_B（向量分数 0.79）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. Doc_C（向量分数 0.76）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BM25 检索结果：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. Doc_D（BM25 分数 5.2）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. Doc_C（BM25 分数 4.8）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. Doc_A（BM25 分数 4.1）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RRF 融合（k=60）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Doc_A: 1/(60+1) + 1/(60+3) = 0.0164 + 0.0159 = 0.0323
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Doc_B: 1/(60+2) + 0 = 0.0159（BM25 没召回）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Doc_C: 1/(60+3) + 1/(60+2) = 0.0159 + 0.0159 = 0.0318
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Doc_D: 0 + 1/(60+1) = 0.0164（向量没召回）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">最终排序：Doc_A &amp;gt; Doc_C &amp;gt; Doc_B &amp;gt; Doc_D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Doc_A 在两路都有出现，最终得分最高。这就是 RRF 的魅力：&lt;strong>两路都召回的文档，更有可能是相关的。&lt;/strong>&lt;/p>
&lt;h3 id="metadata-过滤">Metadata 过滤
&lt;/h3>&lt;p>除了向量检索和 BM25，还可以利用元数据做过滤：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">用户问：&amp;#34;销售合同模板在哪下载？&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">先过滤：source = &amp;#34;sales_docs&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">再检索：在销售文档范围内检索
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">好处：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 缩小检索范围，减少噪声
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 提高检索精度
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 支持权限隔离（不同用户可见不同来源）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>过滤可以在检索前（pre-filtering）或检索后（post-filtering）。主流向量库都支持 pre-filtering，效率更高。&lt;/p>
&lt;h2 id="四rerank精排的原理">四、Rerank：精排的原理
&lt;/h2>&lt;p>召回阶段的目标是&amp;quot;别漏掉&amp;rdquo;，所以召回数量较多，难免混入噪声。Rerank 阶段的目标是&amp;quot;降噪&amp;quot;，从候选中选出最相关的。&lt;/p>
&lt;h3 id="为什么需要-rerank">为什么需要 Rerank
&lt;/h3>&lt;p>向量检索和 BM25 都是&amp;quot;双塔&amp;quot;结构：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Query → Encoder → Query Vector ─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├→ Similarity
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Document → Encoder → Doc Vector ─┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Query 和 Document 各自编码，只在最后计算相似度。&lt;/p>
&lt;p>&lt;strong>问题&lt;/strong>：Query 和 Document 之间的交互太少。编码时看不到对方，只能依赖各自的信息。&lt;/p>
&lt;p>&lt;strong>Rerank 的思路&lt;/strong>：让 Query 和 Document 充分交互，更精确地判断相关性。&lt;/p>
&lt;h3 id="cross-encoder-的工作原理">Cross-Encoder 的工作原理
&lt;/h3>&lt;p>Cross-Encoder 是&amp;quot;单塔&amp;quot;结构：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Query + Document → Transformer → Relevance Score
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>把 Query 和 Document 拼在一起，丢进 Transformer，让模型自己学习两者的交互。&lt;/p>
&lt;p>&lt;strong>示意&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">输入：[CLS] Query [SEP] Document [SEP]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Transformer 会计算每个 token 和其他所有 token 的注意力，
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">包括 Query token 和 Document token 之间的交互。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">输出：[CLS] 位置的向量 → 全连接层 → 相关性分数
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>为什么比双塔更准&lt;/strong>？&lt;/p>
&lt;p>双塔：Query 编码时看不到 Document，只能用通用的语义表示。
单塔：Query 和 Document 一起编码，模型可以看到两者之间的关系。&lt;/p>
&lt;p>比如：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Query：&amp;#34;苹果的价格&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Document 1：&amp;#34;苹果公司股价下跌&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Document 2：&amp;#34;水果店苹果 5 元一斤&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">双塔可能把两个 Document 都召回（都包含&amp;#34;苹果&amp;#34;和&amp;#34;价格&amp;#34;相关词）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Cross-Encoder 能判断：Document 2 更相关（语义上&amp;#34;价格&amp;#34;指水果价格，不是股价）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>为什么不能替代检索&lt;/strong>？&lt;/p>
&lt;p>Cross-Encoder 需要把 Query 和每个 Document 都拼起来过一遍模型。&lt;/p>
&lt;p>计算量 = 候选数量 × Transformer 计算量&lt;/p>
&lt;p>如果候选是 100 万，计算量巨大，延迟无法接受。&lt;/p>
&lt;p>所以只能用在召回之后，对小规模候选做精排。&lt;/p>
&lt;h3 id="rerank-模型">Rerank 模型
&lt;/h3>&lt;p>常用 Rerank 模型：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模型&lt;/th>
&lt;th>特点&lt;/th>
&lt;th>延迟（100 候选）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>bge-reranker-large&lt;/td>
&lt;td>开源，效果好&lt;/td>
&lt;td>~180ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bge-reranker-base&lt;/td>
&lt;td>开源，更快&lt;/td>
&lt;td>~95ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cohere rerank-3&lt;/td>
&lt;td>API，效果好&lt;/td>
&lt;td>~120ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ms-marco-MiniLM&lt;/td>
&lt;td>开源，轻量&lt;/td>
&lt;td>~45ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>jina-reranker-v2&lt;/td>
&lt;td>开源，多语言&lt;/td>
&lt;td>~80ms&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>选择考虑：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>追求效果&lt;/strong>：bge-reranker-large 或 cohere rerank-3&lt;/li>
&lt;li>&lt;strong>追求速度&lt;/strong>：ms-marco-MiniLM 或 bge-reranker-base&lt;/li>
&lt;li>&lt;strong>中文场景&lt;/strong>：bge-reranker-large 或 jina-reranker-v2&lt;/li>
&lt;li>&lt;strong>私有化部署&lt;/strong>：bge 系列&lt;/li>
&lt;/ul>
&lt;h3 id="rerank-的效果">Rerank 的效果
&lt;/h3>&lt;p>实测对比：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>配置&lt;/th>
&lt;th>Recall@5&lt;/th>
&lt;th>正确答案平均排名&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>向量检索&lt;/td>
&lt;td>72%&lt;/td>
&lt;td>4.2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>混合检索（无 Rerank）&lt;/td>
&lt;td>79%&lt;/td>
&lt;td>3.5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>混合 + Rerank&lt;/td>
&lt;td>88%&lt;/td>
&lt;td>1.8&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Rerank 后，正确答案的平均排名从 3.5 提升到 1.8——明显更靠前，更容易进入最终的 prompt。&lt;/p>
&lt;h2 id="五完整的检索流程">五、完整的检索流程
&lt;/h2>&lt;p>结合以上内容，一个完整的检索流程如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 用户 Query │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ &amp;#34;错误码 401 是什么意思&amp;#34; │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 阶段 1：候选召回（Recall） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 目标：不漏掉，召回足够多的候选 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ┌─────────────────┐ ┌─────────────────┐ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ 向量检索 │ │ BM25 检索 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ top-50 │ │ top-50 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ │ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ 擅长语义相似 │ │ 擅长精确匹配 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └────────┬────────┘ └────────┬────────┘ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └─────────┬──────────┘ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ▼ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ┌─────────────┐ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ RRF 融合 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ~80 候选 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └──────┬──────┘ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ┌──────▼──────┐ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ Metadata │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ 过滤 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ~60 候选 │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └──────┬──────┘ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────┼──────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 阶段 2：精排（Rerank） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 目标：从候选中选出最相关的 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 输入：~60 个候选 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 处理：Cross-Encoder 重新打分 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 输出：top-10 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 耗时：~150ms │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 阶段 3：上下文组装 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 目标：控制进入 prompt 的内容 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 输入：top-10 候选 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 处理： │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 1. 控制总长度（如 4000 tokens） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 2. 保持多样性（不同 source 的 chunk） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 3. 去重 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 输出：5-8 个 chunk │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 构建 Prompt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 调用 LLM
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 答案
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="各阶段的参数建议">各阶段的参数建议
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>阶段&lt;/th>
&lt;th>参数&lt;/th>
&lt;th>推荐值&lt;/th>
&lt;th>说明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>向量召回&lt;/td>
&lt;td>top_k&lt;/td>
&lt;td>50-100&lt;/td>
&lt;td>宁多勿少&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>BM25 召回&lt;/td>
&lt;td>top_k&lt;/td>
&lt;td>50-100&lt;/td>
&lt;td>宁多勿少&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>RRF&lt;/td>
&lt;td>k&lt;/td>
&lt;td>60&lt;/td>
&lt;td>经验值，一般不用调&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Rerank&lt;/td>
&lt;td>输入&lt;/td>
&lt;td>20-30&lt;/td>
&lt;td>不用太大，计算慢&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Rerank&lt;/td>
&lt;td>输出&lt;/td>
&lt;td>10-15&lt;/td>
&lt;td>给 prompt 组装留空间&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Prompt 组装&lt;/td>
&lt;td>最终数量&lt;/td>
&lt;td>3-8&lt;/td>
&lt;td>不宜过多&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Prompt 组装&lt;/td>
&lt;td>token 预算&lt;/td>
&lt;td>3000-4000&lt;/td>
&lt;td>根据模型调整&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="各阶段的延迟占比">各阶段的延迟占比
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">总延迟：~300-500ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">向量检索：30-50ms（10%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">BM25 检索：10-20ms（5%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RRF 融合：&amp;lt;5ms（&amp;lt;1%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Rerank：150-200ms（50%）← 主要瓶颈
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Prompt 组装：&amp;lt;10ms（&amp;lt;5%）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">LLM 调用：100-200ms（35%）← 另一个瓶颈
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>优化方向：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>减少 Rerank 候选数&lt;/strong>：从 30 减到 20，节省 ~50ms&lt;/li>
&lt;li>&lt;strong>用更快的 Rerank 模型&lt;/strong>：bge-reranker-base 比 large 快 ~80ms&lt;/li>
&lt;li>&lt;strong>缓存热门 query&lt;/strong>：相同问题直接返回，跳过整个流程&lt;/li>
&lt;/ol>
&lt;h2 id="六query-rewrite高级优化">六、Query Rewrite：高级优化
&lt;/h2>&lt;p>检索质量不仅取决于检索算法，还取决于 Query 本身。&lt;/p>
&lt;p>用户的问题往往不够清晰，需要&amp;quot;改写&amp;quot;才能更好地检索。&lt;/p>
&lt;h3 id="常见的改写策略">常见的改写策略
&lt;/h3>&lt;p>&lt;strong>1. 同义词扩展&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始：&amp;#34;怎么获取令牌&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">改写：&amp;#34;怎么获取令牌 OR token OR access_token&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. 拼写纠正&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始：&amp;#34;错误码 4O1&amp;#34;（字母 O）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">改写：&amp;#34;错误码 401&amp;#34;（数字 0）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>3. 核心词提取&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始：&amp;#34;我想了解一下关于 API 超时时间的配置方法&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">改写：&amp;#34;API 超时时间 配置&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>去掉无意义的词，保留核心检索词。&lt;/p>
&lt;p>&lt;strong>4. Query 分解&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始：&amp;#34;对比 v2.0 和 v2.1 版本的 API 差异&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">分解：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Query 1：&amp;#34;v2.0 版本 API 特性&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Query 2：&amp;#34;v2.1 版本 API 特性&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- Query 3：&amp;#34;v2.0 v2.1 版本差异&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>复杂问题拆成多个简单问题，分别检索，再合并。&lt;/p>
&lt;p>&lt;strong>5. 假设文档生成（HyDE）&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始：&amp;#34;API 的认证方式是什么&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">生成假设文档：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;API 的认证方式使用 Bearer Token。所有请求需要在 Header 中携带
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Authorization: Bearer &amp;lt;token&amp;gt;。Token 有效期 24 小时...&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用假设文档去检索，而不是原始 query。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>直觉：假设文档和真实文档的相似度，可能比 query 和文档的相似度更高。&lt;/p>
&lt;h3 id="query-rewrite-的权衡">Query Rewrite 的权衡
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>优点&lt;/th>
&lt;th>缺点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>提高检索质量&lt;/td>
&lt;td>增加 LLM 调用成本&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>处理复杂问题&lt;/td>
&lt;td>增加延迟&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>适应用户表达习惯&lt;/td>
&lt;td>可能改写错误&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>建议：&lt;/p>
&lt;ul>
&lt;li>简单问题不需要改写&lt;/li>
&lt;li>复杂问题、长尾问题适合改写&lt;/li>
&lt;li>可以用规则+LLM结合，降低成本&lt;/li>
&lt;/ul>
&lt;h2 id="七一个推荐的升级路线">七、一个推荐的升级路线
&lt;/h2>&lt;p>如果你现在还是单路向量检索，建议按这个顺序升级：&lt;/p>
&lt;h3 id="第一步优化-chunking成本低效果好">第一步：优化 Chunking（成本低，效果好）
&lt;/h3>&lt;ul>
&lt;li>从固定长度改为按段落/标题切分&lt;/li>
&lt;li>给每个 chunk 补充父级标题上下文&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>预期效果&lt;/strong>：Recall@5 从 60% 提升到 75%&lt;/p>
&lt;h3 id="第二步引入-bm25成本中">第二步：引入 BM25（成本中）
&lt;/h3>&lt;ul>
&lt;li>部署 BM25 检索&lt;/li>
&lt;li>实现 RRF 融合&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>预期效果&lt;/strong>：Recall@5 从 75% 提升到 82%&lt;/p>
&lt;h3 id="第三步接入-rerank成本中">第三步：接入 Rerank（成本中）
&lt;/h3>&lt;ul>
&lt;li>部署 Cross-Encoder 模型&lt;/li>
&lt;li>调整召回数量和精排数量&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>预期效果&lt;/strong>：Recall@5 从 82% 提升到 88%&lt;/p>
&lt;h3 id="第四步高级优化成本高">第四步：高级优化（成本高）
&lt;/h3>&lt;ul>
&lt;li>Query Rewrite&lt;/li>
&lt;li>Query Decomposition&lt;/li>
&lt;li>HyDE&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>预期效果&lt;/strong>：Recall@5 从 88% 提升到 92%+&lt;/p>
&lt;h3 id="收益递减规律">收益递减规律
&lt;/h3>&lt;p>从 60% 到 80%：相对容易，基础优化即可
从 80% 到 90%：需要系统优化，混合检索+Rerank
从 90% 到 95%：难度大增，需要高级策略和大量调试&lt;/p>
&lt;p>&lt;strong>建议&lt;/strong>：先做到 85%，再考虑是否值得继续投入。&lt;/p>
&lt;h2 id="八本文小结">八、本文小结
&lt;/h2>&lt;p>RAG 做得好不好，很多时候不是模型不够强，而是：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Chunk 没切好&lt;/strong> — 语义不完整、缺上下文&lt;/li>
&lt;li>&lt;strong>候选召回太单一&lt;/strong> — 只用向量，对精确匹配不稳定&lt;/li>
&lt;li>&lt;strong>Rerank 没真正落地&lt;/strong> — 用&amp;quot;假 rerank&amp;quot;或根本没 rerank&lt;/li>
&lt;/ol>
&lt;p>核心要点：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Chunking&lt;/strong>：按语义结构切分 + 补充上下文&lt;/li>
&lt;li>&lt;strong>混合检索&lt;/strong>：向量（语义）+ BM25（精确）+ RRF 融合&lt;/li>
&lt;li>&lt;strong>Rerank&lt;/strong>：Cross-Encoder 做真正的精排&lt;/li>
&lt;li>&lt;strong>Query Rewrite&lt;/strong>：处理复杂和长尾问题&lt;/li>
&lt;/ul>
&lt;p>下一篇会讲：如何做 RAG 的评测和 Inspect，才能知道问题到底出在哪一层。&lt;/p></description></item><item><title>RAG入门：从问题定义到系统设计</title><link>https://www.zata.cc/p/rag%E5%85%A5%E9%97%A8%E4%BB%8E%E9%97%AE%E9%A2%98%E5%AE%9A%E4%B9%89%E5%88%B0%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/</link><pubDate>Wed, 25 Mar 2026 15:40:00 +0800</pubDate><guid>https://www.zata.cc/p/rag%E5%85%A5%E9%97%A8%E4%BB%8E%E9%97%AE%E9%A2%98%E5%AE%9A%E4%B9%89%E5%88%B0%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/</guid><description>&lt;img src="https://www.zata.cc/p/rag%E5%85%A5%E9%97%A8%E4%BB%8E%E9%97%AE%E9%A2%98%E5%AE%9A%E4%B9%89%E5%88%B0%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/images/index/index.png" alt="Featured image of post RAG入门：从问题定义到系统设计" />&lt;p>RAG，全称 Retrieval-Augmented Generation，核心思想其实很朴素：不要把所有知识都塞进模型参数里，而是在回答问题前，先从外部知识库里把最相关的信息找出来，再交给模型生成答案。&lt;/p>
&lt;p>这套方法之所以重要，是因为纯大模型回答经常会遇到三类问题：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>知识过期&lt;/strong> — GPT-4 的训练数据截止到 2023 年底，你问它 2024 年 3 月的新闻，它要么说不知道，要么编一个。&lt;/li>
&lt;li>&lt;strong>专有知识缺失&lt;/strong> — 你们公司的内部文档、API 规范、业务规则，模型从来没见过。&lt;/li>
&lt;li>&lt;strong>幻觉问题&lt;/strong> — 模型会&amp;quot;自信地胡说八道&amp;quot;，尤其是当它不确定的时候。&lt;/li>
&lt;/ol>
&lt;p>RAG 的目标不是让模型&amp;quot;更聪明&amp;quot;，而是让系统&amp;quot;更可控&amp;quot;。你把知识更新、答案依据、召回范围、调试手段都从模型参数里解耦了出来。&lt;/p>
&lt;h2 id="一rag-解决的本质问题">一、RAG 解决的本质问题
&lt;/h2>&lt;p>先想清楚一个问题：&lt;strong>为什么不让模型直接回答，而要先检索？&lt;/strong>&lt;/p>
&lt;p>答案是：&lt;strong>模型的参数空间是有限的，但知识是无限的。&lt;/strong>&lt;/p>
&lt;p>GPT-4 有 1.8 万亿参数，看起来很多，但这些参数要编码：语言规律、世界知识、推理能力、常识……真正留给&amp;quot;事实知识&amp;quot;的空间并不多。而且参数一旦训练完成，就固定了。你想让它知道你们公司最新的报销流程？只能重新训练，成本几十万起步。&lt;/p>
&lt;p>RAG 的思路是：&lt;strong>把&amp;quot;事实知识&amp;quot;从参数里剥离出来，放到外部存储里。&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">传统模型：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">知识 → 训练 → 参数 → 推理 → 答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">（知识固化在参数里，更新成本高）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RAG：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">知识 → 索引 → 向量库 → 检索 → 推理 → 答案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">（知识和模型解耦，更新成本低）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>代价是：每次回答前，需要先检索。检索的质量直接决定了答案的质量。&lt;/p>
&lt;h2 id="二embedding把文本变成向量">二、Embedding：把文本变成向量
&lt;/h2>&lt;p>RAG 的第一步是让机器&amp;quot;理解&amp;quot;文本。方法是 Embedding——把文本映射到一个高维向量空间。&lt;/p>
&lt;h3 id="embedding-的直觉">Embedding 的直觉
&lt;/h3>&lt;p>假设我们有一个 3 维空间，每个词可以表示为一个点：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">&amp;#34;猫&amp;#34; → (0.2, 0.8, 0.1)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;狗&amp;#34; → (0.3, 0.7, 0.2) ← 和&amp;#34;猫&amp;#34;很近，都是宠物
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;汽车&amp;#34; → (0.9, 0.1, 0.3) ← 和&amp;#34;猫&amp;#34;很远，不同类别
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在这个空间里，语义相似的词距离近，语义不同的词距离远。&lt;/p>
&lt;p>实际的 Embedding 维度是几百到几千维，但原理一样：&lt;strong>让语义相似的文本在向量空间里距离近。&lt;/strong>&lt;/p>
&lt;h3 id="训练-embedding-模型">训练 Embedding 模型
&lt;/h3>&lt;p>Embedding 模型是怎么训练出来的？核心思想是：&lt;strong>让相似文本的向量靠近，不相似文本的向量远离。&lt;/strong>&lt;/p>
&lt;p>常用的训练方式有两种：&lt;/p>
&lt;p>&lt;strong>1. 对比学习（Contrastive Learning）&lt;/strong>&lt;/p>
&lt;p>准备大量&amp;quot;相似对&amp;quot;和&amp;quot;不相似对&amp;quot;：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">相似对：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">(&amp;#34;如何重置密码&amp;#34;, &amp;#34;密码重置方法&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">(&amp;#34;API 超时设置&amp;#34;, &amp;#34;配置 API 超时时间&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">不相似对：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">(&amp;#34;如何重置密码&amp;#34;, &amp;#34;API 超时设置&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">(&amp;#34;密码重置方法&amp;#34;, &amp;#34;今天天气怎么样&amp;#34;)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>训练目标：让相似对的向量距离小，不相似对的向量距离大。&lt;/p>
&lt;p>损失函数（InfoNCE Loss）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">L = -log( exp(sim(q, p+)/τ) / Σexp(sim(q, pi)/τ) )
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">其中：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- q 是 query 的向量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- p+ 是正样本的向量
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- pi 是所有样本（包括正样本和负样本）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- sim 是相似度函数（如余弦相似度）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- τ 是温度参数
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>直觉解释：让正样本的相似度占主导，负样本的相似度被压制。&lt;/p>
&lt;p>&lt;strong>2. 自监督学习&lt;/strong>&lt;/p>
&lt;p>不用人工标注，利用文本本身的结构：&lt;/p>
&lt;ul>
&lt;li>同一个句子/段落的不同部分互为正样本&lt;/li>
&lt;li>不同句子/段落互为负样本&lt;/li>
&lt;/ul>
&lt;p>代表性方法：SimCSE，把同一个句子丢进模型两次（不同的 dropout mask），得到的两个向量应该相似。&lt;/p>
&lt;h3 id="主流-embedding-模型">主流 Embedding 模型
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模型&lt;/th>
&lt;th>维度&lt;/th>
&lt;th>特点&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>text-embedding-3-small&lt;/td>
&lt;td>1536&lt;/td>
&lt;td>OpenAI，多语言&lt;/td>
&lt;td>通用场景&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>text-embedding-3-large&lt;/td>
&lt;td>3072&lt;/td>
&lt;td>OpenAI，更高精度&lt;/td>
&lt;td>高质量要求&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bge-large-zh&lt;/td>
&lt;td>1024&lt;/td>
&lt;td>开源，中文优化&lt;/td>
&lt;td>中文场景&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bge-m3&lt;/td>
&lt;td>1024&lt;/td>
&lt;td>开源，多语言&lt;/td>
&lt;td>多语言混合&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>e5-large-v2&lt;/td>
&lt;td>1024&lt;/td>
&lt;td>开源，需要加前缀&lt;/td>
&lt;td>英文场景&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>选择原则：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>中文为主&lt;/strong>：选 bge-large-zh&lt;/li>
&lt;li>&lt;strong>多语言混合&lt;/strong>：选 text-embedding-3-small 或 bge-m3&lt;/li>
&lt;li>&lt;strong>追求高质量且有预算&lt;/strong>：选 text-embedding-3-large&lt;/li>
&lt;li>&lt;strong>私有化部署&lt;/strong>：选 bge 系列&lt;/li>
&lt;/ul>
&lt;h2 id="三向量检索在高维空间找邻居">三、向量检索：在高维空间找邻居
&lt;/h2>&lt;p>有了向量，接下来是检索：给定一个 query 向量，找到最相似的文档向量。&lt;/p>
&lt;h3 id="相似度计算">相似度计算
&lt;/h3>&lt;p>最常用的是&lt;strong>余弦相似度&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">cosine(a, b) = (a · b) / (||a|| × ||b||)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">其中：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- a · b 是向量点积
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- ||a|| 是向量的模长
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结果范围：[-1, 1]，越大越相似
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>为什么用余弦相似度而不是欧氏距离？&lt;/p>
&lt;p>因为 Embedding 的方向比长度更重要。两个文本的语义相似，体现在向量方向相近，而不是长度相近。余弦相似度只看方向，不看长度。&lt;/p>
&lt;h3 id="暴力检索的问题">暴力检索的问题
&lt;/h3>&lt;p>最简单的检索方式是暴力计算：把 query 和所有文档向量都算一遍相似度，排序取 top-k。&lt;/p>
&lt;p>问题：慢。&lt;/p>
&lt;p>假设向量维度 1024，文档数量 100 万：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">单次检索计算量：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">100万 × 1024 = 10亿次浮点运算
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">耗时估算：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">单核 CPU ≈ 100-500ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">GPU ≈ 10-50ms
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>100 万文档还算小，到了 1000 万、1 亿，暴力检索就撑不住了。&lt;/p>
&lt;h3 id="近似最近邻搜索ann">近似最近邻搜索（ANN）
&lt;/h3>&lt;p>解决方案：&lt;strong>用精度换速度&lt;/strong>。不要求找到&amp;quot;最近的&amp;quot;，只要找到&amp;quot;足够近的&amp;quot;。&lt;/p>
&lt;p>主流算法：&lt;/p>
&lt;p>&lt;strong>1. HNSW（Hierarchical Navigable Small World）&lt;/strong>&lt;/p>
&lt;p>思路：构建一个多层的图结构，每层是一个小世界网络。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">第 0 层：所有节点
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 1 层：部分节点（概率选取）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">第 2 层：更少的节点
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">搜索时：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">从最高层开始，快速跳到目标区域附近
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">逐层下降，越来越精确
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">最后在第 0 层找到最近邻
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>类比：找北京的某个人。先在世界地图上定位到中国，再在中国地图上定位到北京，再在北京地图上定位到朝阳区……每一步都在缩小范围。&lt;/p>
&lt;p>&lt;strong>2. IVF（Inverted File Index）&lt;/strong>&lt;/p>
&lt;p>思路：把向量空间划分为多个区域（聚类中心），每个区域维护一个倒排表。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">离线阶段：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 用 K-means 聚类，找到 K 个中心点
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 把每个向量分配到最近的中心点
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 每个中心点维护一个列表（倒排表）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">在线检索：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 找到离 query 最近的几个中心点
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 只在这几个中心点的倒排表里搜索
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 不用遍历所有向量
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>参数选择：nprobe（探测几个中心点）。nprobe 越大，精度越高，速度越慢。&lt;/p>
&lt;p>&lt;strong>3. PQ（Product Quantization）&lt;/strong>&lt;/p>
&lt;p>思路：压缩向量，减少内存占用和计算量。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始向量：1024 维浮点数 = 4096 字节
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">压缩方法：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 把 1024 维分成 8 组，每组 128 维
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 每组用 K-means 聚类，生成 256 个中心点
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 每个向量每组只需 1 字节（存储中心点编号）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">压缩后：8 字节
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">压缩比：512 倍
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>代价：精度损失。但换来的是内存占用大幅降低，可以索引更多文档。&lt;/p>
&lt;h3 id="向量库的选择">向量库的选择
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>向量库&lt;/th>
&lt;th>算法&lt;/th>
&lt;th>特点&lt;/th>
&lt;th>适用场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Chroma&lt;/td>
&lt;td>HNSW&lt;/td>
&lt;td>轻量，易上手&lt;/td>
&lt;td>开发/小规模&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Qdrant&lt;/td>
&lt;td>HNSW&lt;/td>
&lt;td>开源，功能全&lt;/td>
&lt;td>中等规模生产&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Milvus&lt;/td>
&lt;td>多种&lt;/td>
&lt;td>分布式，高性能&lt;/td>
&lt;td>大规模生产&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Pinecone&lt;/td>
&lt;td>专有&lt;/td>
&lt;td>全托管，免运维&lt;/td>
&lt;td>不想运维&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Weaviate&lt;/td>
&lt;td>HNSW&lt;/td>
&lt;td>原生支持多模态&lt;/td>
&lt;td>多模态场景&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="四为什么单靠向量检索不够">四、为什么单靠向量检索不够
&lt;/h2>&lt;p>向量检索很强大，但有天生的局限。&lt;/p>
&lt;h3 id="局限-1对精确匹配不敏感">局限 1：对精确匹配不敏感
&lt;/h3>&lt;p>例子：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">文档：&amp;#34;错误码 401 表示认证失败&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户问：&amp;#34;401 是什么意思&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">向量检索可能召回：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;常见错误码及解决方案&amp;#34;（语义相似）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;权限问题排查&amp;#34;（语义相似）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">而不是精确包含 &amp;#34;401&amp;#34; 的那段。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>原因：Embedding 模型学习的是语义相似性，不是字面匹配。&amp;ldquo;401&amp;rdquo; 这个数字在向量空间里没有特殊意义，它只是一个 token。&lt;/p>
&lt;h3 id="局限-2对专业术语不稳定">局限 2：对专业术语不稳定
&lt;/h3>&lt;p>例子：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">文档：&amp;#34;JSON Web Token 的有效期默认为 1 小时&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户问：&amp;#34;JWT 的有效期&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">向量检索：可能召回，也可能不召回，取决于模型是否学过 JWT = JSON Web Token
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果模型训练数据里没见过这个缩写，就找不到关联。&lt;/p>
&lt;h3 id="局限-3对编号版本号不稳定">局限 3：对编号/版本号不稳定
&lt;/h3>&lt;p>例子：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">文档：&amp;#34;v2.3.1 版本新增了批量导出功能&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">用户问：&amp;#34;v2.3.0 有什么新功能&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">向量检索：可能召回 v2.3.1 或 v2.3.2 的内容，因为&amp;#34;版本更新&amp;#34;语义相似
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>版本号之间的微小差异，在向量空间里可能被&amp;quot;版本&amp;quot;这个大概念淹没。&lt;/p>
&lt;h3 id="解决方案混合检索">解决方案：混合检索
&lt;/h3>&lt;p>这就是为什么生产环境几乎都用 &lt;strong>Hybrid Retrieval&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">候选集 = 向量检索（语义） + 关键词检索（字面） + 元数据过滤（业务规则）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>下一篇文章会详细讲混合检索和 Rerank 的算法。&lt;/p>
&lt;h2 id="五rag-的三阶段架构">五、RAG 的三阶段架构
&lt;/h2>&lt;p>理解了 Embedding 和检索，我们来看 RAG 的整体架构。一个成熟的 RAG 系统分为三个阶段：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 阶段 1：索引（Indexing） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 文档 → 解析 → 切分 → Embedding → 写入向量库 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 核心问题：怎么切分才能让每个 chunk 成为独立的证据？ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 阶段 2：检索（Retrieval） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Query → Embedding → 向量检索 → 关键词检索 → 融合 → Rerank │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 核心问题：怎么召回相关内容，同时减少噪声？ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└────────────────────────┬────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 阶段 3：生成（Generation） │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ Query + Chunks → Prompt 组装 → LLM → 答案 + 引用 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 核心问题：怎么让模型严格依据证据回答，不自由发挥？ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└─────────────────────────────────────────────────────────────────┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>每个阶段都有特定的优化空间，而且&lt;strong>问题往往出现在你忽视的地方&lt;/strong>。&lt;/p>
&lt;h3 id="索引阶段的关键决策">索引阶段的关键决策
&lt;/h3>&lt;p>&lt;strong>1. 切分粒度&lt;/strong>&lt;/p>
&lt;p>太大：噪声多，模型注意力分散
太小：信息碎片化，上下文丢失&lt;/p>
&lt;p>经验值：300-500 tokens（中文约 200-350 字）&lt;/p>
&lt;p>但比长度更重要的是&lt;strong>语义完整性&lt;/strong>。一个 chunk 应该能独立成为一个&amp;quot;证据&amp;quot;。&lt;/p>
&lt;p>&lt;strong>2. 上下文补充&lt;/strong>&lt;/p>
&lt;p>一个常见的坑：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">原始文档：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">### 2.3 校准流程
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">将旋钮调至 3 档，等待指示灯变为绿色。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">按段落切分后，chunk 变成：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;将旋钮调至 3 档，等待指示灯变为绿色。&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题：用户问&amp;#34;ZK-200 怎么校准&amp;#34;，这个 chunk 不会召回，因为：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 没有&amp;#34;ZK-200&amp;#34;（在文档标题里）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 没有&amp;#34;校准&amp;#34;（在章节标题里）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>解决方案：把父级标题拼到 chunk 前面。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">补充上下文后：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;【ZK-200 操作手册 &amp;gt; 2.3 校准流程】
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">将旋钮调至 3 档，等待指示灯变为绿色。&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这个技巧叫 &lt;strong>Contextual Chunking&lt;/strong>，成本低，效果好。&lt;/p>
&lt;p>&lt;strong>3. 元数据设计&lt;/strong>&lt;/p>
&lt;p>每个 chunk 至少要存储：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;id&amp;#34;: &amp;#34;唯一标识&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;content&amp;#34;: &amp;#34;文本内容&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;document_id&amp;#34;: &amp;#34;所属文档&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;source&amp;#34;: &amp;#34;知识库来源&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;title&amp;#34;: &amp;#34;文档标题&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;section&amp;#34;: &amp;#34;章节路径&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;chunk_index&amp;#34;: &amp;#34;在文档中的位置&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;created_at&amp;#34;: &amp;#34;创建时间&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这些元数据在检索时可以做过滤（只搜特定来源）、在回答时可以做引用（答案来自哪个文档）。&lt;/p>
&lt;h3 id="检索阶段的关键决策">检索阶段的关键决策
&lt;/h3>&lt;p>&lt;strong>1. 召回数量&lt;/strong>&lt;/p>
&lt;p>召回太少：容易漏掉正确答案
召回太多：噪声多，成本高&lt;/p>
&lt;p>经验值：&lt;/p>
&lt;ul>
&lt;li>召回阶段：50-100 个候选&lt;/li>
&lt;li>Rerank 后：保留 10-20 个&lt;/li>
&lt;li>最终进 prompt：3-8 个&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. 检索策略&lt;/strong>&lt;/p>
&lt;p>简单场景：纯向量检索够用
复杂场景：向量 + BM25 混合
高精度场景：混合 + Rerank&lt;/p>
&lt;p>&lt;strong>3. 过滤策略&lt;/strong>&lt;/p>
&lt;p>利用元数据缩小检索范围：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">用户问：&amp;#34;销售合同模板在哪下载？&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">不过滤：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">搜索范围 = 所有文档（产品、研发、销售、HR...）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结果可能混入研发部门的合同管理规范
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">按 department=&amp;#34;sales&amp;#34; 过滤：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">搜索范围 = 销售部门文档
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">结果更精准
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="生成阶段的关键决策">生成阶段的关键决策
&lt;/h3>&lt;p>&lt;strong>1. Prompt 设计&lt;/strong>&lt;/p>
&lt;p>核心原则：&lt;strong>让模型&amp;quot;不得不&amp;quot;依据证据回答。&lt;/strong>&lt;/p>
&lt;p>差的 Prompt：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">参考资料：{chunks}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题：{query}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">请回答：
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>模型可能无视参考资料，自由发挥。&lt;/p>
&lt;p>好的 Prompt：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">你是一个文档助手。请根据以下参考资料回答问题。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">要求：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1. 答案必须基于参考资料，不要编造
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2. 如果参考资料中没有答案，请直接说&amp;#34;根据现有资料无法回答&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">3. 回答时标注引用来源，格式：[来源: 文档名 &amp;gt; 章节]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">参考资料：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{chunks}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">问题：{query}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">请回答：
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. 上下文预算&lt;/strong>&lt;/p>
&lt;p>模型有上下文长度限制，不能无限塞内容。更重要的是：&lt;strong>内容越多，模型注意力越分散。&lt;/strong>&lt;/p>
&lt;p>经验值：检索内容不超过 4000 tokens（约 3000 字中文）&lt;/p>
&lt;p>分配建议：&lt;/p>
&lt;ul>
&lt;li>关键证据：2000-3000 tokens&lt;/li>
&lt;li>Prompt 模板：200-300 tokens&lt;/li>
&lt;li>用户问题和输出：预留 1000+ tokens&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. 引用机制&lt;/strong>&lt;/p>
&lt;p>让模型标注答案的来源：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">答案：&amp;#34;API 的超时时间默认为 30 秒 [来源: API 规范 &amp;gt; 3.2 超时配置]&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>好处：&lt;/p>
&lt;ul>
&lt;li>用户可以验证答案&lt;/li>
&lt;li>系统可以追溯错误&lt;/li>
&lt;li>增加答案的可信度&lt;/li>
&lt;/ul>
&lt;h2 id="六rag-vs-微调怎么选">六、RAG vs 微调：怎么选
&lt;/h2>&lt;p>很多人问：应该用 RAG 还是微调？&lt;/p>
&lt;p>答案：&lt;strong>不冲突，解决的问题不同。&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题类型&lt;/th>
&lt;th>解决方案&lt;/th>
&lt;th>原因&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>知识过时&lt;/td>
&lt;td>RAG&lt;/td>
&lt;td>更新知识库即可&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>专有知识缺失&lt;/td>
&lt;td>RAG&lt;/td>
&lt;td>模型没见过这些知识&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>输出格式不稳定&lt;/td>
&lt;td>微调&lt;/td>
&lt;td>让模型学会特定格式&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>输出风格不对&lt;/td>
&lt;td>微调&lt;/td>
&lt;td>让模型掌握特定风格&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>工具使用不规范&lt;/td>
&lt;td>微调&lt;/td>
&lt;td>让模型学会调用模式&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>RAG 擅长：解决&amp;quot;知道什么&amp;quot;&lt;/strong>
&lt;strong>微调擅长：解决&amp;quot;怎么做&amp;quot;&lt;/strong>&lt;/p>
&lt;p>实际项目中，往往是两者结合：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">微调：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 让模型学会输出 JSON 格式
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 让模型学会引用来源
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 让模型学会说&amp;#34;不知道&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">RAG：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 提供最新的业务知识
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 提供可追溯的证据
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">- 提供领域专业信息
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="七第一版-rag-应该怎么搭">七、第一版 RAG 应该怎么搭
&lt;/h2>&lt;p>如果你从零开始，我的建议是：&lt;/p>
&lt;p>&lt;strong>不要一上来就追求复杂架构。第一版的目标是&amp;quot;可解释&amp;quot;，不是&amp;quot;最优&amp;quot;。&lt;/strong>&lt;/p>
&lt;h3 id="推荐的第一版配置">推荐的第一版配置
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模块&lt;/th>
&lt;th>配置&lt;/th>
&lt;th>原因&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>文档导入&lt;/td>
&lt;td>手动，按需导入&lt;/td>
&lt;td>先保证质量，再追求自动化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>切分策略&lt;/td>
&lt;td>按段落，500 字左右&lt;/td>
&lt;td>简单可控，效果有保障&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Embedding&lt;/td>
&lt;td>text-embedding-3-small 或 bge-large-zh&lt;/td>
&lt;td>成熟稳定，效果好&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>检索&lt;/td>
&lt;td>纯向量检索，top_k=5&lt;/td>
&lt;td>先跑通，再优化&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Prompt&lt;/td>
&lt;td>明确约束 + 引用要求&lt;/td>
&lt;td>确保答案有依据&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Inspect&lt;/td>
&lt;td>保留每次检索的候选列表&lt;/td>
&lt;td>方便定位问题&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="第一版容易犯的错误">第一版容易犯的错误
&lt;/h3>&lt;p>&lt;strong>错误 1：上来就全量导入&lt;/strong>&lt;/p>
&lt;p>把公司所有文档都丢进去，结果检索噪声巨大，答案质量很差。&lt;/p>
&lt;p>正确做法：先导入核心文档（100-200 篇），验证效果，再逐步扩展。&lt;/p>
&lt;p>&lt;strong>错误 2：忽视元数据&lt;/strong>&lt;/p>
&lt;p>只存内容和向量，其他什么都不留。后面想做过滤、引用、增量更新，发现数据不够。&lt;/p>
&lt;p>正确做法：一开始就设计好元数据结构，chunk 要保留来源、章节、时间等信息。&lt;/p>
&lt;p>&lt;strong>错误 3：不做评测&lt;/strong>&lt;/p>
&lt;p>优化全靠&amp;quot;感觉&amp;quot;，没有客观标准。&lt;/p>
&lt;p>正确做法：准备 20-50 个测试问题，固定评测，每次改动都要看指标变化。&lt;/p>
&lt;p>&lt;strong>错误 4：没有 Inspect 能力&lt;/strong>&lt;/p>
&lt;p>答案错了，不知道是检索错还是生成错。&lt;/p>
&lt;p>正确做法：保留每次请求的中间结果（候选列表、分数、prompt），方便排查。&lt;/p>
&lt;h2 id="八如何判断系统准备好了">八、如何判断系统准备好了
&lt;/h2>&lt;p>在上线前，问自己这些问题：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">□ 能回答核心问题吗？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── 准备 20 个关键问题，正确率 &amp;gt; 70%
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 能解释答案来源吗？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── 每个答案都有引用，用户能追溯
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 答案错了能定位吗？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── 有 Inspect 页面，能看到检索结果
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 知道下一步优化什么吗？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── 有评测指标，知道哪类问题表现差
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">□ 文档更新后能同步吗？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── 有增量更新机制，不是全量重建
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果这些问题都回答不了，说明系统还不成熟，需要继续打磨。&lt;/p>
&lt;h2 id="九下一篇文章讲什么">九、下一篇文章讲什么
&lt;/h2>&lt;p>这篇文章讲了 RAG 的基础：&lt;/p>
&lt;ul>
&lt;li>Embedding 的原理和选择&lt;/li>
&lt;li>向量检索的算法和局限&lt;/li>
&lt;li>三阶段架构的关键决策&lt;/li>
&lt;/ul>
&lt;p>下一篇会深入讲：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Chunking 的策略&lt;/strong>：怎么切才能保留语义完整性&lt;/li>
&lt;li>&lt;strong>混合检索&lt;/strong>：BM25 算法原理、RRF 融合公式&lt;/li>
&lt;li>&lt;strong>Rerank&lt;/strong>：Cross-Encoder 的工作原理、为什么比向量检索更准&lt;/li>
&lt;/ul>
&lt;p>这些是 RAG 质量提升的关键，也是最容易踩坑的地方。&lt;/p></description></item></channel></rss>