最近在做一个人社局的文档问答机器人,想把政策文件切分后塞进向量数据库做RAG。测试了不同chunk大小(128/256/512 tokens),发现小的召回准但上下文不完整,大的倒是能覆盖更多信息,但容易把不同条款混在一起,检索出来全是噪声。用的bge-small模型,感觉对中文长文本效果一般,但换bge-large又怕太慢(只有一张3090)。另外,我看有的方案还用了双编码器+交叉编码器重排序,这个对社区项目来说是不是太复杂了?求各位大佬指点一下落地的平衡点,谢谢。
用向量数据库搞RAG,chunk大小和embedding模型怎么选啊?
全部回复
共 164 条政策文件这种结构化的文本,其实不太适合一刀切按固定token切。我之前做类似的政务问答,发现按条款或章节来切效果会好很多,比如先按“第X条”做粗切,再对超长的条款做二次切分,这样每个chunk语义上是完整的,不会出现半截条款被检索出来的情况。bge-small对中文长文本确实力不从心,但换large之前可以先试试bge-m3或者用指令微调过的中文embedding,有些7B以下的模型在3090上跑推理也还扛得住,不一定非得large。chunk大小我倾向于256到384之间,配合一定的overlap,纯128虽然准但确实容易丢上下文,尤其是政策文件里前后条款有关联的时候。重排序那块其实没你想的那么复杂,用bge-reranker-base跑交叉编码,对top20做重排,3090完全带得动,延迟也就多几百毫秒,召回质量提升挺明显的。另外可以试试在检索前加一层关键词过滤,比如用户问的是“社保补缴”,先用BM25筛一遍缩小范围,再走向量召回,混合检索对政策类问答特别管用。别一上来就追求端到端最优,先把切分和检索策略调稳,后面再考虑加rerank或者换模型,不然调参空间太大容易迷失。
我最近也踩过类似的坑,后来改成按条款结构切,比如以“第X条”为边界,再限制单chunk不超过300 tokens,效果比硬切好不少。bge-small确实有点吃力,你可以先试bge-base,3090上跑推理问题不大,large再配量化也能撑。重排序不用一上来就上交叉编码器,先用向量召回top20再用轻量rerank模型筛一遍,社区项目完全够用。
我最近也在折腾类似的东西,chunk可以试试按语义切而不是死磕固定长度,政策文件里条款边界挺明显的,按章节或条款切效果会好很多。bge-small确实对长文本吃力,其实换个bge-base或者m3e-base在3090上完全跑得动,不一定非得上large。重排序那套双塔+交叉编码器听着唬人,但你可以先用bge-reranker-base试试,加在检索后面成本不高,召回质量提升挺明显的。
政策文件切分可以试试按条款结构走,别死磕固定token数,比如按“第X条”切再控制单块不超300字,召回会干净很多。3090上bge-large其实推理还行,批量小一点能跑,关键是建库时别用太大batch。重排序对社区项目不算复杂,bge-reranker-base接一下也就几十行代码,先粗排top20再精排top5提升挺明显。