RAG 入库后路径里多了 \_ ?markdownify 默认转义踩坑与修复

最近在做知识库构建服务时,遇到一个很隐蔽的问题:源文档(Word)里明明是 Windows 共享路径,入库后在 Knowledge Base 的 chunk 里却在下划线前面多了一个反斜杠。

原文:\\12.254.13.112\Temp_Share

入库后的文本:\\12.254.13.112\Temp\_Share(注意下划线前被自动添加了反斜杠)

乍一看像是解析 bug,但仔细追链路后发现:这其实是 HTML 转 Markdown 转换库的「渲染安全」默认行为,在 RAG 场景里反而会伤害检索。

一、问题现象

上传 DOCX 后,在 chunk 预览里可以看到:

  • 原文:Temp_Share
  • 入库:Temp\_Share

搜索词 Temp 能命中,但精确匹配 Temp_Share 时就会受影响。尤其是 Windows 共享路径、变量名、邮箱本地部分这类包含下划线的内容,很容易踩坑。

二、根因定位

我们的 DOCX 处理链路是:

DOCX →(mammoth)→ HTML →(markdownify)→ Markdown → Chunk / Embedding

关键点在第二步:markdownify。本地验证非常直接:

import markdownify

print(markdownify.markdownify("Temp_Share"))

# Temp\_Share

对应源码逻辑大致是:只要开启了 escape_underscores,就会把所有下划线替换成带反斜杠的形式。也就是说,不是源文件写错了,也不是业务代码自己加的反斜杠,而是 markdownify 默认开启了下划线转义。

三、为什么默认要转义?

这不是 markdownify 的 bug,而是它的设计目标决定的。Markdown 里,下划线和星号都是强调语法:

  • _this_ 会渲染成斜体
  • *this* 也会渲染成斜体

如果 HTML 转 Markdown 后不做转义,后续再被 Markdown 渲染器解析时,像 foo_bar_baz 这类文本,在部分解析器下可能被误当成斜体。所以 markdownify 默认:

  • escape_underscores = True:把 _ 转成 \_
  • escape_asterisks = True:把 * 转成 \*
  • escape_misc = False:其他特殊字符默认不转义

一句话总结:默认偏向「渲染正确」,不是「字面量正确」。这对博客、文档站点是合理的;对 RAG 知识库却不一定合适。

四、RAG 场景要不要转义?

结论:RAG 入库通常不需要、也不应该默认做这类 Markdown 渲染转义。

原因很简单:RAG 链路里,文本主要不是「给人看的 Markdown 渲染结果」,而是要经历切块、向量化、检索、再喂给大模型生成答案。在这些环节里,\_ 基本都是噪声:

  • 切块:多出来的反斜杠没有语义价值
  • Embedding:改变 tokenization,路径语义被污染
  • 精确检索:用户搜 Temp_Share,库里却是 Temp\_Share
  • 喂给 LLM:模型可能以为路径里真有反斜杠

Windows 路径尤其危险。原文本身已经有大量反斜杠,再叠加转义后的 \_,人和模型都更难分辨。

五、业界通行做法

不同库的默认值,其实已经反映出「面向渲染」和「面向 LLM / RAG」的分水岭:

默认转义下划线

定位

python-markdownify

开启

通用 HTML→Markdown,偏渲染

html-to-markdown(Kreuzberg)

关闭

明确面向 LLM / RAG

另外,markdownify 的 escape_misc 也曾被默认打开,但社区反馈很差:过度转义会把 URL、标识符搞坏,后来又改回默认关闭。这说明一个趋势:为渲染器保平安的转义,不该无脑带到 LLM 数据预处理里。

当然,「不转义」不等于「不做清洗」。RAG 更该做的是:

  • 去掉零宽字符、不可见 Unicode、bidi 控制符
  • 规范化空白
  • 保留标题、列表、表格结构

而不是给正文里的下划线和星号加反斜杠。

六、修复方式

官方已经提供开关,直接关掉即可:

markdownify.markdownify(

  html,
  heading_style="ATX",
  table_infer_header=True,

  escape_underscores=False,

 escape_asterisks=False,

)

我们在项目里改了两处调用:

  1. HTML / DOCX 主转换路径
  2. PDF 表格转 Markdown 路径

效果对比:

  • 修改前:Temp\_Share
  • 修改后:Temp_Share

七、改完后要注意什么

  1. 已入库旧数据不会自动修复,需要重新上传或重建受影响文档。
  2. Markdown Preview 可能出现「真斜体」。如果原文本来就想用 _italic_,关闭转义后会按 Markdown 渲染成斜体。对 IT Wiki、路径、配置项、代码标识符为主的语料,这个代价通常可接受。

八、实践建议

如果你也在做文档入库 / RAG 预处理,可以按这个原则取舍:

  • 面向页面渲染:保留 escape_underscores=True
  • 面向检索和 LLM:关闭 escape_underscores 和 escape_asterisks
  • 永远别盲目打开 escape_misc=True,很容易把 URL 和技术标识符污染掉

更实用的总结:Markdown 转义是为了「显示好看」;RAG 入库是为了「语义准确」。两者目标不同,默认策略不该混用。

参考

  1. python-markdownify 官方仓库
  2. html-to-markdown(Kreuzberg)API 文档
  3. CommonMark / GFM 关于下划线和星号强调语法的说明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茫茫人海一粒沙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值