RAG项目填坑记录:表格检索、标签丢失

发布时间:2026/7/12 19:44:44
RAG项目填坑记录:表格检索、标签丢失 最近在做一个文档问答的项目遇到几个之前没碰到过的问题记录一下解决过程。一、表格内容召回了但答不出来现象文档里有三张表表1是数据字典表2是评估标准表3是飞行规则。表1相关的问题都能答对。表2和表3检索能命中对应的chunk但模型给不出正确答案或者给的数据对不上。排查过程我用的是Docling做文档解析。看了一下解析后的chunk内容发现问题出在表格转文本这一步。表1结构简单就是两列字段名和含义。转成文本后大概是字段Axxx字段Bxxx这种格式。即使表头在切分时丢了每一行数据本身是自解释的模型能看懂。表2和表3不一样。它们有复杂的表头比如第一行是合并单元格的分类标签下面才是具体数据列。Docling处理这种表时表头被放到chunk_0数据行被分到后面的chunk。当用户提问命中数据行那个chunk时模型看到的只有一堆孤立的数字和短文本不知道这些数字对应什么列自然答不出来。解决办法我试了几个方案最简单有效的是入库前把列名复制到每一行数据上def process_table(df): # 把多级表头展平合并成一层的列名 if isinstance(df.columns, pd.MultiIndex): df.columns [_.join(col).strip() for col in df.columns.values] chunks [] for _, row in df.iterrows(): line .join([f{col}为{val} for col, val in row.items() if pd.notna(val)]) chunks.append(line) return chunks这样每个数据chunk都带上了列名信息模型看到的是最大飞行速度为0.8而不是0.8。另外两个备选方案也可以考虑一是用模型把表格转成自然语言描述再入库二是表格行数不多的话整表作为一个chunk不切分。根据你的具体情况选。二、文档开头的chunk召不回来现象文档开头部分的内容比如GUI框架、开发语言这些信息永远检索不到。看了一下chunk_0解析时CUDA报错了标签没提取出来。chunk_17也是类似问题抛了个level2的key error。Docling依赖层级标题检测来给chunk打标签文档开头如果有特殊格式扉页、目录、图表解析器容易崩。没标签的chunk在检索时权重很低基本等于沉底。解决办法这两个chunk每次都是稳定受害者我的处理方式比较直接给这些特定ID的chunk手动补标签从正文截取前几十个字作为标签干脆把它们从检索池里移出来单独挂到系统提示词里。因为文档开头通常是背景介绍不是高频问答内容放固定上下文里反而更稳定三、多路召回的配比问题原来的做法我用了两路召回BM25做关键词匹配向量做语义匹配。一开始是按常规做法把两路分数加权求和或者固定比例比如语义3条、关键词2条组Top-K。效果不太好。问题在哪BM25的分数和向量相似度分数根本不在一个量级上。向量相似度在0.5到0.9之间BM25经常跑到十几甚至更高。强行加权或者归一化总有一方的贡献被压掉。更关键的是关键词匹配和语义匹配召回来的东西交集很小。用户问精确编号比如规则4.2.1的时候语义召回来的基本都是泛化内容关键词那边找到了大量命中的chunk但因为只分配了2个名额正确答案被截掉了。现在的做法改成两路各自独立召回不限制比例合并去重后全部塞给模型允许最终数量大于K。具体来说就是语义召5条关键词也召5条合并去重后可能有7到9条全部送给LLM。效果比加权混合好不少。现在模型上下文窗口都够大多喂几条不影响但召回率提升明显。如果想进一步控制最终数量可以用RRF倒数排名融合来做合并排序它只看每路召回中的排名次序不看具体分数比加权求和合理。总结这次踩的几个坑核心就三点复杂表格转文本后结构容易丢入库前做行级列名粘连能解决大部分问题解析器不稳定导致的标签丢失可以手动兜底特定chunk直接物理隔离多路召回不要强行配比或加权各自独立召回再合并效果更稳记录一下希望对遇到类似问题的同学有帮助。