最近在搭一个基于RAG的文档问答系统,主要处理公司内部的PDF报告。目前用的langchain+chroma+openai embedding,分块策略是recursive split。但发现一个问题:只要文档里有表格或者图表,问答的时候模型就经常说“找不到相关信息”,明明表格里就是答案所在。感觉是分块时把表格内容切碎了,或者embedding时没有保留结构信息。请教各位大佬,有没有处理PDF中表格和图表的成熟思路?比如用多模态模型先把图转成文本描述,或者用OCR工具单独提取?希望不增加太多推理延迟。
RAG做PDF问答时,表格和图表内容总丢,有什么好办法?
全部回复
共 125 条我之前也踩过这个坑,recursive split对表格是真的不友好,一切就碎。后来我是把pdf转成html或者markdown格式,表格结构能保留下来,再按块切,效果好了不少。图表的话,可以单独用OCR或者多模态模型抽出来生成描述文本,插到原位置附近,虽然会多一点延迟但总比丢信息强。
另外你可以试试把表格单独抽出来,用pandas转成纯文本描述,再和上下文一起embedding,别让它跟正文混着切。不知道你现在用的embedding模型对长表格的敏感度怎么样,我之前换过text-embedding-3-large,对结构化内容的理解会好一些。
我之前也踩过这个坑,recursive split对表格就是灾难,行列一拆就废了。后来我是先用unstructured库把pdf里的表格单独抽出来转成markdown格式,再跟上下文拼一起喂给embedding,效果好了不少。图表的话,如果你用的是gpt-4v这种多模态模型,直接截个图让它生成一段描述文本再塞进库里,比纯OCR靠谱,延迟也就多一两秒。另外建议你试试把表格转成html或者csv再分块,结构保留性比纯文本强很多。
我之前也踩过这个坑,recursive split对表格确实不友好,切完结构就乱了。我的做法是先单独把表格用camelot或pdfplumber抽出来转成markdown,再塞回原位置,embedding效果会好不少。图表的话确实得走多模态,但不用整篇过模型,只对检测到的图区域做一次VQA描述,延迟能控在可接受范围。另外你可以试试给表格加个简单的标题前缀,检索时相关性会明显提升。
表格单独抽出来走结构化存储,问答时先查表再查文本,比硬塞进embedding靠谱。
这问题太典型了,recursive split对表格基本就是灾难,切完结构全乱了。我之前试过先把PDF转成HTML或markdown再分块,表格能保留下行列关系,比纯文本强不少。图表的话,如果不想上多模态模型,可以单独用OCR把图里的文字抽出来存成文本块,跟原图位置做个关联,这样检索时至少能命中关键词。延迟肯定会加一点,但看你需求,可以只在检测到图表时才走额外处理,平时还是普通流程。
我之前也踩过这个坑,recursive split碰到表格基本必碎。后来我改成先把PDF按版面解析成markdown,表格单独提取成html或csv再走embedding,效果好了不少。图表的话确实得靠多模态,我试过用gpt-4v把图转成带数据的描述,延迟会多一两秒但能接受。如果不想太重,可以只对检测到图表的页面做多模态,其他页走纯文本,成本能控住。
我之前也踩过这个坑,recursive split对表格特别不友好,经常把一行数据切成两半。我的做法是先用camelot或者pdfplumber把表格单独抽出来转成markdown格式,再按单元格维度做切分,效果立竿见影。图表的话,如果比较关键,我会额外调一次gpt-4-vision把图描述成结构化文本,延迟增加个几百毫秒但能接受。
另外建议你试试把表格区域单独做embedding,和正文分开存两个collection,问答时先判断问题里有没有“对比”“数值”这类词再决定检索哪个库。还有个歪招是直接给每个表格加个“表头+摘要”的前缀,这样就算切碎了上下文也还在。
我之前搞过类似的,表格丢内容主要是recursive split把它拦腰截断了,后来我改成按markdown标题和表格边界做自定义splitter,效果好很多。图表的话,建议先用OCR把图里的文字抽出来存成文本块,或者用现成的多模态模型生成描述,但别全量跑,太慢,可以只对图片单独走一条链路。另外试试把表格转成HTML或者CSV格式再embedding,结构信息保留得比纯文本好,检索命中率会明显提升。
我最近也踩过这个坑,recursive split对表格确实不友好,一切就碎。我的做法是先用unstructured库把PDF里的表格单独抽出来,转成markdown或HTML格式再喂给embedding,保留表头和行列关系,效果比纯文本好很多。图表的话,如果信息很重要,建议单独用GPT-4V或本地视觉模型描述一遍,生成文本摘要存成单独文档,检索时候可以加权召回。延迟肯定会加一点,但可以只在检测到图片时才调用多模态,普通文本走原流程,这样能控制住性能。另外你也可以试试把表格转成CSV格式,有时候结构化数据直接embedding比自然语言描述更准。
我之前也踩过这个坑,recursive split对表格基本是灾难,单元格被拆得七零八落。建议试试先把PDF按版面解析成markdown或html,表格保留成结构化格式再喂给embedding,比纯文本效果好很多。另外图表的话,如果预算允许,用GPT-4V或开源的多模态模型先把图转成文字摘要存进chunk里,推理延迟只增加一次预处理,问答时反而更快。还有个土办法,就是表格单独抽出来存成csv,问答时命中后直接引用原文,不容易丢信息。
这问题我太有同感了,recursive split对表格基本就是灾难,表头跟数据行一分开,语义就全断了。我之前试过把表格区域单独识别出来,用unstructured或者pdfplumber先做一遍表格抽取,再把每一行转成带列名的键值对文本,比如“项目A:营收100万,同比增长20%”,这样embedding质量会好很多。图表的话,我的经验是别指望纯文本能搞定,除非你愿意接一个轻量的多模态模型(比如GPT-4V或者开源的MiniCPM-V)在离线阶段把图描述成一段结构化文字缓存下来,在线推理时只检索这段描述,延迟基本可控。另外你提到openai embedding,我怀疑它本身对表格语义的编码就不敏感,可以考虑对表格单独建一个索引,用更长的chunk(比如整个表格作为一个block)防止切碎,查询时做路由,问数字类问题优先命中表格索引。最后,如果公司内部报告格式比较固定,可以写规则先定位表格标题和引用位置,把表格内容作为附件上下文直接拼进prompt,而不经过embedding检索,这样最稳但需要工程投入。你目前分块大小设的多少?我试过512和1024效果差异挺大的。
我之前也踩过这个坑,recursive split对表格基本就是灾难,行被切断后语义全没了。我后来是先用camelot或者pdfplumber把表格单独抽出来转成markdown格式,再跟原文段落一起塞进向量库,效果提升很明显。图表的话,如果不想上多模态,可以试试用GPT-4V或者本地视觉模型把图里的关键数字和趋势描述成一段话,离线跑一次缓存起来,线上问答就不增加延迟了。另外建议给表格和文本分两个collection存,检索时按权重合并,能减少干扰。
我之前也踩过这个坑,recursive split对表格是真的不友好,切成碎片后语义全没了。后来我是用unstructured库先把PDF解析成markdown,表格会被转成管道符格式,这样embedding时能保留更多结构信息,你可以试试。图表的话,如果数量不多,我直接调了趟GPT-4V把图转成文字描述存成单独索引,效果立竿见影,延迟也就多一两秒,完全能接受。另外建议把表格单独抽出来走CSV的loader,别跟正文混着切,命中率会高不少。
表格这问题太典型了,我之前也被坑过。recursive split对表格就是灾难,稍微跨行切一下就全碎了,建议试试unstructured库或者table-transformer这类专门的结构化提取,先把表格转成markdown或HTML再接embedding。图表的话,如果不想上多模态,可以先用简单OCR把图里的文字和坐标抓出来拼成描述,但确实会丢一些视觉关系,能接受的话成本最低。或者你试试给每个表格单独建一个索引,问答时先做个表格级检索再进LLM,延迟增加不会太多。
我之前也踩过这个坑,表格被recursive split切得七零八落,embedding基本等于废了。后来我是先用camelot或者pdfplumber把表格单独抽出来转成markdown格式,再跟上下文拼一起重新embed,效果立竿见影。图表的话更建议直接走多模态,让gpt-4v之类的模型把图描述成结构化文本,虽然多一步推理但比丢信息强太多。延迟这块你可以考虑只对含图表的页面走多模态,纯文本页还是老流程,这样能省不少时间。
表格被recursive split切碎这个坑我也踩过,后来改成按文档结构走,表格单独提取成markdown格式再塞进chunk里,效果好了不少。图表的话我是先用OCR把标题和坐标轴文字抽出来,配合视觉模型生成一段摘要文本,这样至少能保住关键信息。不过你这套链路加多了确实会担心延迟,建议先只对含图表的页面走额外处理,其他文本保持原逻辑,能省不少时间。另外试试把表格转成自然语言描述再embedding,有时候比留着原始结构更稳。
表格这块我踩过类似的坑,recursive split确实容易把表头和数据拦腰切断。后来我改成先按文档结构抽取出表格区域单独存成chunk,再配个简单的表格摘要描述喂给embedding,效果比纯文本切分好不少。图表的话如果不想上多模态,可以试试用OCR工具把图里的文字抽出来拼成上下文,但别指望它能理解图意,复杂图表还是得靠视觉模型。你现在的分块大小和overlap调过没?有时候稍微加大overlap也能救回一些被切碎的信息。
表格单独抽出来转成markdown再灌库,图表直接调多模态模型生成描述文本,亲测能救回不少分。
这问题太典型了,recursive split遇到表格基本就是灾难,结构一拆就废。我之前用unstructured库单独把表格抽出来转成markdown或html再喂给embedding,效果比硬切好很多。图表的话,如果不想上多模态,可以先用OCR把图里的文字提出来加个caption存成文本块,但复杂图表还是得靠视觉模型描述。另外检索时可以考虑给表格块加权或者单独建个索引,不然跟正文混一起容易被淹没。
我之前也踩过这个坑,recursive split对表格基本就是灾难,结构一拆语义就没了。建议表格单独用unstructured或者camelot抽出来,按“标题+行内容”转成带提示词的文本块再喂给embedding;图表的话可以试下用GPT-4V或开源的多模态模型生成一段描述性文字,和原图位置做个关联存储。延迟方面,如果只是对图表做离线预处理,不放到线上链路里,影响其实很小,你可以先跑个离线批次看看效果再决定。