码上拾光

多模态模型给的坐标不能直接用:一次回锚的实现记录

· #实现#文档解析#AI应用

上一篇提到,大纲解析链路里多模态模型这一级的坐标不准。这篇写怎么修的。这段代码是整个项目里改动最多的一个文件,最后一千八百多行,值得单独记。

现象

给模型一张页面图,让它返回标题文字和位置。文字基本对,位置不对——Y 坐标普遍偏 30 到 50 个点(PDF 坐标单位,一页高约 840)。偏差方向不固定,同一页里有的偏上有的偏下。

切片是按标题坐标截的,偏 40 个点意味着切片要么把上一节的尾巴切进来,要么把本节的第一行切掉。

思路

模型认字准、定位不准,那就只用它的字,位置自己找。PDF 本身有文本层(扫描件走 OCR 后也有),拿模型给的标题文字在页面文本里搜,搜到的位置才是真位置。

听起来简单,做起来全是细节。

细节

匹配前先归一化。 模型输出的文字和 PDF 文本层的文字经常不一致:全角半角(3.13.1)、空格(3 .1)、繁简、标点。先做 NFKC 归一化再比。

不要求全文匹配。 标题可能很长,模型可能只返回前半截或者少一个字。用”锚点匹配”:取标题里最有区分度的一段(通常是编号加前几个字)去搜,搜到之后再验证附近文字是否大体一致。

距离阈值。 搜到的候选位置如果离模型给的位置超过 60 个点,宁可判定为”没找到”,也不接受。因为同一页上可能有重复文字(目录页、页眉),搜到的可能是别处。

跨页单调性。 标题在文档里的顺序是确定的:第 5 个标题的位置一定在第 4 个之后。回锚完所有标题后做一次全局检查,位置顺序和大纲顺序不一致的,说明锚错了,回退到模型原始坐标并打标记。

贪心还是全局。 一开始用贪心:逐个标题搜,搜到就定。后来发现前面锚错一个,后面全跟着错。改成先收集所有候选,再按单调性约束做一次全局选择,错误率明显下降。

结果

回锚之后,切片边界的错误从”经常”变成”偶尔”。剩下的错误集中在扫描件 OCR 文本层本身就错的情况——文本层里的字和图上的字对不上,搜不到,只能回退。

顺带的教训

这个文件一开始两百行,最后一千八百行,不是代码写得差,是每一个”偶尔”都对应一类真实文档。文档解析这种事,80% 的效果用 20% 的代码,剩下 20% 的效果要 80% 的代码,而客户验收看的是后面那 20%。

接受这一点之后,心态平和了很多。


← 回到文章列表