AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


聊聊Agentic RAG,可能是目前最强大和灵活的RAG实现方式
发布日期:2024-10-27 08:20:41 浏览次数: 1680 来源:风叔云


前言

经典RAG应用的范式与架构已经非常流行,我们可以在很短的时间内借助成熟框架开发一个简单能用的RAG应用。在【RAG实战篇系列】文章中,风叔也介绍了一个最最基本的Naive RAG系统,以及优化RAG系统的十八般武器。

但是,实际应用场景要远比理论中复杂。以企业级应用场景为例,企业内部有大量不同来源与类型的文档,比如word、pdf等非结构化数据,以及mysql数据库这种结构化数据。

假设,我们现在需要在这些文档之上构建一个知识密集型的应用或工具,包括:

  • 基于全局的理解文档后回答问题,比如对某知识内容进行总结摘要
  • 跨文档与知识库的回答问题,比如比较不同文档内容的区别
  • 结合非知识工具的复合场景,比如从文档提取产品介绍发送给客户


如果使用传统的RAG架构,要实现这种复杂的场景显然是不现实的。传统RAG系统在回答文档相关的事实性问题时可以表现得不错,但是实际的知识应用要更为复杂,包括推理性和总结性的各类问题。 当然我们也可以借助一些改进的RAG范式来提高应用场景的适应性,比如GraphRAG,但在一些跨文档或者需要结合工具的场景下仍然无法胜任。

这种情况下,Agentic RAG就能派上用场了。


1. Agentic RAG的概念

Agentic RAG是一种结合了AI Agent和RAG系统的方法,借助Agent的任务规划与工具能力,来协调完成对多文档的、多类型的检索问答需求

下图可以很清晰地解释Agentic RAG的原理,读过风叔之前文章的读者应该靠接,AI Agent的四大模块分别是感知、规划、记忆和工具。在Agentic RAG模式中:

  • RAG退化成Agent使用的知识工具,我们可以针对目标文档构建多种不同的RAG引擎,比如使用向量索引来回答事实性问题,使用摘要索引来回答总结性问题,使用知识图谱索引来回答需要更多关联性的问题等。
  • 在单个文档/知识库的多个RAG引擎之上设置一个DocAgent,把RAG引擎作为该Agent的tools,并利用LLM的能力由DocAgent在自己“负责”的文档内使用这些tools来回答问题。
  • 最后设置一个总的顶级代理TopAgent来管理所有的低阶DocAgent,将DocAgent看作自己的tools,仍然利用LLM来规划、协调、执行用户问题的回答方案。


这样,通过Agent和RAG的强强联合,Agentic RAG既能准确的解析不同类型的文件,还能利用Agent强大的规划和推理能力,面对用户Query选择最合适的路由策略和处理方法,大幅提升系统面对海量文档、跨文档检索、全局提炼与总结等问题时的处理能力。


2. Agentic RAG的应用场景

Agentic RAG模式吸收了AI Agent和RAG的优点,AI Agent擅长规划、反思和执行,而RAG系统擅长本地知识的获取和检索。因此,Agentic RAG可以在很多场景下发挥价值。

企业知识管理:企业数据非常繁多,文件类型、格式、内容也千差万别。但是我们可以构建一个Agentic RAG部队,每个Agent后面都接了相应的数据源和Rag系统,专门处理不同的领域或不同部门的数据。这样,既能高效地访问和综合来自多个数据源的信息,也能打破不同部门的数据孤岛。

智能客服:传统的智能客服会先识别用户的意图,然后交给不同的Bot来跟进,当Bot也无法回答时,再转人工坐席。一套智能客服背后都要接很多个Bot,而且每个Bot都要进行特殊配置和训练,非常繁琐。通过Agentic RAG,Top Agent可以真正理解多样的用户查询意图,从而自动分配给对应的Doc Agent,从正确的源文档检索相关信息,并提供准确和个性化的响应。

设备检修:当电气设备出现设备故障时,通常都需要品牌方派遣专业的检修人员,而且需要查询很久产品手册才能定位问题所在。一个电气设备的产品手册可能少则几百页,多则数千页,故障类型也多种多样。利用Agentic RAG,就能帮助维修人员更快速地在现场定位问题,找到解决方案。

智能投研:在传统的券商部门,投研部门的每个人每周都要阅读大量的新闻和报告,进行关键信息的总结、提炼和推理,并撰写投资研究报告,非常重复而且低效。而通过Agentic Rag,我们可以针对技术、产品、行业、财务、政策等不同的领域构建专门的Doc Agent,比如财务Agent就专门负责搜索和读取目标公司或行业的财务数据,整理财务报告。最终Top Agent汇总多个Agent的输出之后,生成最终的报告

我们还能列出非常多的Agentic Rag的应用场景,这里就不一一赘述了。


3. Agentic RAG的实现

下面,我们结合源代码,介绍Agentic Rag的实现方式。


第一步,准备测试文档

首先准备三个RAG相关的测试PDF文档,其名称与路径分别保存。当然,在实际应用中,这里文档数量可以扩展到非常大:

names = ['c-rag','self-rag','kg-rag']files = ['c-rag.pdf','self-rag.pdf','kg-rag.pdf']


第二步,创建Doc Agent的函数

创建一个针对单个文档生成Doc Agent的函数,在这个函数中,将对一个文档创建两个索引与对应的RAG引擎:

  • 针对普通事实性问题的向量索引与RAG引擎

  • 针对更高层语义理解的总结类问题的摘要索引与RAG引擎

最后,我们把这两个引擎作为一个Agent可使用的两个tool,构建一个Doc Agent返回。

#采用chroma向量数据库chroma = chromadb.HttpClient(host="localhost", port=8000)collection = chroma.get_or_create_collection(name="agentic_rag")   vector_store = ChromaVectorStore(chroma_collection=collection)
#创建针对某个文档的doc_agent  def create_doc_agent(file,name):  
#文档拆分    print(f'Starting to create doc agent for 【{name}】...\n')  docs =SimpleDirectoryReader(input_files = [file]).load_data()splitter = SentenceSplitter(chunk_size=500,chunk_overlap=50)nodes = splitter.get_nodes_from_documents(docs)
#创建向量索引,并做持久保存if not os.path.exists(f"./storage/{name}"):print('Creating vector index...\n')storage_context = StorageContext.from_defaults(vector_store=vector_store)vector_index = VectorStoreIndex(nodes,storage_context=storage_context)vector_index.storage_context.persist(persist_dir=f"./storage/{name}")else:print('Loading vector index...\n')storage_context = StorageContext.from_defaults(persist_dir=f"./storage/{name}",vector_store=vector_store)vector_index = load_index_from_storage(storage_context=storage_context)
#创建基于向量的查询引擎query_engine = vector_index.as_query_engine(similarity_top_k=5)
#创建摘要索引与对应的查询引擎summary_index = SummaryIndex(nodes)    summary_engine = summary_index.as_query_engine(response_mode="tree_summarize")  
#将RAG引擎转化为两个tool    query_tool = QueryEngineTool.from_defaults(query_engine=query_engine,name=f'query_tool',description=f'Use if you want to query details about {name}')      summary_tool = QueryEngineTool.from_defaults(query_engine=summary_engine,name=f'summary_tool',description=f'Use ONLY IF you want to get a holistic summary of the documents. DO NOT USE if you want to query some details about {name}.')  
    #创建一个doc agent      doc_agent =   **ReActAgent** .from_tools(  **[query_tool,summary_tool]** ,verbose=True,                                    system_prompt=f"""You are a specialized agent designed to answer queries about {name}.You must ALWAYS use at least one of the tools provided when answering a question; DO NOT rely on prior knowledge. DO NOT fabricate answer.""")      return doc_agent


这部分代码主要目的就是把两个查询的RAG引擎包装成工具,一个是query_tool,用于回答事实性问题;一个是summary_tool,用于回答总结性问题当然,实际情况下我们可以结合需要,构建更多类型的引擎。

最后我们构建了一个ReAct思考范式的AI Agent,并把构建的RAG tools插入。


第三步,批量创建Doc Agent

有了上面的函数后,就可以批量创建好这些文档的Doc Agent。这里把每一个文档名字和对应的Agent保存在一个dict中:

#创建不同文档的agent  print('===============================================\n')print('Creating tool agents for different documents...\n')doc_agents_dict = {}  for name, file in zip(names, files):    doc_agent = create_doc_agent(file, name)      doc_agents_dict[name] = tool_agent


第四步,创建Top Agent

最后,我们需要创建一个顶层的Top Agent,这个Agent的作用是接收客户的请求问题,然后规划这个问题的查询计划,并使用工具来完成,而这里的工具就是上面创建好的多个Doc Agent:

 #首先将Doc Agent进行“工具化”  print('===============================================\n')print('Creating tools from doc agents...\n')  all_tools = []
for name in names:agent_tool = QueryEngineTool.from_defaults(           #注意,Agent本身也是一种Query Engine,所以直接转为tool             query_engine=doc_agents_dict[name],             #这个工具的名字             name=f"tool\_{name.replace("-", "")}",             #描述这个工具的作用和使用方法             description=f"Use this tool if you want to answer any questions about {name}."  )
all_tools.append(agent_tool)
#创建Top Agentprint('Creating top agent...\n')top_agent =  **OpenAIAgent.** from_tools(  **tools=all_tools** ,verbose=True,system_prompt="""You are an agent designed to answer queries over a set of given papers.Please always use the tools provided to answer a question.Do not rely on prior knowledge.DO NOT fabricate answer""" ) 


注意这里我们创建的Top Agent使用了 OpenAIAgent ,而不是ReActAgent,这也展示了这种架构的灵活性,不同Agent可以按需使用不同的推理范式。

我们通过Prompt告诉Top Agent,“请始终使用提供的工具来回答问题”,就是让Top Agent对问题进行路由。


第五步,测试

现在来简单测试这个Top Agent,并观察其执行的过程:

输入一个问题: Please introduce Retrieval Evaluator in C-RAG pattern?

==Entering Chat REPL
Type "exit" to exit.
Human: Please introduce Retrieval Evaluator in C-RAG pattern?
Added user message to memory: Please introduce Retrieval Evaluator in C-RAG pattern?
== Callina Function ==
Calling function: tool crag with args: {"input": "Retrieval Evaluator in C-RAG pattern")
Thought: The user is asking about the "Retrieval Evaluator"in the C-RAG pattern. I need to use a tool to help me answer the question.
Action: query tool
Action Input: { 'input: Retrieval Evaluator in C-RAG pattern'}
Observation: The retrieval evaluator in the CRAG pattern is designed to evaluate the relevance of retrieved documents to the input questi egree based on the relevance scores calculated for each question-document pair. Depending on this confidence level, the evaluator trigger actions- Correct, Incorrect, or Ambiguous. This process helps in determining whether the retrieved documents are suitable for generatin
Thought: I can answer without using any more tools. I'll use the user's lanquage to answer
Answer: The Retrieval Evaluator in the C-RAG pattern is responsible for evaluating the relevance of retrieved documents to the input ques e level based on relevance scores for each question-document pair, triggering actions like Correct, Incorrect, or Ambiquous. This evaluat Leved documents are appropriate for generating a response
Got output: The Retrieval Evaluator in the C-RAG pattern is responsible for evaluating the relevance of retrieved documents to the input dence level based on relevance scores for each question-document pair, triggering actions like Correct, Incorrect, or Ambiquous. This eva retrieved documents are appropriate for generating a response.

注意观察上面的Thought环节,可以看出Agent的“思考”过程:

第一,在TopAgent这一层,通过OpenAI的function calling来实现,这里的函数名tool_crag,也就是后端Doc Agent的名称。

第二,然后来到Doc Agent层,Doc Agent收到请求后,通过ReAct范式的思考过程,决定需要调用query_tool工具,也就是通过向量索引进行响应的RAG引擎。收到返回后DocAgent通过观察与推理,认为可以回答这个问题,并返回结果给Top Agent。

第三,Top Agent收到函数调用的结果后,认为无需再次进行其他函数调用,因此直接输出了结果,整个迭代过程结束。


第六步,进一步优化Agentic Rag

上面我们只用了三个文档,构建了针对它们的DocAgent。如果这里的文档数量是几十或者几百,过多的Doc Agent作为Tools塞给Top Agent进行推理选择时会带来一些问题,比如LLM产生困惑并推理错误的概率会提高,比如过多的Tools信息导致上下文过大,成本与延迟增加。

一种可行的方法是,利用RAG的思想对Tools进行检索,即只把本次输入问题语义相关的Tools(即这里的多个Doc Agent)交给Top Agent使用。 


总结

相对于更适用于对少数文档进行简单查询的经典RAG应用,Agentic RAG的方法通过更具有自主能力的AI Agent来对其进行增强,具备了极大的灵活性与扩展性, 几乎可以完成任意基于知识的复杂任务:

  • 基于RAG之上的Doc Agent将不再局限于简单的回答事实性的问题,通过扩展更多的后端RAG引擎,可以完成更多的知识型任务 。比如:整理、摘要生成、数据分析、甚至借助API访问外部系统等
  • Top Agent管理与协调下的多个Doc Agent,可以通过协作完成联合型的任务。 比如对两个不同文档中的知识做对比与汇总,这也是经典问答型的RAG无法完成的任务类型。


关于Agentic RAG的介绍就先到这里。


后记

这篇文章之后,整个《RAG实战篇》系列就全部介绍完了,这个系列一共包括十篇文章,从最经典的Naive RAG开始,然后沿着RAG的主要环节,即索引、查询转换、路由、查询构建、检索召回、内容生成六大环节,依次介绍了每个环节的主要优化方案。然后,风叔又介绍了RAG系统的两座高山,GraphRAG和Agentic RAG。至此,相信大家对RAG系统已经有了更加深刻的认识,并且能够搭建一个相对完整的RAG系统。

整个RAG在学术界和工业界,依然在飞速的升级进化,后续风叔还会针对该话题,零星做一些介绍。


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询