最近在搭一个RAG系统,用的bge-large做向量召回,top50召回率还行,但精排阶段用了ChatGLM3-6B做rerank,发现中文长文本(比如企业财报、论文摘要)效果特别拉胯,经常把不相关的排到前面。试过直接拼接query和doc,也试过加特殊分隔符,但感觉模型根本没理解长文本里的关键信息。
RAG里用大模型做精排,但中文长文本检索效果差,有救吗?
全部回复
共 8 条我也遇到过类似的问题,长文本下小模型精排确实容易“抓瞎”,感觉是上下文窗口和注意力分配的双重瓶颈。可以试试把文档切得更细一点,比如按段落或关键句分段召回,再让ChatGLM只对每段打分,最后聚合排序,效果比直接喂整篇好不少。另外,精排阶段用更长上下文的模型(比如13B或更大的)或者针对排序任务微调一下,也是个方向。
同样踩过这个坑,感觉问题可能出在ChatGLM3-6B对长文本的position encoding上限上,它原生支持的序列长度有限,超了之后注意力分布会乱。可以试试先把长文本分段再分别rerank,或者换成能处理更长上下文的模型比如Qwen2.5-7B,效果会稳一些。另外精排阶段加个粗排过滤,先按BM25或相似度阈值卡一下,减少无关文档干扰,也能改善不少。
同感,我也试过用ChatGLM3做rerank,长文本确实容易丢失关键信息。后来我改用分段+滑动窗口的方式,把长文档切成512token的块再分别打分聚合,效果好了不少。另外可以试试instruction tuning一下精排模型,或者换专门的长文本reranker比如Cohere的,虽然贵但省心。
我最近也踩过类似的坑,6B模型对中文长文本的语义捕捉确实不太够,尤其财报这种密集信息段落。建议试试把精排拆成两阶段:先用轻量模型(比如bge-reranker)粗筛到top10,再喂给ChatGLM做细排,长文本可以按段落拆开分别打分再融合。另外prompt里明确标注“请关注第X段”这类指令,有时候比改分隔符管用。
试试把长文本按段落切分后再输入rerank模型,或者换个专门优化过的中文长文本排序模型?
同感,bge-large召回还行但精排阶段用ChatGLM3-6B处理中文长文本确实容易翻车,可能是模型对长距离依赖的把握不够,或者训练数据里长文档样本偏少。我试过把文档分段后再让模型对比每段和query的相关性,最后取最高分,效果比直接拼接好一些。另外也可以考虑换专门做rerank的模型比如bge-reranker-v2,它对中文长文本的支持会好一点,你可以试试看。
bge-large做召回其实问题不大,但ChatGLM3-6B在长文本rerank上确实容易丢细节,尤其中文财报这种密集信息。可以试试把query拆成关键实体或核心句,和doc分段交叉匹配再打分,而不是整段拼接。另外换专门的中文rerank模型比如bge-reranker-v2,效果可能会稳很多。
这个现象我也遇到过,bge-large在中文长文本上的向量召回其实已经做得不错了,但到了精排阶段,ChatGLM3-6B对长上下文的敏感度确实不够,尤其是财报或论文摘要里那些关键数字、术语和逻辑关系,模型容易“漏看”或者“混淆”。我试过把query和doc分段输入,甚至用[SEP]和[CLS]做标记,但效果提升有限,后来发现可能是模型对长文本的注意力分布太分散了,关键信息被稀释了。有个思路你可以试试:在输入精排之前,先用一个轻量级的关键词提取或摘要模块,把长文本压缩成几个核心句子,再和query拼接,这样模型更容易抓住重点。另外,也可以考虑用更长的上下文窗口模型,比如GLM-4或Qwen2.5,它们对中文长文本的理解力会强一些。你提到精排把不相关的排到前面,有没有可能是训练数据里正负样本的分布有问题?比如负样本太简单或者太随机,导致模型学到的区分特征不够鲁棒。