背景与问题

检索增强需要在检索之前,对查询进行预处理,以提高检索的准确性和效率,Pre-Retrieval即预检索优化/检索前优化,着重优化索引结构和查询方式。优化索引级提高被索引的内容质量,查询优化就是要在查询之前就明确用户的问题,去分析和理解用户的意图,从而生成更准确的查询。

索引优化:

摘要索引

在处理非结构化的文档如长表格、文本混合的文档,普通的rag可能会处理效果不好,甚至将表拆解,从而影响检索结果,这种情况怎么找到重点是一个挑战,而摘要索引就是提取文档的关键信息,生成摘要、存储摘要,当用户检索的时候其实是检索向量数据库里的摘要数据,匹配之后去返回原始文档。

基本思路:

  • 让LLM为每个块生成摘要,embedding存储摘要数据
  • 检索摘要数据,回溯原文档返回
  • 将原文本作为上下文送给LLM获取答案

适合的场景:

  • 统计表(列多、行多)
  • 合同 / 法务 / 财务 / 制度(条款+说明混杂)
  • 技术文档(说明 + 示例 + 注意事项)
  • 企业知识库

缺点:

  • 摘要索引更适合 “文档稳定、查询频繁” 的系统
  • 不适合 “实时写入、即时可查”的内容,比如聊天、实时日志、高频更新、极细的问答文档
  • 摘要即二次理解,如果做摘要的大模型能力较差,则会影响摘要信息的提取,进而影响检索效果

父子索引

父子索引主要是解决精度和上下文之间的平衡问题,在传统的rag中,切分文档块需要取舍文档精度和内容全面的问题:

小的文档块: 优点:精度高,能精确的匹配用户的提问,减少不必要的干扰
缺点:如果大模型需要整合很多段信息才能回答问题时候,文档块缺乏必要的上下文信息

大的文档块: 优点:能整合更多的上下文信息,更全面的回答问题
缺点:检索精度低,整合的噪音大,某些信息可能会误导大模型的回答

父子索引是一种分层、多粒度的策略,将文档分成两个层级,父文档存储较大的文本块,提供完整连贯的上下文信息,例如一个章节,一个段落; 子索引存储较小的文本块,聚焦具体的事实观点,例如一个句子、一个段落。在向量数据库中存储子索引,当用户提问的时候,先检索子索引,找到相关的文本块,再根据这些文本块去检索父索引,整合更多的上下文信息,返回更全面的回答。

假设性问题索引

假设性问题索引是说将文档切片之后,对每一个切片使用大模型生成几个假设性问题,然后将问题存储到向量数据库里。用户提问的时候检索假设性问题索引,找到相关的问题,再根据这些问题去获得原文档块,整合原文档块,再送给大模型回答问题。

基本思路:

  • 先将文档切分成多个文档块
  • 让大模型对每一个文档块生成N个假设性问题,以向量的方式存储假设性问题
  • 当用户提问时,检索向量数据库(假设性问题数据)
  • 根据问题获得原文档块,整合原文档块
  • 将整合后的文档块作为上下文送给大模型回答问题

元数据索引

元数据索引是指在rag中,除了文档内容本身,还存储了文档的元数据(如标题、作者、时间等),将元数据也转换为向量表示,存储到向量数据库中,用来作为元数据检索的素材。

基本思路:

  • 为每个文档块生成元数据(标签),以向量的方式存储元数据
  • 当用户提问时,用大模型提取出所提问题的元数据,通过标签先对文档做一次过滤(数据过滤候选文档集)
  • 结合向量检索进一步获取topk的文档块(语义检索)
  • 将文档块作为上下文送给大模型回答问题

查询优化

Enrich 完善问题

当用户使用简单的自然语言与大模型交互的时候,由于语言简略模糊等缘故,使得大模型无法理解或者产生歧义,为了理解用户的意图,我们需要引导用户补充完善问题。即通过多轮对话,不断收集用户信息,补充完善所需数据。

基本流程:

  • 用户提问
  • LLM判断内容是否完善(针对某个业务模板)
  • 不完善则引导用户继续补充需求
  • 直到LLM判断需求完善
  • 总结用户需求
  • 进行Rag检索或者其他
  • 获得答案/反馈

这里面有几个关键的点,一是要针对每个要处理的业务构建模板,包含业务所需收集的信息,比如订酒店、订机票等,需要的时间、地点等,设置N个模板供大模型判断用户是否是有意要办理这些业务,二是要判断用户意图(是否是想办理某个业务),然后选择选择模板来判断信息是否完善,三是要根据用户的多轮文化,不断完善用户业务需求,直到LLM判断需求完善。最后根据用户的信息总结给下一步的业务(rag搜索或者交给某个传统的接口去执行)

Multi-Query 多查询检索

对用户的问题让大模型从多角度生成多个问题,然后根据生成的问题多分别检索,整合召回多结果,以整合更加完善的返回结果。

基本思路:

  • 让大模型基于用户问题,生成多个相关问题;
  • 所有的问题都去检索向量数据库,整合多路召回的结果;
  • 最后将整合的结果作为上下文送给大模型回答问题。

问题:

  • 优点:问题更加完善
  • 缺点:上下文会增加

Decomposition 问题分解

当用户问题很复杂的时候,大模型一次回答可能不好,这时候要考虑使用问题分解,将问题分解成为多个小问题,然后用串行或者并行的方式进行执行。

实现思路:

  • 将用户问题拆解成多个问题(调用LLM)
  • 对每个问题分别检索答案
  • 整理返回的所有答案,结合原始问题,整理新的prompt
  • 调用大模型获取答案