How to handle list item during chunking?**
P1 · rag
🏷 标签:rag, chunking, document-processing, information-retrieval
1️⃣ 考察意图
面试官想考察你对非连续文本(列表)的 chunking 策略设计能力,以及结构化信息保留与检索效果的权衡。这属于工程取舍 + 系统设计类型,刁钻点在于:列表天然是“多段但语义连续”的,简单按 token 或段落切分会破坏逻辑结构,导致检索时召回碎片化或答案不完整。答好了能展示你对 RAG 整条链路(解析→分块→检索→生成)的实战理解,以及面对复杂文档格式时的工程决策能力。
2️⃣ 标准答
处理列表 chunking 的核心矛盾是:保持语义完整性 vs. 控制 chunk 大小。以下分 5 步展开。
第一步:识别列表结构
- 使用启发式规则:检测行首的编号(1. / (1) / ①)、项目符号(- / * / •)、或缩进模式(如每行前 4 空格)。
- 对 PDF 用布局解析器(如
pdfplumber提取坐标 +Unstructured的partition_pdf),对 HTML 用BeautifulSoup解析<ul>/<ol>标签。 - 坑:OCR 文档中列表可能被误识别为普通段落,需结合字体变化(如加粗标题)或行间距阈值(列表项行距通常小于段落间距)。
第二步:选择 chunking 策略(三种主流方案)
- 策略 A:整体保留——将整个列表作为一个 chunk。适用于短列表(≤5 项),如“三个注意事项”。优点:语义完整,检索时直接命中。缺点:长列表(如 20 项条款)会超过 512 token 窗口,导致检索精度下降。
- 策略 B:按项拆分——每项独立 chunk,但保留上下文前缀(如列表标题 + 序号)。例如 chunk 内容为“【列表:安装步骤】步骤 1:下载 SDK”。优点:细粒度检索,适合长列表。缺点:丢失项间逻辑关系(如“步骤 1 和步骤 2 必须按顺序执行”)。
- 策略 C:混合策略——短列表(≤5 项)整体保留,长列表按项拆分并添加元数据。具体实现:设置阈值(如 3 项或 200 token),低于阈值走 A,高于走 B。这是实际项目中最常用的方案,平衡了召回率和 chunk 数量。
第三步:处理嵌套列表
- 递归拆分:检测到子列表时,将父项和子列表合并为一个 chunk(如“2. 配置环境\n - 安装 Python\n - 设置虚拟环境”)。
- 扁平化:将嵌套结构展开为平级项,用缩进或前缀标记层级(如“2.1 安装 Python”)。推荐用递归拆分,因为扁平化会丢失层级语义,导致检索时混淆“安装 Python”是配置环境的一部分还是独立步骤。
第四步:元数据标记
- 每个 chunk 必须记录:列表类型(ordered/unordered)、层级(level 1/2)、序号(如“2.1”)、父标题(如“安装步骤”)。这允许检索后通过元数据重组列表,或让 LLM 在生成时恢复结构。
- 实战坑:元数据本身会占用 token,需控制字段数量(建议 ≤5 个),否则 chunk 有效内容减少。例如只存
list_id和item_index,不存完整路径。
第五步:评估与调优
- 在 QA 任务上对比三种策略:用
Recall@k和Answer Completeness(人工评分 1-5)。经验数据【通用知识】:混合策略在技术文档上 Recall 比整体保留高 15%,比按项拆分高 8%,且 chunk 数量减少 30%。 - 调优点:阈值(3 项 vs. 5 项)需根据文档集统计分布调整。例如法律条款平均 8 项,阈值设为 5 会导致 60% 列表被拆分,需改为 10。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从三个层面回答:第一,识别列表结构,用启发式规则或布局解析器检测边界;第二,选择 chunking 策略,推荐混合策略——短列表整体保留,长列表按项拆分并加元数据;第三,处理嵌套列表时递归拆分,保留层级。总结一句:核心是平衡语义完整性和检索粒度,通过元数据标记让 LLM 能恢复结构。”
4️⃣ 高频追问 & 应对
追问 1:如果列表项本身很长(如每项 500 字),按项拆分后 chunk 还是太大怎么办?
对长项进一步拆分:先检测项内是否有子结构(如段落、子列表),用语义分割(如
spaCy的句子边界检测)或递归字符分割(RecursiveCharacterTextSplitter的chunk_size=256)。同时更新元数据:记录parent_item_id和sub_chunk_index,检索时通过parent_item_id聚合。注意:这会导致 chunk 数量暴增,需评估是否值得——如果长项占比 <10%,直接整体保留更省事。
追问 2:如何保证拆分后的列表项在检索时能正确排序?
元数据中存
item_index(整数),检索后按list_id分组、item_index排序。如果列表是乱序的(如用户手动打乱),需额外存original_order。生成阶段,将排序后的 chunk 内容拼接成列表字符串传给 LLM,并提示“以下内容按原始顺序排列”。坑:如果检索只命中部分项,拼接后可能缺失中间项,需在 prompt 中注明“仅展示检索到的项,序号可能不连续”。
追问 3:如果文档是扫描件,列表结构识别不准怎么办?
先用 OCR(如
Tesseract)提取文本和坐标,再用规则(如行首数字 + 缩进)或轻量模型(如LayoutLMv3微调)检测列表。如果准确率 <80%,退化为按段落拆分,不保留列表结构。因为错误的结构比无结构更糟糕——LLM 会基于错误序号生成幻觉。实战中,对低质量 PDF 优先用Unstructured的partition_pdf,它内置了列表检测逻辑。
5️⃣ 避坑 · 常见错误答法
- ❌ “直接按段落拆分,列表项自然会被分开。” → ✅ 列表项之间逻辑连续,按段落拆分会导致“步骤 1”和“步骤 2”被分到不同 chunk,检索时只召回步骤 1 而丢失步骤 2,答案不完整。
- ❌ “所有列表都按项拆分,这样最细粒度。” → ✅ 短列表(如 3 项)按项拆分后,每个 chunk 只有 10-20 token,检索时噪声大,且 LLM 需要拼接多个 chunk 才能理解完整语义,增加延迟和幻觉风险。
- ❌ “用 LLM 直接解析列表结构,准确率最高。” → ✅ LLM 解析成本高(每页 0.1-0.5 元),且对长文档有 token 限制。应该先用规则/布局解析器做 80% 的工作,LLM 只处理边缘 case(如复杂嵌套)。
6️⃣ 简历呼应
- 如果你有 RAG 项目:从“我在项目中对比了三种列表 chunking 策略,发现混合策略在召回率上提升 15%”切入,展示你做过 A/B 测试。
- 如果你只做过传统 NLP:用“列表 chunking 类似于序列标注中的 BIO 标签,需要识别边界并保留上下文”类比,体现迁移能力。
- 如果你是校招无项目:聚焦“我复现了 Unstructured 的列表检测逻辑,用规则实现了 90% 准确率”的 demo,展示动手能力。
- 《RAG 文档分块策略:从固定大小到语义分割》(博客,作者:LangChain 团队)
- 《LayoutLMv3: Pre-training for Document AI with Unified Text and Image Masking》(论文)
- 《Unstructured 库文档:Partitioning PDFs with Lists》(官方文档)
- 《Evaluating Chunking Strategies for Retrieval-Augmented Generation》(ArXiv 论文)
- 《RecursiveCharacterTextSplitter 源码解析》(GitHub,LangChain 仓库)