{"schema_version":1,"id":"article:financial-rag-dual-pipeline","kind":"article","slug":"financial-rag-dual-pipeline","title":"一个金融研报 RAG 应用：「离线解析」和「在线问答」双链路详解","author":"晨旭","url":"https://chenxu.xin/writing/financial-rag-dual-pipeline","date":"2025-12-05","updated":"2025-12-05","description":"复盘一套真实的金融 RAG 项目：离线链路怎么把多栏排版、扫描件和跨页表格解析成干净的知识，在线链路怎么通过 Query 优化、混合检索和重排把答案找准。","position":null,"group":null,"series":"AI技术理解","tags":["rag","hands-on"],"publication_status":"public","maturity":"evergreen","body_sha256":"1a38ba7eec264c4ce23dc3bf79193d3cae145464fa5b281fc084dbc0ad1edbd8","paragraph_rule":"src/lib/paragraphs.mjs@1","paragraphs":[{"id":"p1","kind":"paragraph","text":"在 AI 产品的落地中，RAG 是知识库的标配，且是 Agent 应用中的核心组件。尤其是在金融、保险等专业领域，多栏排版、扫描件模糊、跨页表格，以及用户模糊的提问意图，这些非结构化数据带来的挑战，是每一个 AI 产品经理和技术团队必须攻克的深水区。","raw":"在 AI 产品的落地中，RAG 是知识库的标配，且是 Agent 应用中的核心组件。尤其是在金融、保险等专业领域，多栏排版、扫描件模糊、跨页表格，以及用户模糊的提问意图，这些非结构化数据带来的挑战，是每一个 AI 产品经理和技术团队必须攻克的深水区。"},{"id":"p2","kind":"paragraph","text":"这篇文章复盘自一套真实的金融 RAG 实战项目。跳出代码细节，从「离线解析」与「在线问答」这两条核心链路出发，拆解构建 RAG 系统的底层逻辑。","raw":"这篇文章复盘自一套真实的金融 RAG 实战项目。跳出代码细节，从「离线解析」与「在线问答」这两条核心链路出发，拆解构建 RAG 系统的底层逻辑。"},{"id":"p3","kind":"paragraph","text":"对于 AI 产品经理而言，拥有系统性的优化思维至关重要：知道了数据在管道中是如何流动的，才能在产品出现 Bad Case 时，精准定位是解析出了问题，还是检索走了神。","raw":"对于 AI 产品经理而言，拥有系统性的优化思维至关重要：知道了数据在管道中是如何流动的，才能在产品出现 Bad Case 时，精准定位是解析出了问题，还是检索走了神。"},{"id":"p4","kind":"heading","text":"全链路架构","raw":"## 全链路架构"},{"id":"p5","kind":"paragraph","text":"做一个 RAG 产品，首先要建立上帝视角，不能只停留在前端的对话框，还要看透后端的「双流」架构。RAG 系统本质上由两条异步的流水线组成。","raw":"做一个 RAG 产品，首先要建立上帝视角，不能只停留在前端的对话框，还要看透后端的「双流」架构。RAG 系统本质上由两条异步的流水线组成。"},{"id":"p6","kind":"paragraph","text":"离线处理流程（数据入库），这是系统的消化系统：","raw":"**离线处理流程（数据入库）**，这是系统的消化系统："},{"id":"p7","kind":"list","text":"- 提取：从 PDF、PPT、TXT 等异构数据源中提取内容。\n- 向量化：通过 Embedding 模型将文本转化为向量。\n- 存储：将文本和向量存入向量数据库（如 Milvus / ElasticSearch）和关系型数据库（如 PostgreSQL）。","raw":"- **提取**：从 PDF、PPT、TXT 等异构数据源中提取内容。\n- **向量化**：通过 Embedding 模型将文本转化为向量。\n- **存储**：将文本和向量存入向量数据库（如 Milvus / ElasticSearch）和关系型数据库（如 PostgreSQL）。"},{"id":"p8","kind":"paragraph","text":"在线查询流程（实时问答），这是系统的大脑：","raw":"**在线查询流程（实时问答）**，这是系统的大脑："},{"id":"p9","kind":"list","text":"- 查询处理：对用户 Query 进行编码、重写和意图识别。\n- 检索：通过语义检索和关键词检索获取相关片段。\n- 生成：LLM 基于增强的上下文生成最终回答。","raw":"- **查询处理**：对用户 Query 进行编码、重写和意图识别。\n- **检索**：通过语义检索和关键词检索获取相关片段。\n- **生成**：LLM 基于增强的上下文生成最终回答。"},{"id":"p10","kind":"paragraph","text":"离线阶段是提前做好知识库的解析；当用户来问问题的时候，进入第二阶段的在线检索。通过这两步操作，最终将用户的问题扩充为「检索回来的精确文本块 + 用户的原始问题」，再一起送给 LLM 作为 user prompt。","raw":"离线阶段是提前做好知识库的解析；当用户来问问题的时候，进入第二阶段的在线检索。通过这两步操作，最终将用户的问题扩充为「检索回来的精确文本块 + 用户的原始问题」，再一起送给 LLM 作为 user prompt。"},{"id":"p11","kind":"heading","text":"离线解析：精细化治理","raw":"## 离线解析：精细化治理"},{"id":"p12","kind":"paragraph","text":"RAG 领域的名言 Garbage In, Garbage Out，在金融研报这种专业领域体现得淋漓尽致，解析质量直接决定了系统的上限。可以从解析、分块、层级结构这三个维度进行优化。","raw":"RAG 领域的名言 Garbage In, Garbage Out，在金融研报这种专业领域体现得淋漓尽致，解析质量直接决定了系统的上限。可以从解析、分块、层级结构这三个维度进行优化。"},{"id":"p13","kind":"heading","text":"1、深度解析：从「看到」到「看懂」","raw":"### 1、深度解析：从「看到」到「看懂」"},{"id":"p14","kind":"paragraph","text":"在金融 RAG 中，PDF 解析不能是单纯的文字提取，需要对文档结构进行逆向工程，集成 OCR、深度学习布局识别和机器学习文本合并的复杂流水线。","raw":"在金融 RAG 中，PDF 解析不能是单纯的文字提取，需要对文档结构进行逆向工程，集成 OCR、深度学习布局识别和机器学习文本合并的复杂流水线。"},{"id":"p15","kind":"paragraph","text":"（1）视觉化与 OCR：让机器「看」到","raw":"**（1）视觉化与 OCR：让机器「看」到**"},{"id":"p16","kind":"paragraph","text":"金融研报中大量存在扫描件或图片格式的图表。解析的第一步是将 PDF 页面转化为高分辨率图像：使用 pdfplumber 将页面转为图像，同时提取原始字符坐标。如果检测到是扫描件而非电子原生 PDF，系统会启动 OCR 引擎（如 Tesseract），识别图像中的文字并生成新的文本框，与原始信息融合。","raw":"金融研报中大量存在扫描件或图片格式的图表。解析的第一步是将 PDF 页面转化为高分辨率图像：使用 pdfplumber 将页面转为图像，同时提取原始字符坐标。如果检测到是扫描件而非电子原生 PDF，系统会启动 OCR 引擎（如 Tesseract），识别图像中的文字并生成新的文本框，与原始信息融合。"},{"id":"p17","kind":"paragraph","text":"（2）布局识别：让机器「分类」","raw":"**（2）布局识别：让机器「分类」**"},{"id":"p18","kind":"paragraph","text":"系统需要知道哪块是正文，哪块是页眉，哪块是图表。调用基于深度学习目标检测模型的 LayoutRecognizer，对页面进行区域划分，给不同区域打上 Title、Text、Table、Figure 等标签。","raw":"系统需要知道哪块是正文，哪块是页眉，哪块是图表。调用基于深度学习目标检测模型的 LayoutRecognizer，对页面进行区域划分，给不同区域打上 Title、Text、Table、Figure 等标签。"},{"id":"p19","kind":"paragraph","text":"这解决了多栏排版读乱序的问题——因为这里是按区域读取，而不是按行读取。","raw":"这解决了多栏排版读乱序的问题——因为这里是按区域读取，而不是按行读取。"},{"id":"p20","kind":"paragraph","text":"（3）表格结构还原","raw":"**（3）表格结构还原**"},{"id":"p21","kind":"paragraph","text":"金融数据都在表格里，因此不仅要提取表格里的字，还要还原行列关系。TableStructureRecognizer 会裁剪出表格区域，识别单元格边界，将图片中的表格重构为 HTML 或结构化数据，确保「表头—数值」的对应关系不丢失。","raw":"金融数据都在表格里，因此不仅要提取表格里的字，还要还原行列关系。TableStructureRecognizer 会裁剪出表格区域，识别单元格边界，将图片中的表格重构为 HTML 或结构化数据，确保「表头—数值」的对应关系不丢失。"},{"id":"p22","kind":"paragraph","text":"（4）智能文本合并：让机器「连贯」","raw":"**（4）智能文本合并：让机器「连贯」**"},{"id":"p23","kind":"paragraph","text":"这是最体现技术深度的环节。OCR 出来的往往是破碎的单字或单行，需要把它们拼成完整的段落：","raw":"这是最体现技术深度的环节。OCR 出来的往往是破碎的单字或单行，需要把它们拼成完整的段落："},{"id":"p24","kind":"list","text":"- 横向合并：将同一行内距离极近的文本框拼接。\n- 纵向合并：基于行距和对齐方式，将同一自然段的多行文本拼接。\n- 基于 XGBoost 的上下文合并：这是一个高级特性。训练一个 XGBoost 模型，根据文本特征（是否以句号结尾、行间距、字体大小变化）来预测「下一行是否属于当前段落」，这比写死的规则要准确得多。","raw":"- **横向合并**：将同一行内距离极近的文本框拼接。\n- **纵向合并**：基于行距和对齐方式，将同一自然段的多行文本拼接。\n- **基于 XGBoost 的上下文合并**：这是一个高级特性。训练一个 XGBoost 模型，根据文本特征（是否以句号结尾、行间距、字体大小变化）来预测「下一行是否属于当前段落」，这比写死的规则要准确得多。"},{"id":"p25","kind":"heading","text":"2、智能切块：数据入库前的精修","raw":"### 2、智能切块：数据入库前的精修"},{"id":"p26","kind":"paragraph","text":"切分不是简单的「每 500 字切一刀」。错误的切分会斩断语义，导致检索失效。在 RAG 系统中，文档切块是最容易被忽视、却直接决定检索效果的环节：切得太碎，模型看不懂上下文；切得太长，检索噪音大且浪费 Token。","raw":"切分不是简单的「每 500 字切一刀」。错误的切分会斩断语义，导致检索失效。在 RAG 系统中，文档切块是最容易被忽视、却直接决定检索效果的环节：切得太碎，模型看不懂上下文；切得太长，检索噪音大且浪费 Token。"},{"id":"p27","kind":"paragraph","text":"需要一种从宏观到微观再回归宏观的处理策略，原始文档变成机器可读的向量要经历三个阶段。","raw":"需要一种从宏观到微观再回归宏观的处理策略，原始文档变成机器可读的向量要经历三个阶段。"},{"id":"p28","kind":"paragraph","text":"第一步：格式识别与初步解析。系统首先充当一个分拣员，根据文件后缀调用不同的解析器（如 PdfParser、DocxParser），将文档拆解为自然的段落（Sections）。","raw":"**第一步：格式识别与初步解析**。系统首先充当一个分拣员，根据文件后缀调用不同的解析器（如 PdfParser、DocxParser），将文档拆解为自然的段落（Sections）。"},{"id":"p29","kind":"paragraph","text":"第二步：碎片化拆分。为了保证后续合并的灵活性，不能直接用段落当 Chunk，因为有的段落长达几千字，有的只有几个字。因此需要先打碎：利用分隔符（换行符、句号、感叹号）将 Section 进一步拆解为更小的文本碎片，产物是一堆细粒度的句子或短语。","raw":"**第二步：碎片化拆分**。为了保证后续合并的灵活性，不能直接用段落当 Chunk，因为有的段落长达几千字，有的只有几个字。因此需要先打碎：利用分隔符（换行符、句号、感叹号）将 Section 进一步拆解为更小的文本碎片，产物是一堆细粒度的句子或短语。"},{"id":"p30","kind":"paragraph","text":"第三步：基于 Token 预算的动态合并。这是最核心的一步，我们像装箱子一样，设定一个标准箱子大小（例如 128 Tokens），然后把刚才打碎的句子一个个装进去。","raw":"**第三步：基于 Token 预算的动态合并**。这是最核心的一步，我们像装箱子一样，设定一个标准箱子大小（例如 128 Tokens），然后把刚才打碎的句子一个个装进去。"},{"id":"p31","kind":"paragraph","text":"这里涉及的核心算法是 naive_merge，它的目标是在保持语义连贯性（不把一句话切断）的前提下，最大化利用每个 Chunk 的容量：","raw":"这里涉及的核心算法是 `naive_merge`，它的目标是在保持语义连贯性（不把一句话切断）的前提下，最大化利用每个 Chunk 的容量："},{"id":"p32","kind":"list","text":"1. 初始化：创建一个空的 Chunk 容器，设定阈值（例如 chunk_token_num = 128）。\n2. 循环填装：遍历文本碎片列表，计算「当前 Chunk 已有的 Token 数 + 新碎片的 Token 数」。小于等于阈值就装入；大于阈值就封箱，把当前 Chunk 保存，创建一个新 Chunk 并把这个碎片作为第一个元素放进去。\n3. 最终输出：生成 Chunks 列表。","raw":"1. **初始化**：创建一个空的 Chunk 容器，设定阈值（例如 `chunk_token_num = 128`）。\n2. **循环填装**：遍历文本碎片列表，计算「当前 Chunk 已有的 Token 数 + 新碎片的 Token 数」。小于等于阈值就装入；大于阈值就封箱，把当前 Chunk 保存，创建一个新 Chunk 并把这个碎片作为第一个元素放进去。\n3. **最终输出**：生成 Chunks 列表。"},{"id":"p33","kind":"paragraph","text":"举个例子：假设阈值是 128，当前 Chunk 里已经装了 120 个 Token，下一个句子有 15 个 Token。120 + 15 = 135 > 128，于是系统把这 120 个 Token 打包成 Chunk A，然后开启 Chunk B，把这 15 个 Token 的句子放进去。","raw":"举个例子：假设阈值是 128，当前 Chunk 里已经装了 120 个 Token，下一个句子有 15 个 Token。120 + 15 = 135 > 128，于是系统把这 120 个 Token 打包成 Chunk A，然后开启 Chunk B，把这 15 个 Token 的句子放进去。"},{"id":"p34","kind":"paragraph","text":"经过上述处理，我们得到的不仅仅是一段段文本字符串，而是一个结构化的对象列表。每个最终的 Chunk 都包含：","raw":"经过上述处理，我们得到的不仅仅是一段段文本字符串，而是一个结构化的对象列表。每个最终的 Chunk 都包含："},{"id":"p35","kind":"list","text":"- Content：文本块的字符串内容，用于给大模型阅读。\n- Tokens：分词后的 Token 列表，用于计算成本和上下文窗口。\n- Metadata：位置信息（页码、在原文中的偏移量），这对于产品界面上展示引用来源至关重要。","raw":"- **Content**：文本块的字符串内容，用于给大模型阅读。\n- **Tokens**：分词后的 Token 列表，用于计算成本和上下文窗口。\n- **Metadata**：位置信息（页码、在原文中的偏移量），这对于产品界面上展示引用来源至关重要。"},{"id":"p36","kind":"paragraph","text":"为什么不直接按字符数或段落切分？ 直接切字符可能会把「人工智能」切成「人工」和「智能」两个 Chunk，导致语义崩坏；直接切段落则有的极短导致向量过于稀疏检索匹配不到，有的极长超过 Embedding 模型的窗口限制。","raw":"**为什么不直接按字符数或段落切分？** 直接切字符可能会把「人工智能」切成「人工」和「智能」两个 Chunk，导致语义崩坏；直接切段落则有的极短导致向量过于稀疏检索匹配不到，有的极长超过 Embedding 模型的窗口限制。"},{"id":"p37","kind":"paragraph","text":"naive_merge 是一种动态平衡：先利用标点符号保护句子级的语义完整性，再利用 Token 计数控制 Chunk 的大小颗粒度。","raw":"`naive_merge` 是一种动态平衡：先利用标点符号保护句子级的语义完整性，再利用 Token 计数控制 Chunk 的大小颗粒度。"},{"id":"p38","kind":"heading","text":"3、重建层级结构与元数据","raw":"### 3、重建层级结构与元数据"},{"id":"p39","kind":"paragraph","text":"单纯的文本切片是孤立的，我们需要为每个切片找回它的坐标。","raw":"单纯的文本切片是孤立的，我们需要为每个切片找回它的坐标。"},{"id":"p40","kind":"paragraph","text":"比如，当模型检索到「第三条：赔付金额为 50 万」这个切片时，如果丢失了它所属的「一级标题：重大疾病险」，模型可能会张冠李戴，把它当成意外险的条款。","raw":"比如，当模型检索到「第三条：赔付金额为 50 万」这个切片时，如果丢失了它所属的「一级标题：重大疾病险」，模型可能会张冠李戴，把它当成意外险的条款。"},{"id":"p41","kind":"paragraph","text":"解决方案是元数据增强。在解析时维护一个层级栈，给每一个 Chunk 打上标签：","raw":"解决方案是元数据增强。在解析时维护一个层级栈，给每一个 Chunk 打上标签："},{"id":"p42","kind":"code","text":"{\n  \"source\": \"理赔手册.pdf\",\n  \"page\": 5,\n  \"section_path\": \"总则/第二章/第三条\",\n  \"type\": \"text\"\n}","raw":"```json\n{\n  \"source\": \"理赔手册.pdf\",\n  \"page\": 5,\n  \"section_path\": \"总则/第二章/第三条\",\n  \"type\": \"text\"\n}\n```"},{"id":"p43","kind":"paragraph","text":"那么在线问答检索时，就可以让 LLM 利用这些元数据进行精准过滤（例如「只看第二章的内容」），或者在回答时准确引用出处。","raw":"那么在线问答检索时，就可以让 LLM 利用这些元数据进行精准过滤（例如「只看第二章的内容」），或者在回答时准确引用出处。"},{"id":"p44","kind":"heading","text":"在线检索：组合优化","raw":"## 在线检索：组合优化"},{"id":"p45","kind":"paragraph","text":"有了高质量的数据，下一步是让系统听懂人话，并精准找到答案。","raw":"有了高质量的数据，下一步是让系统听懂人话，并精准找到答案。"},{"id":"p46","kind":"heading","text":"1、Query 理解与优化","raw":"### 1、Query 理解与优化"},{"id":"p47","kind":"paragraph","text":"用户的问题往往是模糊的（如「怎么报销？」），直接检索效果会比较差。","raw":"用户的问题往往是模糊的（如「怎么报销？」），直接检索效果会比较差。"},{"id":"p48","kind":"list","text":"- 意图识别：判断用户是在查流程、查数据还是闲聊，可通过规则匹配或 BERT 分类模型实现。\n- Query 重写：将口语化的「怎么报销保险费用？」改写为规范的「保险费用报销流程是什么？」，去除冗余词，补全上下文。\n- Query 扩写：引入同义词。用户搜「理赔」，系统自动扩展搜索「索赔」「赔付」，扩大召回范围。\n- HyDE（假设文档嵌入）：对于复杂问题，先让 LLM 生成一个假设答案，再用这个假设答案去检索真实文档，这能显著提升长尾问题的召回率。","raw":"- **意图识别**：判断用户是在查流程、查数据还是闲聊，可通过规则匹配或 BERT 分类模型实现。\n- **Query 重写**：将口语化的「怎么报销保险费用？」改写为规范的「保险费用报销流程是什么？」，去除冗余词，补全上下文。\n- **Query 扩写**：引入同义词。用户搜「理赔」，系统自动扩展搜索「索赔」「赔付」，扩大召回范围。\n- **HyDE（假设文档嵌入）**：对于复杂问题，先让 LLM 生成一个假设答案，再用这个假设答案去检索真实文档，这能显著提升长尾问题的召回率。"},{"id":"p49","kind":"heading","text":"2、混合检索","raw":"### 2、混合检索"},{"id":"p50","kind":"paragraph","text":"单一的检索方式在金融场景下往往捉襟见肘。向量检索擅长语义匹配（如「推销」匹配「销售」），但对专有名词（如「A 款产品」）不够敏感；关键词检索（BM25）擅长精确匹配，但无法理解语义。","raw":"单一的检索方式在金融场景下往往捉襟见肘。向量检索擅长语义匹配（如「推销」匹配「销售」），但对专有名词（如「A 款产品」）不够敏感；关键词检索（BM25）擅长精确匹配，但无法理解语义。"},{"id":"p51","kind":"paragraph","text":"解决方案是 BM25 与向量检索并行，将两者的得分进行归一化和加权融合（例如 0.6 × 向量分 + 0.4 × BM25 分），取长补短。","raw":"解决方案是 BM25 与向量检索并行，将两者的得分进行归一化和加权融合（例如 0.6 × 向量分 + 0.4 × BM25 分），取长补短。"},{"id":"p52","kind":"heading","text":"3、领域微调","raw":"### 3、领域微调"},{"id":"p53","kind":"paragraph","text":"通用的 Embedding 模型（如 BGE）可能不懂「保单现金价值」是什么。策略是使用金融领域的私有数据（问答对、专业术语）对 Embedding 模型进行微调，拉近专业术语在向量空间中的距离，显著提升召回准确率。","raw":"通用的 Embedding 模型（如 BGE）可能不懂「保单现金价值」是什么。策略是使用金融领域的私有数据（问答对、专业术语）对 Embedding 模型进行微调，拉近专业术语在向量空间中的距离，显著提升召回准确率。"},{"id":"p54","kind":"heading","text":"4、重排序：精度的最后一道防线","raw":"### 4、重排序：精度的最后一道防线"},{"id":"p55","kind":"paragraph","text":"初步检索为了不漏掉信息，通常会召回 Top 50 甚至 Top 100 个片段，但这其中包含大量噪声。","raw":"初步检索为了不漏掉信息，通常会召回 Top 50 甚至 Top 100 个片段，但这其中包含大量噪声。"},{"id":"p56","kind":"paragraph","text":"Cross-Encoder 重排引入一个更精细的模型，将用户 Query 和候选文档拼在一起进行深度打分，能识别细微的语义差异。例如查询「最新车险流程」，初步检索可能混入了「2020 年旧流程」，重排模型能精准识别出「2023 年修订版」更相关，将其排在第一位。","raw":"Cross-Encoder 重排引入一个更精细的模型，将用户 Query 和候选文档拼在一起进行深度打分，能识别细微的语义差异。例如查询「最新车险流程」，初步检索可能混入了「2020 年旧流程」，重排模型能精准识别出「2023 年修订版」更相关，将其排在第一位。"},{"id":"p57","kind":"paragraph","text":"总结来看，检索是一个漏斗模型：Query 优化（扩充漏斗口）→ 混合检索（粗筛）→ 重排序（精选）→ LLM 生成。需要关注每个环节的转化率。通过建立评估指标（如 MRR、NDCG、Precision@K），就可以量化出「引入重排后，Top 3 召回率提升了 15%」这样的结论。","raw":"总结来看，检索是一个漏斗模型：Query 优化（扩充漏斗口）→ 混合检索（粗筛）→ 重排序（精选）→ LLM 生成。需要关注每个环节的转化率。通过建立评估指标（如 MRR、NDCG、Precision@K），就可以量化出「引入重排后，Top 3 召回率提升了 15%」这样的结论。"},{"id":"p58","kind":"heading","text":"最后","raw":"## 最后"},{"id":"p59","kind":"list","text":"- 离线解析的颗粒度，决定了知识库的纯度。\n- 在线检索的重排策略，决定了用户体验的精度。","raw":"- 离线解析的颗粒度，决定了知识库的纯度。\n- 在线检索的重排策略，决定了用户体验的精度。"},{"id":"p60","kind":"paragraph","text":"也许一个 AI 产品的护城河，就是藏在这些最不起眼的脏活累活、某一个参数的调优里。看似枯燥的技术细节优化，最终都会转化为用户感知到的「这个 AI 真的懂我」。","raw":"也许一个 AI 产品的护城河，就是藏在这些最不起眼的脏活累活、某一个参数的调优里。看似枯燥的技术细节优化，最终都会转化为用户感知到的「这个 AI 真的懂我」。"}],"authored_claims":[{"id":"rag-is-two-async-pipelines","text":"RAG 系统本质上由两条异步流水线组成：离线处理（提取、向量化、存储）是消化系统，在线查询（Query 处理、检索、生成）是大脑。建立这个上帝视角，才能在出 Bad Case 时判断问题出在哪一条链路。","stance":"judgment","confidence":"high","supersedes":null,"note":null,"formed_at":"2025-12-05"},{"id":"chunking-is-most-overlooked","text":"文档切块是 RAG 系统中最容易被忽视、却直接决定检索效果的环节。切得太碎模型看不懂上下文，切得太长检索噪音大且浪费 Token。","stance":"judgment","confidence":"high","supersedes":null,"note":null,"formed_at":"2025-12-05"},{"id":"naive-merge-dynamic-balance","text":"按 Token 预算动态合并（naive_merge）是工程落地中高性价比的切块方案——先用标点符号保护句子级的语义完整性，再用 Token 计数控制 Chunk 的颗粒度，避免了纯字符切分和纯段落切分各自的缺陷。","stance":"judgment","confidence":null,"supersedes":null,"note":null,"formed_at":"2025-12-05"},{"id":"metadata-prevents-mismatch","text":"孤立的文本切片会导致张冠李戴。检索到「第三条：赔付金额为 50 万」时如果丢失了它所属的一级标题，模型可能会把重疾险条款当成意外险。层级栈加元数据是找回坐标的解法。","stance":"fact","confidence":null,"supersedes":null,"note":null,"formed_at":"2025-12-05"},{"id":"retrieval-is-a-funnel","text":"检索是一个漏斗模型：Query 优化扩充漏斗口、混合检索做粗筛、重排序做精选、最后交给 LLM 生成。每个环节的转化率都要单独看，才能量化出「引入重排后 Top 3 召回率提升多少」这样的结论。","stance":"judgment","confidence":"high","supersedes":null,"note":null,"formed_at":"2025-12-05"}],"claim_ids":["rag-is-two-async-pipelines","chunking-is-most-overlooked","naive-merge-dynamic-balance","metadata-prevents-mismatch","retrieval-is-a-funnel"],"revision":"431e7720506246e0b8231773189f859b93501f0555880fa84cae48c4f6ba937b"}