大模型应用开发,必看的 RAG 高阶技巧
最近一直在探索 RAG(检索增强生成)相关的技术,并且分析了 LangChain 和 LlamaIndex 相关技术实现,现在总结和分享一些自己的经验。
RAG 前沿进展
我们借助相关论文中的截图,来说明目前 RAG 技术的进展。
Retrieval-Augmented Generation for Large Language Models: A Survey
除了在用户的输入 query 上做文章外,还有更多的操作是进行后处理,比如多路召回和重排序。而且最新的技术也增加了很多新模块,比如 Self-RAG 这篇文章就引入了自我性,通过训练一个新的 LLM 去自适应地按需检索段落,并生成和反映检索到的段落和它自己的生成结果。但这个方法的流程太长,是否适合线上的实际环境,需要真实场景的验证。
从 LangChain 以及 LlamaIndex 的实现,以及论文中提及内容,这次分享 RAG 的高阶技术分为了三个大模块:
- Query Transformation:针对用户 query 的相关操作。
- Agent 技术:本质上利用大模型的能力去调用函数来实现更复杂的功能。
- Post-process:也就是后处理,在我们检索到上下文之后,可以使用一些后处理的方法去对数据进行处理,以便得到更优质的上下文信息。
像重排序、多路召回技术这些都比较常见了,就不再做过多的阐述。
Query Transformation
Query Transformation 主要就是利用各种技巧和大模型的能力,去对用户的 query 进行改写、转换等操作,丰富 query 的语义信息。
Query Rewrite
因为对于 LLM 而言,原始查询不可能总是最佳检索,尤其是在现实世界中,我们首先提示 LLM 重写查询,然后进行检索增强阅读。这个技术可以参考下面 LangChain 中的示例,本质还是使用了提示词工程,去编写改写的提示词,这部分提示词也是可以优化的地方。
template = """Provide a better search query for \
web search engine to answer the given question, end \
the queries with '**'. Question: \
{x} Answer:"""
rewrite_prompt = ChatPromptTemplate.from_template(template)
def _parse(text):
return text.strip("**")
distracted_query = "man that sam bankman fried trial was crazy! what is langchain?"
rewriter = rewrite_prompt | ChatOpenAI(temperature=0) | StrOutputParser() | _parse
rewriter.invoke({"x": distracted_query})
MultiQuery
本质上是 Query Rewrite 的改进版,可以同时生成 n 个和用户 query 相似的 query,然后同时进行检索,这样能确保召回的内容尽可能的符合原始 query。具体可以参考下面的代码,需要 LangChain 的最新版本。
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI
question = "What are the approaches to Task Decomposition?"
llm = ChatOpenAI(temperature=)
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=vectordb.as_retriever(), llm=llm
)


