微信扫码
添加专属顾问
多文档代理式 RAG 工作流程
大型语言模型 (LLM) 彻底改变了我们从海量文本数据中提取见解的方式。在财务分析领域,LLM 应用程序正在被设计用来帮助分析师回答有关公司业绩、收益报告和市场趋势的复杂问题。
其中一个应用涉及使用检索增强生成 (RAG) 管道来促进从财务报表和其他来源中提取信息。
假设财务分析师想要了解公司第二季度财报电话会议的主要内容,特别是关注公司正在建立的技术壁垒。这类问题超越了简单的查找,需要更复杂的方法。这就是 LLM 代理的概念发挥作用的地方。
根据 Llama-Index 的说法,“代理”是一个自动推理和决策引擎。它接收用户输入/查询,并可以做出内部决策来执行该查询,以便返回正确的结果。代理的关键组件可能包括但不限于:
将复杂问题分解成更小的问题
选择要使用的外部工具 + 想出调用工具的参数
规划一组任务
将先前完成的任务存储在内存模块中
LLM 代理是一个系统,它结合了各种技术,如规划、定制焦点、内存利用和使用不同的工具来回答复杂问题。
让我们分解如何开发 LLM 代理来回答上述问题:
规划:_ LLM 代理首先需要了解问题的性质并创建一个提取相关信息的计划。这涉及识别关键术语,如“第二季度财报电话会议”和“技术壁垒”,并确定收集这些信息的最佳来源。_
定制焦点:_ 然后,LLM 代理将注意力集中在与技术壁垒相关的问题的特定方面。这涉及过滤掉不相关的信息,并专注于最适合分析师查询的细节。_
内存:_ LLM 代理利用其内存从过去的财报电话会议、公司报告和其他来源中回忆相关信息。这有助于提供背景信息来支持其分析。_
使用不同的工具:_ LLM 代理利用各种工具和技术来提取和分析信息。这可能包括自然语言处理 (NLP) 算法、情绪分析和主题建模,以更深入地了解财报电话会议。_
将复杂问题分解:_ 最后,LLM 代理将复杂问题分解成更简单的子部分,使其更容易提取相关信息并提供连贯的答案。_
来源:代理的通用组件
在标准 RAG 中,LLM 主要用于信息合成。
另一方面,工具调用在 RAG 管道之上增加了一层查询理解层,使用户能够提出复杂的查询并获得更精确的结果。这使 LLM 能够弄清楚如何使用向量数据库,而不仅仅是使用其输出。
工具调用使 LLM 能够通过动态接口与外部环境交互,在该接口中,工具调用不仅有助于选择合适的工具,而且还能推断执行所需的论点。因此,与标准 RAG 相比,它能够更好地理解请求并生成更好的响应。
如果用户提出一个包含多个步骤的复杂问题,或者提出一个需要澄清的模糊问题怎么办?代理推理循环在这种情况下发挥作用。代理能够在工具上进行推理,经过多个步骤,而不是一次性调用。
来源:llama index
在 LlamaIndex 中,代理包含两个组件:
AgentRunner
AgentWorkers
AgentRunner 对象与 AgentWorkers 交互。
AgentRunners 是协调器,它们存储:
状态
会话记忆
创建任务
维持任务
为每个任务运行步骤
展示面向用户的、高级的用户界面
AgentWorkers负责:
选择和使用工具
选择 LLM 来使用工具。
来源:Llama-Index
调用代理查询允许以一次性方式查询代理,但不会保留状态。这就是内存方面发挥作用的地方,它用于维护对话历史记录。在这里,代理将聊天历史记录维护到一个对话记忆缓冲区中。默认情况下,记忆缓冲区是一个扁平的项目列表,它是一个滚动缓冲区,具体取决于 LLM 的上下文窗口大小。因此,当代理决定使用工具时,它不仅使用当前聊天,而且还使用以前的对话历史记录来执行下一组操作。
在这里,我们将构建一个多文档代理来处理多个文档。在这里,我们已经在 3 个文档上实现了代理式 RAG,同样的方法可以扩展到更多文档。
Llama-Index:LlamaIndex 是面向上下文增强 LLM 应用程序的数据框架。
Mistral API:开发人员可以通过其 API 与 Mistral 交互,这与 OpenAI 的 API 系统类似。
它在英语、法语、西班牙语、德语和意大利语中具有天然的流畅性,对语法和文化背景有细致的理解。
它 32K 个令牌的上下文窗口允许从大型文档中精确地调用信息。
它精确的指令遵循功能使开发人员能够设计自己的审核策略——我们使用它来设置 Le Chat 的系统级审核。
它天生具有函数调用功能。
代码使用 google colab 实现。
安装所需依赖项:
%%writefile requirements.txt
llama-index
llama-index-llms-huggingface
llama-index-embeddings-fastembed
fastembed
Unstructured[md]
chromadb
llama-index-vector-stores-chroma
llama-index-llms-groq
einops
accelerate
sentence-transformers
llama-index-llms-mistralai
llama-index-llms-openai
!pip install -r requirements.txt
下载要处理的文档:
!mkdir data
! wget "https://arxiv.org/pdf/1810.04805.pdf" -O ./data/BERT_arxiv.pdf
! wget "https://arxiv.org/pdf/2005.11401" -O ./data/RAG_arxiv.pdf
! wget "https://arxiv.org/pdf/2310.11511" -O ./data/self_rag_arxiv.pdf
! wget "https://arxiv.org/pdf/2401.15884" -O ./data/crag_arxiv.pdf
导入所需的依赖项:
from llama_index.core import SimpleDirectoryReader,VectorStoreIndex,SummaryIndex
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.tools import FunctionTool,QueryEngineTool
from llama_index.core.vector_stores import MetadataFilters,FilterCondition
from typing import List,Optional
importnest_asyncio
nest_asyncio.apply()
读取文档:
documents = SimpleDirectoryReader(input_files = ['./data/self_rag_arxiv.pdf']).load_data()
print(len(documents))
print(f"Document Meta{documents[0].metadata}")
将文档拆分成块/节点
splitter = SentenceSplitter(chunk_size=1024,chunk_overlap=100)
nodes = splitter.get_nodes_from_documents(documents)
print(f"Length of nodes : {len(nodes)}")
print(f"get the content for node 0 :{nodes[0].get_content(metadata_mode='all')}")
输出:
Length of nodes : 43
get the content for node 0 :page_label: 1
file_name: self_rag_arxiv.pdf
file_path: data/self_rag_arxiv.pdf
file_type: application/pdf
file_size: 1405127
creation_date: 2024-05-11
last_modified_date: 2023-10-19
Preprint.
SELF-RAG: LEARNING TO RETRIEVE , GENERATE ,AND
CRITIQUE THROUGH SELF-REFLECTION
...(略)
实例化向量存储
import chromadb
db = chromadb.PersistentClient(path="./chroma_db_mistral")
chroma_collection = db.get_or_create_collection("multidocument-agent")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
实例化嵌入模型
from llama_index.embeddings.fastembed import FastEmbedEmbedding
from llama_index.core import Settings
embed_model = FastEmbedEmbedding(model_name="BAAI/bge-small-en-v1.5")
Settings.embed_model = embed_model
Settings.chunk_size = 1024
实例化 LLM
from llama_index.llms.mistralai import MistralAI
os.environ["MISTRAL_API_KEY"] = userdata.get("MISTRAL_API_KEY")
llm = MistralAI(model="mistral-large-latest")
图片:
简要概述:
这段代码展示了如何将文本拆分成多个块并存储在向量数据库中,以及如何实例化嵌入模型和 LLM。最后,它还展示了一个名为 Self-RAG 的框架,用于提高 LLM 的生成质量和准确性。
需要注意的是,代码中的部分内容可能需要根据实际情况进行修改,例如,需要修改 MISTRAL_API_KEY 的值,并根据自己的需要调整其他参数。
LlamaIndex 数据代理处理自然语言输入以执行操作,而不是生成响应。创建有效数据代理的关键在于抽象工具。但在这种情况下,工具究竟指的是什么?可以将工具视为为代理交互而设计的 API 接口,而不是为人类设计的接口。
核心概念:
**工具:**本质上,工具包含一个通用接口和基本元数据,例如名称、描述和函数模式。
**工具规范:**深入探讨 API 的具体细节,提供一个全面的服务 API 规范,可以转换为各种工具。
有多种类型的工具可用:
**FunctionTool:**将任何用户定义的函数转换为工具,并能够推断函数的模式。
**QueryEngineTool:**围绕现有的查询引擎进行包装。由于我们的代理抽象源自 BaseQueryEngine,因此该工具也可以容纳代理。
name = "BERT_arxiv"
vector_index = VectorStoreIndex(nodes,storage_context=storage_context)
vector_index.storage_context.vector_store.persist(persist_path="/content/chroma_db")
def vector_query(query:str,page_numbers:Optional[List[str]]=None)->str:
'''
perform vector search over index on
query(str): query string needs to be embedded
page_numbers(List[str]): list of page numbers to be retrieved,
leave blank if we want to perform a vector search over all pages
'''
page_numbers = page_numbers or []
metadata_dict = [{"key":'page_label',"value":p} for p in page_numbers]
query_engine = vector_index.as_query_engine(similarity_top_k =2,
filters = MetadataFilters.from_dicts(metadata_dict,
condition=FilterCondition.OR)
)
response = query_engine.query(query)
return response
vector_query_tool = FunctionTool.from_defaults(name=f"vector_tool_{name}",
fn=vector_query)
summary_index = SummaryIndex(nodes)
summary_query_engine = summary_index.as_query_engine(response_mode="tree_summarize",
se_async=True,)
summary_query_tool = QueryEngineTool.from_defaults(name=f"summary_tool_{name}",
query_engine=summary_query_engine,
description=("Use ONLY IF you want to get a holistic summary of the documents."
"DO NOT USE if you have specified questions over the documents."))
测试 LLM
response = llm.predict_and_call([vector_query_tool],
"Summarize the content in page number 2",
verbose=True)
=== Calling Function ===
Calling function: vector_tool_BERT_arxiv with args: {"query": "summarize content", "page_numbers": ["2"]}
=== Function Output ===
The content discusses the use of RAG models for knowledge-intensive generation tasks, such as MS-MARCO and Jeopardy question generation, showing that the models produce more factual, specific, and diverse responses compared to a BART baseline. The models also perform well in FEVER fact verification, achieving results close to state-of-the-art pipeline models. Additionally, the models demonstrate the ability to update their knowledge as the world changes by replacing the non-parametric memory.
def get_doc_tools(file_path:str,name:str)->str:
'''
从文档中获取向量查询和摘要查询工具
'''
documents = SimpleDirectoryReader(input_files = [file_path]).load_data()
print(f"length of nodes")
splitter = SentenceSplitter(chunk_size=1024,chunk_overlap=100)
nodes = splitter.get_nodes_from_documents(documents)
print(f"Length of nodes : {len(nodes)}")
vector_index = VectorStoreIndex(nodes,storage_context=storage_context)
vector_index.storage_context.vector_store.persist(persist_path="/content/chroma_db")
def vector_query(query:str,page_numbers:Optional[List[str]]=None)->str:
'''
在索引上执行向量搜索
query(str): 需要嵌入的查询字符串
page_numbers(List[str]): 要检索的页码列表,
如果要对所有页面执行向量搜索,则留空
'''
page_numbers = page_numbers or []
metadata_dict = [{"key":'page_label',"value":p} for p in page_numbers]
query_engine = vector_index.as_query_engine(similarity_top_k =2,
filters = MetadataFilters.from_dicts(metadata_dict,
condition=FilterCondition.OR)
)
response = query_engine.query(query)
return response
vector_query_tool = FunctionTool.from_defaults(name=f"vector_tool_{name}",
fn=vector_query)
summary_index = SummaryIndex(nodes)
summary_query_engine = summary_index.as_query_engine(response_mode="tree_summarize",
se_async=True,)
summary_query_tool = QueryEngineTool.from_defaults(name=f"summary_tool_{name}",
query_engine=summary_query_engine,
description=("Use ONLY IF you want to get a holistic summary of the documents."
"DO NOT USE if you have specified questions over the documents."))
return vector_query_tool,summary_query_tool
准备一个包含指定文档名称的输入列表
import os
root_path = "/content/data"
file_name = []
file_path = []
for files in os.listdir(root_path):
if file.endswith(".pdf"):
file_name.append(files.split(".")[0])
file_path.append(os.path.join(root_path,file))
print(file_name)
print(file_path)
['self_rag_arxiv', 'crag_arxiv', 'RAG_arxiv', '', 'BERT_arxiv']
['/content/data/BERT_arxiv.pdf',
/content/data/BERT_arxiv.pdf',
/content/data/BERT_arxiv.pdf',
/content/data/BERT_arxiv.pdf',
/content/data/BERT_arxiv.pdf']
注意:FunctionTool 期望工具名称的字符串匹配模式 ^[a-zA-Z0--9_-]+$
为每个文档生成向量工具和摘要工具
papers_to_tools_dict = {}
for name,filename in zip(file_name,file_path):
vector_query_tool,summary_query_tool = get_doc_tools(filename,name)
papers_to_tools_dict[name] = [vector_query_tool,summary_query_tool]
length of nodes
Length of nodes : 28
length of nodes
Length of nodes : 28
length of nodes
Length of nodes : 28
length of nodes
Length of nodes : 28
length of nodes
Length of nodes : 28
将工具放入一个扁平列表中
initial_tools = [t for f in file_name for t in papers_to_tools_dict[f]]
initial_tools
将太多工具选择塞入 LLM 提示会导致以下问题:
尤其是当文档数量很大时,工具可能不适合提示,因为我们将每个文档建模为单独的工具。
由于令牌数量的增加,成本和延迟会激增。
提示大纲也可能变得混乱,导致 LLM 无法按照指示执行。
这里的解决方案是在工具级别执行 RAG。为了执行此操作,我们将使用 Llama-Index 的 ObjectIndex 类。
ObjectIndex 类允许对任意 Python 对象进行索引。因此,它非常灵活,适用于各种用例。例如:
使用ObjectIndexObjectIndex
使用ObjectIndexObjectIndex
VectorStoreIndex 是 LlamaIndex 的一个关键组件,它有助于数据的存储和检索。它的工作原理是:
接受 Node 对象列表并从中构建索引。
使用不同的向量存储作为存储后端,增强应用程序的灵活性和可扩展性。
from llama_index.core import VectorStoreIndex
from llama_index.core.objects import ObjectIndex
obj_index = ObjectIndex.from_objects(initial_tools,index_cls=VectorStoreIndex)
将 ObjectIndex 设置为检索器
obj_retriever = obj_index.as_retriever(similarity_top_k=2)
tools = obj_retriever.retrieve("compare and contrast the papers self rag and corrective rag")
print(tools[0].metadata)
print(tools[1].metadata)
ToolMetadata(description='Use ONLY IF you want to get a holistic summary of the documents.DO NOT USE if you have specified questions over the documents.', name='summary_tool_self_rag_arxiv', fn_schema=<class 'llama_index.core.tools.types.DefaultToolFnSchema'>, return_direct=False)
ToolMetadata(description='vector_tool_self_rag_arxiv(query: str, page_numbers: Optional[List[str]] = None) -> str\n\nperform vector search over index on\nquery(str): query string needs to be embedded\npage_numbers(List[str]): list of page numbers to be retrieved,\nleave blank if we want to perform a vector search over all pages\n', name='vector_tool_self_rag_arxiv', fn_schema=<class 'pydantic.v1.main.vector_tool_self_rag_arxiv'>, return_direct=False)
from llama_index.core.agent import FunctionCallingAgentWorker
from llama_index.core.agent import AgentRunner
agent_worker = FunctionCallingAgentWorker.from_tools(tool_retriever=obj_retriever,
llm=llm,
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.""",
verbose=True)
agent = AgentRunner(agent_worker)
询问问题 1
response = agent.query("Compare and contrast self rag and crag.")
print(str(response))
Added user message to memory: Compare and contrast self rag and crag.
=== LLM Response ===
Sure, I'd be happy to help you understand the differences between Self RAG and CRAG, based on the functions provided to me.
Self RAG (Retrieval-Augmented Generation) is a method where the model generates a holistic summary of the documents provided as input. It'
s important to note that this method should only be used if you want a general summary of the documents, and not if you have specific questions over the documents.
On the other hand, CRAG (Contrastive Retrieval-Augmented Generation) is also a method for generating a holistic summary of the documents. The key difference between CRAG and Self RAG is not explicitly clear from the functions provided. However, the name suggests that CRAG might use a contrastive approach in its retrieval process, which could potentially lead to a summary that highlights the differences and similarities between the documents more effectively.
Again, it's crucial to remember that both of these methods should only be used for a holistic summary, and not for answering specific questions over the documents.
询问问题 2
response = agent.query("Summarize the paper corrective RAG.")
print(str(response))
Added user message to memory: Summarize the paper corrective RAG.
=== Calling Function ===
Calling function: summary_tool_RAG_arxiv with args: {"input": "corrective RAG"}
=== Function Output ===
The corrective RAG approach is a method used to address issues or errors in a system by categorizing them into three levels: Red, Amber, and Green. Red signifies critical problems that need immediate attention, Amber indicates issues that require monitoring or action in the near future, and Green represents no significant concerns. This approach helps prioritize and manage corrective actions effectively based on the severity of the identified issues.
=== LLM Response ===
The corrective RAG approach categorizes issues into Red, Amber, and Green levels to prioritize and manage corrective actions effectively based on severity. Red signifies critical problems needing immediate attention, Amber requires monitoring or action soon, and Green indicates no significant concerns.
assistant: The corrective RAG approach categorizes issues into Red, Amber, and Green levels to prioritize and manage corrective actions effectively based on severity. Red signifies critical problems needing immediate attention, Amber requires monitoring or action soon, and Green indicates no significant concerns.
与适用于跨少量文档进行简单查询的标准 RAG 管道不同,这种智能方法根据初始发现进行调整以增强进一步的数据检索。我们在此开发了一个自主研究智能体,增强了我们全面参与和分析数据的能力。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-06-30
本体论语义建设新思路,另类RAG来解决检索问题
2026-06-30
别把RAG当架构:Ontology(本体)才是Agent的业务世界
2026-06-29
PixelRAG:伯克利团队颠覆传统 RAG,用截图代替文本检索! 28 天狂揽 3000+ Star!
2026-06-29
腾讯WeKnora开源详解(三):检索引擎与生态集成
2026-06-29
腾讯开源WeKnora详解(二):知识库与对话核心能力
2026-06-29
RAG又被绕开了,MIT用MEMO给AI外挂记忆脑
2026-06-25
5.2k星星爆火开源!你的知识库迎来了史诗级更新,「像素级原生搜索」来了
2026-06-25
1.5K Star!网页提取神器 webclaw:让 AI 精准抓取网页核心内容!
2026-04-06
2026-04-27
2026-04-23
2026-04-02
2026-04-20
2026-04-09
2026-04-12
2026-04-22
2026-04-10
2026-05-14
2026-06-23
2026-06-23
2026-06-15
2026-06-10
2026-06-10
2026-05-20
2026-05-18
2026-05-11
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。