【Bug已解决】MarkdownHeaderTextSplitter splits nested custom headers into separate chunks when strip_hea…
【Bug已解决】MarkdownHeaderTextSplitter splits nested custom headers into separate chunks when strip_headersFalse 解决方案一、现象长什么样用 LangChain 的MarkdownHeaderTextSplitter按 Markdown 标题切分文档当设置strip_headersFalse即希望保留标题文本在块里且文档里有嵌套的自定义标题多级标题、或非标准标题写法时切分结果不对# 期望每个块都带着它之上的完整标题层级内容不丢失 [ {content: # H1\n## H2\n正文...}, ... ] # 实际嵌套/自定义标题被单独切成一个空块正文被拆到别的块 [ {content: ## H2}, {content: 正文...}, ... ] # H2 与正文分离具体表现只在strip_headersFalse时出现strip_headersTrue标题不保留时反而“正常”因为标题被丢掉了问题被掩盖。文档里有多级嵌套标题如#/##/###连续或同一级出现多次或自定义标题标记时某些标题被切成一个“只有标题、没有正文”的孤立块而正文去了下一个块。下游 RAG 检索时这些“只有标题的空块”会污染索引或正文块丢失了上下文标题。现象表明splitter 在“保留标题”模式下对嵌套标题的归属判断错了——标题没被正确“挂到”后续正文上。关键特征strip_headersFalse时嵌套/自定义标题被错误地切成独立块与正文脱节导致块内容结构破坏。二、背景MarkdownHeaderTextSplitter的作用是按 Markdown 标题层级把长文档切成块常用于 RAG 的文档预处理让每个块携带它所属的标题路径比如“第一章 第二节 正文”这样检索时块带有结构上下文。它有两个关键行为按标题切分遇到一个标题就结束当前块、开始新块。strip_headersTrue时标题文本不进入块内容只作为元数据False时标题文本要保留在块内容里便于直接阅读/拼接。正确的“保留标题”行为应该是当前块要包含“从当前层级到正文”的所有标题 正文。例如遇到## H2后是一段正文块应该是# H1\n## H2\n正文H1 是更早的上级应随 H2 一起带下来因为它们是这块内容的上下文。bug 出在splitter 在处理嵌套标题连续的多个同级/上级标题或自定义标题模式时把“标题行本身”当成了一个独立的切分点于是生成了“只有标题、没有正文”的块而真正的正文被推到了下一个块。本质是对“标题行是否自带正文、标题之间如何合并”的判断有缺陷。三、根因根因是MarkdownHeaderTextSplitter在strip_headersFalse模式下把每个标题行都当成独立切分边界没有把连续/嵌套标题与紧随的正文归并到同一个块导致标题被切成孤立空块标题行即切分点splitter 遇到标题就flush当前累积内容成块。当strip_headersFalse时标题文本要进块但如果紧接着又是一个标题嵌套当前块就只有“上一个标题”、没有正文于是产出空/标题块。未合并嵌套标题连续的# H1/## H2应该合并成“H1H2正文”一块但实现把它们逐个 flushH2 单独成块、正文又单独成块。自定义标题模式处理错用户自定义了标题识别正则比如把某些行当标题这些自定义标题在strip_headersFalse下同样被错误切分。strip_headersTrue掩盖问题标题不进块时孤立标题块只是“空块被丢弃”看似正常于是 bug 只在False时暴露。一句话strip_headersFalse时splitter 把标题行当作独立边界 flush没有把嵌套标题与正文归并导致标题被切成孤立块、与正文脱节。四、最小可运行复现下面用 Python 模拟“标题行 flush”vs“标题正文归并”的切分机理import re from typing import List, Dict def split_buggy(text: str, headers_to_split: List[str]) - List[Dict]: 错误每个标题行都 flush 成独立块。 chunks [] buf for line in text.splitlines(): if re.match(r^#{1,6} , line): if buf.strip(): chunks.append({content: buf.strip()}) buf line \n # 标题行另起下一行正文又分开 else: buf line \n if buf.strip(): chunks.append({content: buf.strip()}) return chunks def split_fixed(text: str, headers_to_split: List[str]) - List[Dict]: 修复标题行累积进当前块遇新标题才 flush标题正文归并。 chunks [] buf for line in text.splitlines(): if re.match(r^#{1,6} , line): # 标题总是归并进当前块只有“已有正文”才先 flush 上一块 if buf.strip() and \n in buf.strip(): # 已有完整块才 flush避免孤立标题块 chunks.append({content: buf.strip()}) buf buf line \n else: buf line \n if buf.strip(): chunks.append({content: buf.strip()}) return chunks doc # H1\n## H2\n正文内容\n## H3\n更多正文 print(buggy:, [c[content] for c in split_buggy(doc, [#, ##])]) # [# H1, ## H2\n正文内容, ## H3, 更多正文] - 标题孤立 print(fixed:, [c[content] for c in split_fixed(doc, [#, ##])]) # [# H1\n## H2\n正文内容, ## H3\n更多正文] - 归并正确buggy把# H1切成孤立块fixed把标题与正文正确归并——正是需要修的逻辑。五、解决方案第一层最小直接修复最小修复是在strip_headersFalse时标题行累积进当前块、仅当块已有正文时才在该标题处 flush避免产生只含标题的孤立块# markdown_header_splitter.py修复片段 def split_text(self, text: str) - List[Document]: chunks [] buf [] for line in text.splitlines(): if self._is_header(line): # 仅当已累积正文才 flush 上一块避免孤立标题块 if buf and any(not self._is_header(l) for l in buf): chunks.append(self._make_doc(buf)) buf [] buf.append(line) # 标题归并进当前块 else: buf.append(line) if buf: chunks.append(self._make_doc(buf)) return chunks这一层让strip_headersFalse下嵌套标题与正文正确归并到同一块不再出现孤立标题块。六、解决方案第二层结构性改进把“Markdown 标题切分如何归并标题与正文尤其 strip_headersFalse”收口成唯一的配置对象LangChainMdHeaderSplitPolicysplitter 读它from dataclasses import dataclass from typing import Tuple dataclass(frozenTrue) class LangChainMdHeaderSplitPolicy: MarkdownHeaderTextSplitter 切分归并的单一事实来源。 # strip_headersFalse 时标题必须归并进块不产生孤立标题块 merge_headers_into_chunk: bool True # 仅当块已含正文时才在该标题处 flush flush_only_if_has_body: bool True # 嵌套标题连续多级合并到同一块不被逐个切分 merge_nested_headers: bool True # 自定义标题模式同样适用上述规则 apply_to_custom_header_patterns: bool True # 代码评审卡点 forbidden_patterns: Tuple[str, ...] ( flush on every header line, header-only chunk allowed when strip_headersFalse, ) def should_flush(self, buf: list) - bool: if not self.merge_headers_into_chunk: return True # 只有块里已有非标题正文行才在该标题处 flush return self.flush_only_if_has_body and any( not self._is_header(l) for l in buf) def describe(self) - str: return strip_headersFalse 时标题归并进块、不产生孤立标题块 POLICY LangChainMdHeaderSplitPolicy() def plan_md_flush(buf: list, policy: LangChainMdHeaderSplitPolicy POLICY) - bool: return policy.should_flush(buf)所有 Markdown 标题切分都读POLICY归并语义被固化嵌套/自定义标题在strip_headersFalse下不再被切成孤立块。七、解决方案第三层断言 / CI 守护把“标题归并、不产生孤立块、嵌套合并”做成断言。下面用 pytest 守护import pytest def test_no_isolated_header_chunk(policy): # 块若只含标题行不应被 flush 成孤立块 assert policy.merge_headers_into_chunk is True assert header-only chunk allowed when strip_headersFalse \ in policy.forbidden_patterns def test_flush_only_with_body(policy): assert policy.flush_only_if_has_body is True # 只有标题的 buf 不应 flush assert policy.should_flush([# H1, ## H2]) is False # 含正文的 buf 应在新标题处 flush assert policy.should_flush([# H1, 正文]) is True def test_merge_nested(policy): assert policy.merge_nested_headers is True def test_custom_patterns(policy): assert policy.apply_to_custom_header_patterns is True def test_forbid_flush_every_header(policy): assert flush on every header line in policy.forbidden_patterns这五组断言锁住(1) 无孤立标题块(2) 仅含正文才 flush(3) 嵌套合并(4) 自定义模式适用(5) 禁止逐标题 flush。CI 跑通即代表strip_headersFalse切分结构正确。八、排查清单遇到MarkdownHeaderTextSplitter在strip_headersFalse下块结构错看是否孤立标题块块里只有标题没正文 → 标题被独立切分本题。确认 strip_headersFalseTrue时问题被掩盖。查 flush 逻辑是不是每个标题行都触发 flush没归并正文。改归并标题累积进块仅块含正文时在该标题处 flush。统一到LangChainMdHeaderSplitPolicyCI 断言禁止孤立标题块。覆盖嵌套/自定义标题多级标题和自定义模式同样归并。端到端切分后每块都含完整标题层级 正文无空块。九、小结MarkdownHeaderTextSplitter splits nested custom headers into separate chunks when strip_headersFalse的根因是MarkdownHeaderTextSplitter在strip_headersFalse保留标题文本模式下把每个标题行都当作独立切分边界 flush 成块没有把连续的嵌套标题与紧随的正文归并到同一块于是产生“只有标题、没有正文”的孤立块正文被推到下一个块块结构被破坏strip_headersTrue时标题不进块问题被掩盖。最小修复是让标题行累积进当前块、仅当块已含正文时才在该标题处 flush避免孤立标题块结构性改进是用唯一的LangChainMdHeaderSplitPolicy固化归并语义CI 用五组断言守护“标题归并、无孤立块、嵌套合并”。记住保留标题的切分器标题是块的上下文前缀而不是独立内容必须和正文归并否则 RAG 索引会被空块污染。

相关新闻

【Bug已解决】Related to #31887 (custom header pattern support) 解决方案

【Bug已解决】Related to #31887 (custom header pattern support) 解决方案

【Bug已解决】Related to #31887 (custom header pattern support) 解决方案 一、现象长什么样 在用 LangChain 的某些聊天模型/LLM 客户端(这一支与 issue #31887 关联)对接需要自定义请求头的模型服务时,发现客户端不允许注入自定义 header…

2026/8/15 2:30:11 阅读更多 →
springboot个人成长足迹与数据分析系统开发与设计

springboot个人成长足迹与数据分析系统开发与设计

1. 项目背景与意义在个人成长与职业发展过程中,我们常常面临一个挑战:如何系统性地记录、追踪和分析自己的学习轨迹、技能提升、项目经验以及时间投入?传统的笔记工具或零散的文件记录难以进行结构化管理和深度分析。因此,开发一个…

2026/8/15 2:30:11 阅读更多 →
OpenClaw架构解析:AI工程化实战中的工作流编排与算子设计

OpenClaw架构解析:AI工程化实战中的工作流编排与算子设计

1. 项目概述:为什么OpenClaw是AI工程师的“实战教科书”?最近在AI工程化社区里,OpenClaw这个名字的讨论热度持续攀升。如果你是一名AI工程师,或者正朝着这个方向努力,却感觉学了一堆算法理论,一到实际部署、…

2026/8/15 2:29:11 阅读更多 →

最新新闻

MathorCup数模竞赛:从赛题结构解析到团队能力匹配的快速选题策略

MathorCup数模竞赛:从赛题结构解析到团队能力匹配的快速选题策略

1. 赛题浅析的核心价值:从“看热闹”到“会选题”又到了MathorCup开赛的季节。每年这个时候,我都能在各个交流群里看到大量类似的提问:“A题和B题哪个好做?”“C题数据量这么大,我们队伍能行吗?”“有没有大…

2026/8/15 3:16:29 阅读更多 →
19套热门表情包系统整理与高效管理全攻略

19套热门表情包系统整理与高效管理全攻略

1. 项目概述:一次表情包资产的系统性整理做内容运营和社群管理的朋友,最近是不是感觉聊天时“词穷”了?不是没话说,而是找不到一个能精准表达当下情绪、又能瞬间拉近距离的表情包。那种感觉,就像厨师面对满柜食材却做不…

2026/8/15 3:16:29 阅读更多 →
终极DDrawCompat完整指南:让老DirectX游戏在现代Windows上重获新生

终极DDrawCompat完整指南:让老DirectX游戏在现代Windows上重获新生

终极DDrawCompat完整指南:让老DirectX游戏在现代Windows上重获新生 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirro…

2026/8/15 3:16:29 阅读更多 →
微信读书笔记插件 WeReader 实测:3 步导出 Markdown 笔记,阅读效率提升看得见

微信读书笔记插件 WeReader 实测:3 步导出 Markdown 笔记,阅读效率提升看得见

微信读书笔记插件 WeReader 实测:3 步导出 Markdown 笔记,阅读效率提升看得见 【免费下载链接】wereader 一个浏览器扩展:主要用于微信读书做笔记,对常使用 Markdown 做笔记的读者比较有帮助。 项目地址: https://gitcode.com/g…

2026/8/15 3:16:29 阅读更多 →
Java Stream API实战:List对象属性聚合计算(求和、最大、最小、平均值)

Java Stream API实战:List对象属性聚合计算(求和、最大、最小、平均值)

1. 项目概述与核心价值在日常的Java开发中,尤其是处理业务数据报表、统计分析或是数据清洗时,我们经常面对一个非常具体的场景:手头有一个包含多个对象的List集合,我们需要快速地对这些对象中的某个数值属性进行一系列聚合计算&am…

2026/8/15 3:16:29 阅读更多 →
VisualCppRedist AIO 完整指南:如何一键修复 Visual C++ 运行库缺失问题

VisualCppRedist AIO 完整指南:如何一键修复 Visual C++ 运行库缺失问题

VisualCppRedist AIO 完整指南:如何一键修复 Visual C 运行库缺失问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 一、那个让人抓狂的周五晚上 …

2026/8/15 3:15:28 阅读更多 →

日新闻

内景 空间站内部 中国空间站 太空 内仓

内景 空间站内部 中国空间站 太空 内仓

本项目为前几天收费帮学妹做的一个项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 空间站内部 中国空间站 太空 内仓 地址:本地PC端运行(或Web…

2026/8/15 0:00:30 阅读更多 →
重新定义数据接口:3个突破性场景让通达信数据读取更智能

重新定义数据接口:3个突破性场景让通达信数据读取更智能

重新定义数据接口:3个突破性场景让通达信数据读取更智能 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 当我们面对海量金融数据时,传统的数据获取方式往往让我们陷入困境—…

2026/8/15 0:00:30 阅读更多 →
一文读懂快消WMS怎么选?2026年国内外10大主流WMS品牌盘点

一文读懂快消WMS怎么选?2026年国内外10大主流WMS品牌盘点

快消品(FMCG)是流通速度较快、竞争较为激烈的行业之一。一瓶饮料从出厂到消费者手中,往往只有几十天甚至几天的周转窗口。这决定了快消行业的仓储管理系统(WMS)与制造业、电商行业存在明显区别:它不仅需要管…

2026/8/15 0:02:30 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/14 13:40:53 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/14 14:06:45 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/15 2:35:29 阅读更多 →