smolagents 文档
Agentic RAG
并获得增强的文档体验
开始使用
Agentic RAG
检索增强生成 (RAG) 简介
检索增强生成 (RAG) 将大型语言模型的能力与外部知识检索相结合,以产生更准确、真实和上下文相关的响应。RAG 的核心是“使用 LLM 回答用户查询,但答案基于从知识库中检索到的信息。”
为何使用 RAG?
与使用普通或微调 LLM 相比,RAG 具有显著优势:
- 事实依据:通过将响应锚定在检索到的事实中来减少幻觉。
- 领域专业化:无需模型再训练即可提供领域特定知识。
- 知识时效性:允许访问超出模型训练截止日期的信息。
- 透明度:能够引用生成内容的来源。
- 控制:对模型可以访问的信息提供精细控制。
传统 RAG 的局限性
尽管有其优点,但传统 RAG 方法面临一些挑战:
- 单次检索步骤:如果初始检索结果不佳,最终生成也会受到影响。
- 查询-文档不匹配:用户查询(通常是问题)可能与包含答案(通常是陈述)的文档不匹配。
- 有限推理:简单的 RAG 管道不允许进行多步推理或查询优化。
- 上下文窗口限制:检索到的文档必须在模型的上下文窗口内。
代理 RAG:一种更强大的方法
我们可以通过实现一个**代理 RAG** 系统来克服这些限制——本质上是一个配备检索功能的代理。这种方法将 RAG 从僵硬的管道转变为交互式、推理驱动的过程。
代理 RAG 的主要优势
配备检索工具的代理可以:
- ✅ 制定优化的查询:代理可以将用户问题转换为适合检索的查询。
- ✅ 执行多次检索:代理可以根据需要迭代检索信息。
- ✅ 对检索内容进行推理:代理可以分析、综合并从多个来源得出结论。
- ✅ 自我批评和完善:代理可以评估检索结果并调整其方法。
这种方法自然地实现了高级 RAG 技术:
构建代理 RAG 系统
让我们一步步构建一个完整的代理 RAG 系统。我们将创建一个代理,通过从 Hugging Face Transformers 库的文档中检索信息来回答有关该库的问题。
您可以跟着下面的代码片段进行操作,也可以查看 smolagents GitHub 仓库中的完整示例:examples/rag.py。
步骤 1:安装必要的依赖项
首先,我们需要安装必要的软件包:
pip install smolagents pandas langchain langchain-community sentence-transformers datasets python-dotenv rank_bm25 --upgrade
如果您打算使用 Hugging Face 的推理 API,则需要设置您的 API 令牌。
# Load environment variables (including HF_TOKEN)
from dotenv import load_dotenv
load_dotenv()
步骤 2:准备知识库
我们将使用包含 Hugging Face 文档的数据集,并将其准备好进行检索。
import datasets
from langchain.docstore.document import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.retrievers import BM25Retriever
# Load the Hugging Face documentation dataset
knowledge_base = datasets.load_dataset("m-ric/huggingface_doc", split="train")
# Filter to include only Transformers documentation
knowledge_base = knowledge_base.filter(lambda row: row["source"].startswith("huggingface/transformers"))
# Convert dataset entries to Document objects with metadata
source_docs = [
Document(page_content=doc["text"], metadata={"source": doc["source"].split("/")[1]})
for doc in knowledge_base
]
# Split documents into smaller chunks for better retrieval
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # Characters per chunk
chunk_overlap=50, # Overlap between chunks to maintain context
add_start_index=True,
strip_whitespace=True,
separators=["\n\n", "\n", ".", " ", ""], # Priority order for splitting
)
docs_processed = text_splitter.split_documents(source_docs)
print(f"Knowledge base prepared with {len(docs_processed)} document chunks")
步骤 3:创建检索器工具
现在,我们将创建一个自定义工具,我们的代理可以使用它从知识库中检索信息。
from smolagents import Tool
class RetrieverTool(Tool):
name = "retriever"
description = "Uses semantic search to retrieve the parts of transformers documentation that could be most relevant to answer your 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, docs, **kwargs):
super().__init__(**kwargs)
# Initialize the retriever with our processed documents
self.retriever = BM25Retriever.from_documents(
docs, k=10 # Return top 10 most relevant documents
)
def forward(self, query: str) -> str:
"""Execute the retrieval based on the provided query."""
assert isinstance(query, str), "Your search query must be a string"
# Retrieve relevant documents
docs = self.retriever.invoke(query)
# Format the retrieved documents for readability
return "\nRetrieved documents:\n" + "".join(
[
f"\n\n===== Document {str(i)} =====\n" + doc.page_content
for i, doc in enumerate(docs)
]
)
# Initialize our retriever tool with the processed documents
retriever_tool = RetrieverTool(docs_processed)
我们使用 BM25,一种词汇检索方法,以简化和提高速度。对于生产系统,您可能需要使用带有嵌入的语义搜索,以获得更好的检索质量。请查看 MTEB 排行榜以获取高质量的嵌入模型。
步骤 4:创建高级检索代理
现在,我们将创建一个可以使用我们的检索工具回答问题的代理。
from smolagents import InferenceClientModel, CodeAgent
# Initialize the agent with our retriever tool
agent = CodeAgent(
tools=[retriever_tool], # List of tools available to the agent
model=InferenceClientModel(), # Default model "Qwen/Qwen2.5-Coder-32B-Instruct"
max_steps=4, # Limit the number of reasoning steps
verbosity_level=2, # Show detailed agent reasoning
)
# To use a specific model, you can specify it like this:
# model=InferenceClientModel(model_id="meta-llama/Llama-3.3-70B-Instruct")
推理提供商允许访问数百个模型,这些模型由无服务器推理合作伙伴提供支持。支持的提供商列表可以在这里找到。
步骤 5:运行代理回答问题
让我们使用我们的代理来回答一个关于 Transformers 的问题。
# Ask a question that requires retrieving information
question = "For a transformers model training, which is slower, the forward or the backward pass?"
# Run the agent to get an answer
agent_output = agent.run(question)
# Display the final answer
print("\nFinal answer:")
print(agent_output)
代理 RAG 的实际应用
代理 RAG 系统可应用于各种用例:
- 技术文档辅助:帮助用户浏览复杂的技术文档。
- 研究论文分析:从科学论文中提取和综合信息。
- 法律文件审查:在法律文件中查找相关的判例和条款。
- 客户支持:根据产品文档和知识库回答问题。
- 教育辅导:根据教科书和学习材料提供解释。
结论
代理 RAG 代表了对传统 RAG 管道的重大进步。通过将 LLM 代理的推理能力与检索系统的事实依据相结合,我们可以构建更强大、更灵活、更准确的信息系统。
我们演示的方法:
- 克服了单步检索的局限性。
- 实现了与知识库更自然的交互。
- 通过自我批评和查询优化提供了一个持续改进的框架。
在构建自己的代理 RAG 系统时,请考虑尝试不同的检索方法、代理架构和知识来源,以找到最适合您特定用例的最佳配置。
< > 在 GitHub 上更新