微信扫码
与创始人交个朋友
我要投稿
前言
经典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模式中:
这样,通过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 Agent
print('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来对其进行增强,具备了极大的灵活性与扩展性, 几乎可以完成任意基于知识的复杂任务:
关于Agentic RAG的介绍就先到这里。
后记
这篇文章之后,整个《RAG实战篇》系列就全部介绍完了,这个系列一共包括十篇文章,从最经典的Naive RAG开始,然后沿着RAG的主要环节,即索引、查询转换、路由、查询构建、检索召回、内容生成六大环节,依次介绍了每个环节的主要优化方案。然后,风叔又介绍了RAG系统的两座高山,GraphRAG和Agentic RAG。至此,相信大家对RAG系统已经有了更加深刻的认识,并且能够搭建一个相对完整的RAG系统。
整个RAG在学术界和工业界,依然在飞速的升级进化,后续风叔还会针对该话题,零星做一些介绍。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-11-21
提升RAG性能的全攻略:优化检索增强生成系统的策略大揭秘 | 深度好文
2024-11-20
FastGraphRAG 如何做到高达 20%优化检索增强生成(RAG)性能优化
2024-11-20
为裸奔的大模型穿上"防护服":企业AI安全护栏设计指南
2024-11-20
RAG-Fusion技术在产品咨询中的实践与分析
2024-11-19
构建高性能RAG:文本分割核心技术详解
2024-11-19
【RAG竞赛获奖方案】CCF第七届AIOps国际挑战赛季军方案分享EasyRAG:一个面向AIOps的简洁RAG框架
2024-11-19
企业RAG构建中,如何用“行级别权限管控”避免数据泄露
2024-11-19
大模型prompt压缩技术总结:从硬提示到软提示代表方案实现思路
2024-07-18
2024-05-05
2024-07-09
2024-07-09
2024-05-19
2024-06-20
2024-07-07
2024-07-07
2024-07-08
2024-07-09
2024-11-06
2024-11-06
2024-11-05
2024-11-04
2024-10-27
2024-10-25
2024-10-21
2024-10-21