写在前面
LLM+RAG 构建很简单,使用开源项目langchain几行代码就搞定,但简单的构建过程不意味着很好的效果。落地过程中诸多的细节问题非常值得去一一探索和解决。下面笔者会根据实践的经验和收集到的信息进行汇总并记录下来。欢迎读者评论区讨论。
这篇文章不分析具体的细节实现,旨在从解决思路上进行探讨,当前环境下如何提高RAG 的效果。
正文
1. 参考信息中主题的唯一性
试想一下,当我们遇到问题时,会通过各种办法获取参考信息,比如检索,查阅,问询等方式,这些信息我们会自动做一遍过滤,以此来保证参考信息是围绕着问题的主题来进行描述。同理,检索到的信息中如果存在冲突,或者冗余的内容时会极大的影响LM 的生成效果。
这个问题在使用外部搜索引擎(bing, google)获取结果时比较明显,一种可能的解决办法是对候选文档生成主题描述(类似论文的摘要),先进行支持性判断,后续可选择性的深入文档细节进行部分内容提取或其他操作。
2. 预设多个Prompt 模板
这个笔者在前面的文章中也提到过,比如:检索的质量较高的情况下,可以使用完全根据参考信息来回答的Prompt模板,在检索不到内容或者检索的质量低的情况下,可以让模型根据自己的知识来回答。甚至还可以扩展到对问题类型的判断,比如:1. 询问模型自身的问题。类似:你是谁,你叫什么名字等等。2. 主观题:类似:说一下你对日本排放核废水到海洋的看法?等等....通过不同的问题类型走不同的预设Prompt模板。
3. query改写
这个策略在搜索引擎中也很常见,但在RAG中这个改写分成多种类型:1. query扩展:如果原始query没有检索到相关信息或者检索到的信息质量低的情况下,可对query进行扩展或者重写,以此来扩大召回。2. 拆分问题。这个办法有点类似于咒语“step by step”,通过对复杂问题拆分成多个简单的问题,用拆分后的多个子问题去检索获取参考信息。3. 一篇论文的做法先让模型生成一个较简单的回复,然后让回复去进行检索。
4. 多种检索方式
对闭域知识进行多种方式的召回策略。
关键字匹配:通常会用ES来实现。
Embedding匹配:当前中文场景下笔者用的比较多的是m3e的基座模型,而在垂类问答下,存在大量的专名,是非常有必要对向量模型进行微调的,而且收益很高,大概在6个点以上。在这里,还有一个比较细致的工作就是 chunk 切分,当前比较主流的做法是尽量将chunk值调低,但太碎的上下文会造成语义单元的缺失,实际使用中的值需要多次测试。
条件过滤:类似于高级搜索。这种方法在垂类问答下很常见,也由此衍生出了Text2SQL, Text2KG的探索工作,举个例子:我想查看公司2022年的营收情况。通过将文本转化为类SQL查询语句直接对数据库进行查询拿到结果。或者,我问腰痛可能的骨科疾病是什么?通过转化为neo4j的查询语句对KG(闭域KG)进行查询拿到结果。这一块研究的论文也较多,笔者后续会对这一方案进行分享。
5. rerank
模型在长下文的场景中更倾向于关注前后的信息,而会忽略中间的信息,将相关的信息放在前后两端,不相关的放在中间,详情可查阅之前笔者发的文章。
出自:https://mp.weixin.qq.com/s/iE2N-zwqYiCyOAMAM6qgHg