<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>技术选型 on 老朱的赛博工位</title><link>https://blog.zjkun.top/tags/%E6%8A%80%E6%9C%AF%E9%80%89%E5%9E%8B/</link><description>Recent content in 技术选型 on 老朱的赛博工位</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Tue, 20 Oct 2026 14:05:00 +0800</lastBuildDate><atom:link href="https://blog.zjkun.top/tags/%E6%8A%80%E6%9C%AF%E9%80%89%E5%9E%8B/index.xml" rel="self" type="application/rss+xml"/><item><title>RAG 父页面召回？这 3 种场景不值得做</title><link>https://blog.zjkun.top/posts/rag-parent-document-retrieval/</link><pubDate>Tue, 20 Oct 2026 14:05:00 +0800</pubDate><guid>https://blog.zjkun.top/posts/rag-parent-document-retrieval/</guid><description>父页面召回（Parent Document Retrieval）是最容易被盲抄的 RAG 功能。我研究了 2 天，结论：我不做。3 种不值得做的场景、2 种值得做的场景、3 秒自查法，以及我的真实数据（172 个小 chunk、混合检索+精排 top5 命中稳定）。功能不是看别人做了就抄，是看自己的数据形状。</description><content:encoded><![CDATA[<p>做 RAG 最容易被盲抄的一个功能是父页面召回（Parent Document Retrieval）。我研究了 2 天，结论：<strong>我不做，而且很多人一开始就做错了。</strong></p>
<p>30 秒拿走一份判断清单，下面是完整论证版。</p>
<h2 id="它是什么治什么病">它是什么，治什么病</h2>
<p>一句话：<strong>索引小块管查得准，返回父文档管上下文全。</strong></p>
<p>检索命中一个小 chunk 后，不直接把它喂给模型，而是顺着元数据找回它所属的大单元（父段落/整页/整文档），用大单元做生成上下文。</p>
<p>它治的病只有一个：<strong>分块把意义切断了</strong>——结论依赖前文铺垫，小块单独拿出来语义不成立。</p>
<p>副作用同样明确：prompt 塞进大量无关内容、模型注意力被稀释（回答变吵）、token 成本变高、时延变长。</p>
<p><strong>它是治「切断意义」的药，不是补脑药。</strong> 没这个病就别吃。</p>
<h2 id="3-种场景不值得做">3 种场景不值得做</h2>
<ol>
<li><strong>段落自包含</strong>：问答对、条款、产品参数这类文体，按分隔符切开后每块意义完整。小块已经够用，展开父页只是往 prompt 里灌水。</li>
<li><strong>语料不大且检索稳</strong>：混合检索+重排做完，top3/top5 一直命中得很稳，根本不需要回父页凑上下文——你的问题在「查得准」，不在「上下文全」。</li>
<li><strong>抽取型答案</strong>：只要从文档里抽一个字段/一条规定。返回整页反而给模型发挥空间，它开始在你不该有自由度的地方自行总结。</li>
</ol>
<h2 id="2-种场景值得做">2 种场景值得做</h2>
<ol>
<li><strong>长文档、结论依赖上下文才成立</strong>：法律意见书、实验报告，「综上所述」的「上述」就是病。</li>
<li><strong>怎么切都装不下一个答案</strong>：切小块检索不准、切大块上下文还是不够——说明你缺的不是查得准，是上下文完整。这时父页面召回才是正解。</li>
</ol>
<h2 id="我的数据形状为什么落在不做区">我的数据形状：为什么落在「不做」区</h2>
<p>语料是部门制度类文档，txt/word/pdf/xlsx 上传解析成纯文本后走我的递归切分器（<code>chunker.ts</code>）：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-ts" data-lang="ts"><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">DEFAULT_TARGET_CHARS</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">800</span>   <span style="color:#75715e">// 目标字符数 ≈ 上限值
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// 短文档：直接一片（核心保护，避免过切）
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">cleaned</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">&lt;=</span> <span style="color:#a6e22e">targetChars</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> [{ <span style="color:#a6e22e">content</span>: <span style="color:#66d9ef">cleaned</span>, <span style="color:#a6e22e">chunk_order</span>: <span style="color:#66d9ef">1</span>, <span style="color:#a6e22e">page_no</span>: <span style="color:#66d9ef">pageNo</span> }]
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 超长才逐层下降粒度：标题 → 空行段落 → 句号断句 → 固定兜底
</span></span></span></code></pre></div><p>制度文档的特点：条款天然自包含，一条「婚假申请流程」就是一个完整语义单元，800 字符目标 + 贪心合并（每片尽量落在 [400, 800] 区间）切出来的就是<strong>本来就自包含的小块</strong>。全库 <strong>172 个 chunk</strong>，混合检索（BM25+向量 RRF 融合）+ 精排取前 5 之后，命中一直挺稳——正好命中上面「不值得做」的前两种。</p>
<p>还有一个隐性成本：<strong>父页面召回需要 chunk→parent 的元数据链路</strong>（parent_id/页文档正文回查）。我的 chunk 有 <code>page_no</code> 和全文档连续 <code>chunk_order</code>，页级回查技术上做得动，但文档级展开等于把「检索」降级成「整本塞」——为我这 172 个块的语料引入这层结构和运行期回查，收益负期望。</p>
<p>所以父页面召回对我是<strong>锦上添花，不是药</strong>。功能不是看别人做了就抄，是看自己的数据形状。</p>
<h2 id="3-秒自查法建议抄走">3 秒自查法（建议抄走）</h2>
<p>随机抽库里 5 个段落，只问一句：</p>
<blockquote>
<p><strong>「只留这一段，答案还成立吗？」</strong></p>
</blockquote>
<ul>
<li>多数成立 → 不用做父页面，钱花在检索精排上更值</li>
<li>多数不成立 → 再动手，而且先试便宜的「取相邻片段」（命中 chunk 前后各带 1 条），还解决不了才上父文档级展开</li>
</ul>
<h2 id="速查表">速查表</h2>
<table>
	<thead>
			<tr>
					<th>判断</th>
					<th>动作</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>条款/FAQ/参数，块块自包含</td>
					<td>不做，省成本</td>
			</tr>
			<tr>
					<td>top5 命中稳定</td>
					<td>不做，问题不在这</td>
			</tr>
			<tr>
					<td>只要抽字段</td>
					<td>不做，整页反而引入发挥空间</td>
			</tr>
			<tr>
					<td>长文结论依赖铺垫</td>
					<td>值得做</td>
			</tr>
			<tr>
					<td>怎么切都不装不下答案</td>
					<td>值得做（先试相邻片段）</td>
			</tr>
	</tbody>
</table>
<p>我的清单里后续真要排的是 eval 验证集和生成侧引用校验——先有尺子再谈优化，这是下一个话题。</p>
<blockquote>
<p>本篇最早于 2026 年 10 月 20 日发布于小红书，此为博客完整版。</p>
</blockquote>
]]></content:encoded></item></channel></rss>