开源 AI 食谱文档
多智能体 RAG 系统 🤖🤝🤖
并获得增强的文档体验
开始使用
多智能体 RAG 系统 🤖🤝🤖
🚨 注意:本教程是高级教程。在深入研究之前,您应该对以下食谱中讨论的概念有扎实的理解
在本笔记本中,我们将创建一个多智能体 RAG 系统,一个多个智能体协同工作以检索和生成信息的系统,结合了基于检索的系统和 生成模型的优势。
什么是多智能体 RAG 系统?🤔
多智能体检索增强生成 (RAG) 系统由多个智能体组成,这些智能体协同工作以执行复杂任务。检索智能体检索相关文档或信息,而生成智能体综合这些信息以生成有意义的输出。有一个管理智能体负责协调系统,并根据用户输入为任务选择最合适的智能体。
此食谱的最初想法来自这篇文章。您可以在那里找到更多详细信息。
下面,您可以找到我们将构建的架构。
1. 安装依赖项
首先,让我们安装依赖项
!pip install -q smolagents
!pip install markdownify duckduckgo-search spaces gradio-tools langchain langchain-community langchain-huggingface faiss-cpu --upgrade -q
让我们登录以便调用 HF Inference API
from huggingface_hub import notebook_login
notebook_login()
2. 让我们创建我们的多智能体 RAG 系统
在本节中,我们将创建 RAG 系统中存在的每个智能体。
我们将拥有由中央智能体管理的 3 个智能体(有关详细信息,请参阅图像)
- 🕵💬 网络搜索智能体:它将包含
DuckDuckGoSearchTool
工具和VisitWebpageTool
。如您所见,每个智能体可能包含一个工具列表。 - 🕵💬 检索器智能体:它将包含两个工具,用于从两个不同的知识库检索信息。
- 🕵💬 图像生成智能体:除了图像生成工具外,它还将包含一个提示生成器工具。
💡 除了这些智能体之外,中央/协调智能体还将有权访问 代码解释器工具 以执行代码。
我们将使用 Qwen/Qwen2.5-72B-Instruct 作为每个组件的 LLM,它将通过 Inference API 访问。根据智能体的不同,可能会使用不同的 LLM 模型。
注意: Inference API 基于各种标准托管模型,并且部署的模型可能会在没有事先通知的情况下进行更新或替换。在此处了解更多信息here。
from smolagents import HfApiModel
model_id = "Qwen/Qwen2.5-72B-Instruct"
model = HfApiModel(model_id)
让我们深入了解每个智能体的详细信息!
2.1 网络搜索智能体 🔍
网络搜索智能体 将利用 DuckDuckGoSearchTool
搜索网络并收集相关信息。此工具充当搜索引擎,根据指定的关键字查询结果。
为了使搜索结果可操作,我们还需要智能体访问 DuckDuckGo 检索到的网页。这可以通过使用内置的 VisitWebpageTool
来实现。
让我们探索如何设置它并将其集成到我们的系统中!
以下代码来自最初的 让多个智能体在多智能体层级结构中协作 🤖🤝🤖 食谱,因此请参阅它以获取更多详细信息。
2.1.1 构建我们的多工具网络智能体 🤖
现在我们已经设置了基本搜索和网页工具,让我们构建我们的 多工具网络智能体。此智能体将结合多种工具来执行更复杂的任务,从而利用 ToolCallingAgent
的功能。
ToolCallingAgent
特别适合网络搜索任务,因为它的 JSON 操作公式仅需要简单的参数,并且可以在单操作的顺序链中无缝工作。这使其成为我们需要在网络上搜索相关信息并从特定网页检索详细内容的场景的绝佳选择。相比之下,CodeAgent
操作公式更适合涉及大量或并行工具调用的场景。
通过集成多个工具,我们可以确保我们的智能体以复杂而高效的方式与网络交互。
让我们深入了解如何设置它并将其集成到我们的系统中!
from smolagents import CodeAgent, ToolCallingAgent, ManagedAgent, DuckDuckGoSearchTool, VisitWebpageTool
web_agent = ToolCallingAgent(tools=[DuckDuckGoSearchTool(), VisitWebpageTool()], model=model)
现在我们有了第一个智能体,让我们将其包装为 ManagedAgent
,以便中央智能体可以使用它。
managed_web_agent = ManagedAgent(
agent=web_agent,
name="search_agent",
description="Runs web searches for you. Give it your query as an argument.",
)
2.2 检索器智能体 🤖🔍
我们的多智能体系统中的第二个智能体是 检索器智能体。此智能体负责从不同来源收集相关信息。为了实现这一目标,它将利用两个工具,这两个工具从两个独立的知识库检索数据。
我们将重用之前在其他 RAG 食谱中使用过的两个数据源,这将使检索器能够有效地收集信息以进行进一步处理。
通过利用这些工具,检索器智能体可以访问不同的数据集,确保在传递给系统的下一步之前全面收集相关信息。
让我们探索如何设置检索器并将其集成到我们的多智能体系统中!
2.2.1 HF 文档检索器工具 📚
第一个检索器工具来自 智能体 RAG:通过查询重构和自查询增强您的 RAG!🚀 食谱。
对于此检索器,我们将使用一个数据集,该数据集包含各种 huggingface
包的文档页面汇编,所有文档页面都存储为 markdown 文件。此数据集充当检索器智能体的知识库,用于搜索和检索相关文档。
为了使我们的智能体可以轻松访问此数据集,我们将
- 下载数据集:我们将首先获取 markdown 文档。
- 嵌入数据:然后,我们将使用 FAISS 向量存储 将文档转换为嵌入,以实现高效的相似性搜索。
通过这样做,检索器工具可以根据搜索查询快速访问相关文档片段,从而使智能体能够提供准确而详细的信息。
让我们继续设置工具来处理文档检索!
import datasets
knowledge_base = datasets.load_dataset("m-ric/huggingface_doc", split="train")
from tqdm import tqdm
from transformers import AutoTokenizer
from langchain.docstore.document import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores.utils import DistanceStrategy
source_docs = [
Document(page_content=doc["text"], metadata={"source": doc["source"].split("/")[1]}) for doc in knowledge_base
]
text_splitter = RecursiveCharacterTextSplitter.from_huggingface_tokenizer(
AutoTokenizer.from_pretrained("thenlper/gte-small"),
chunk_size=200,
chunk_overlap=20,
add_start_index=True,
strip_whitespace=True,
separators=["\n\n", "\n", ".", " ", ""],
)
# Split docs and keep only unique ones
print("Splitting documents...")
docs_processed = []
unique_texts = {}
for doc in tqdm(source_docs):
new_docs = text_splitter.split_documents([doc])
for new_doc in new_docs:
if new_doc.page_content not in unique_texts:
unique_texts[new_doc.page_content] = True
docs_processed.append(new_doc)
print("Embedding documents...")
embedding_model = HuggingFaceEmbeddings(model_name="thenlper/gte-small")
huggingface_doc_vector_db = FAISS.from_documents(
documents=docs_processed,
embedding=embedding_model,
distance_strategy=DistanceStrategy.COSINE,
)
现在我们已经将文档嵌入到 FAISS 中,让我们创建 RetrieverTool。此工具将查询 FAISS 向量存储,以检索与用户查询最相关的文档。
这将允许检索器智能体在被查询时访问并提供相关文档。
from smolagents import Tool
from langchain_core.vectorstores import VectorStore
class RetrieverTool(Tool):
name = "retriever"
description = "Using semantic similarity, retrieves some documents from the knowledge base that have the closest embeddings to the input query."
inputs = {
"query": {
"type": "string",
"description": "The query to perform. This should be semantically close to your target documents. Use the affirmative form rather than a question.",
}
}
output_type = "string"
def __init__(self, vectordb: VectorStore, **kwargs):
super().__init__(**kwargs)
self.vectordb = vectordb
def forward(self, query: str) -> str:
assert isinstance(query, str), "Your search query must be a string"
docs = self.vectordb.similarity_search(
query,
k=7,
)
return "\nRetrieved documents:\n" + "".join(
[f"===== Document {str(i)} =====\n" + doc.page_content for i, doc in enumerate(docs)]
)
huggingface_doc_retriever_tool = RetrieverTool(huggingface_doc_vector_db)
2.2.2 PEFT 问题检索器工具
对于第二个检索器,我们将使用 PEFT 问题 作为数据源,就像 使用 Hugging Face Zephyr 和 LangChain 的 GitHub 问题的简单 RAG 中一样。
同样,以下代码来自该食谱,因此请参阅它以获取更多详细信息!
from google.colab import userdata
GITHUB_ACCESS_TOKEN = userdata.get("GITHUB_PERSONAL_TOKEN")
from langchain.document_loaders import GitHubIssuesLoader
loader = GitHubIssuesLoader(repo="huggingface/peft", access_token=GITHUB_ACCESS_TOKEN, include_prs=False, state="all")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=30)
chunked_docs = splitter.split_documents(docs)
peft_issues_vector_db = FAISS.from_documents(chunked_docs, embedding=embedding_model)
现在让我们使用相同的 RetrieverTool
生成第二个检索器工具。
peft_issues_retriever_tool = RetrieverTool(peft_issues_vector_db)
2.2.3 构建检索器智能体
现在我们已经创建了两个检索器工具,是时候构建 检索器智能体 了。此智能体将管理这两个工具,并根据用户查询检索相关信息。
我们将使用 ManagedAgent
来集成这些工具,并将智能体传递给中央智能体进行协调。
retriever_agent = ToolCallingAgent(
tools=[huggingface_doc_retriever_tool, peft_issues_retriever_tool], model=model, max_iterations=4, verbose=2
)
managed_retriever_agent = ManagedAgent(
agent=retriever_agent,
name="retriever_agent",
description="Retrieves documents from the knowledge base for you that are close to the input query. Give it your query as an argument. The knowledge base includes Hugging Face documentation and PEFT issues.",
)
2.3 图像生成智能体 🎨
我们系统中的第三个智能体是 图像生成智能体。此智能体将具有两个工具:一个用于优化用户查询,另一个用于根据查询生成图像。在本例中,我们将使用 CodeAgent
而不是 ReactAgent
,因为可以在一次性执行一组操作。
您可以在 智能体,功能增强 - 多智能体、外部工具等 文档中找到有关图像生成智能体的更多详细信息。
让我们深入了解这些工具如何协同工作以根据用户输入生成图像!
from transformers import load_tool, CodeAgent
prompt_generator_tool = Tool.from_space(
"sergiopaniego/Promptist", name="generator_tool", description="Optimizes user input into model-preferred prompts"
)
image_generation_tool = load_tool("m-ric/text-to-image", trust_remote_code=True)
image_generation_agent = CodeAgent(tools=[prompt_generator_tool, image_generation_tool], model=model)
🖼 同样,我们使用 ManagedAgent
来告诉中央智能体它可以管理它。此外,我们还包含了一个 additional_prompting
参数,以确保智能体返回生成的图像,而不仅仅是文本描述。
managed_image_generation_agent = ManagedAgent(
agent=image_generation_agent,
name="image_generation_agent",
description="Generates images from text prompts. Give it your prompt as an argument.",
additional_prompting="\n\nYour final answer MUST BE only the generated image location.",
)
3. 让我们添加通用智能体管理器来协调系统
中央智能体管理器 将协调智能体之间的任务。它将
- 接收用户输入 并决定哪个智能体(网络搜索、检索器、图像生成)处理它。
- 根据用户查询将任务委派 给适当的智能体。
- 收集和综合 来自智能体的结果。
- 将最终输出返回 给用户。
我们包含了我们开发的所有智能体作为 managed_agents
,并在 additional_authorized_imports
下为代码执行器添加任何必要的导入。
manager_agent = CodeAgent(
tools=[],
model=model,
managed_agents=[managed_web_agent, managed_retriever_agent, managed_image_generation_agent],
additional_authorized_imports=["time", "datetime", "PIL"],
)
现在一切都已设置好,让我们测试多智能体 RAG 系统的性能!
为此,我们将提供一些示例查询,并观察系统如何在智能体之间委派任务、处理信息并返回最终结果。
这将帮助我们了解智能体协同工作的效率和有效性,并在必要时确定优化领域。
让我们继续运行一些测试!
3.1 尝试触发搜索智能体的示例
manager_agent.run("How many years ago was Stripe founded?")
3.2 尝试触发图像生成器智能体的示例
result = manager_agent.run(
"Improve this prompt, then generate an image of it.", prompt="A rabbit wearing a space suit"
)
>>> from IPython.display import Image, display
>>> display(Image(filename=result))
3.3 尝试触发 HF 文档知识库的检索器智能体的示例
manager_agent.run("How can I push a model to the Hub?")
3.4 尝试触发 PEFT 问题知识库的检索器智能体的示例
manager_agent.run("How do you combine multiple adapters in peft?")
🏁 最终想法
我们已成功构建了一个多智能体 RAG 系统,该系统集成了网络搜索、文档检索和图像生成智能体,所有这些智能体都由中央智能体管理器协调。此架构实现了无缝的任务委派、高效的处理以及处理各种用户查询的灵活性。
🔍 探索更多
< > 在 GitHub 上更新