【Smol Course】8-智能体
wbfwonderful Lv4

Agent

AI 智能体(AI Agents)是一种自主系统,能够理解用户请求、将请求拆解为多个步骤,然后执行相应行动以完成任务。它们将语言模型与工具及外部功能相结合,从而与所处环境进行交互。本模章将讲解如何使用 smolagents 库构建高效的智能体,该库为创建强大的 AI 智能体提供了一个轻量级框架。

高效的智能体通常具备三种关键能力:

  • 检索能力:智能体需要能够从各种信息来源获取和使用相关信息。
  • 函数调用:这使得智能体能够在所处环境中采取具体行动。
  • 特定领域的知识和工具:这能让智能体可以执行诸如代码操作这类专业任务。

Building Agentic RAG Systems

自主性检索增强生成(RAG 或 Retrieval Augmented Generation)将有自主性的智能体的能力与知识检索能力相结合。传统的 RAG 系统只是利用大语言模型(LLM),基于检索到的信息来回答询问。而自主性 RAG 更进一步,允许系统智能地控制自身的检索和回答过程。传统 RAG 存在关键局限 —— 它仅执行单一的检索步骤,且依赖与用户询问的直接语义相似性,这可能会遗漏相关信息。自主性 RAG 通过让智能体能够自行制定搜索查询、评估结果,并根据需要执行多个检索步骤,来应对这些挑战。

Basic Retrieval with DuckDuckGo

从构建一个简单的代理开始,它可以使用 DuckDuckGo 搜索 web。该代理将能够通过检索相关信息和综合响应来回答问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel

# Initialize the search tool
search_tool = DuckDuckGoSearchTool()

# Initialize the model
model = HfApiModel()

agent = CodeAgent(
model = model,
tools=[search_tool]
)

# Example usage
response = agent.run(
"What are the latest developments in fusion energy?"
)
print(response)

上述代码将:

  • 分析查询以确定需要哪些信息
  • 使用 DuckDuckGo 搜索相关内容
  • 将检索到的信息合成为连贯的响应
  • 将交互存储在内存中以供将来参考

注意:

  • HfApiModel():创建一个基于 HuggingFace 模型 API 的语言模型实例。HfApiModel() 可能默认使用一个开源模型,实际部署时可配置模型名、token 等。
  • CodeAgent():构造一个 CodeAgent 实例,它拥有:
    • 一个语言模型(model),用于理解指令、生成文本;
    • 一个工具列表(tools),其中包括网络搜索功能。

Custom Knowledge Base Tool

对于特定领域的应用程序,我们通常希望将 web 搜索与我们自己的知识库结合起来。让我们创建一个可以查询技术文档矢量数据库的自定义工具。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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)
self.retriever = BM25Retriever.from_documents(
docs, k=10
)

def forward(self, query: str) -> str:
assert isinstance(query, str), "Your search query must be a string"

docs = self.retriever.invoke(
query,
)
return "\nRetrieved documents:\n" + "".join(
[
f"\n\n===== Document {str(i)} =====\n" + doc.page_content
for i, doc in enumerate(docs)
]
)

retriever_tool = RetrieverTool(docs_processed)
  • 上述代码继承自 smolagents.Tool,代表这是一个可供智能体 (Agent) 调用的工具。
  • 初始化方法中
    • 接收一个预处理好的文档列表 docs
    • BM25Retriever.from_documents(…):构建一个 BM25 检索器,从 docs 中构造倒排索引(用于基于关键词的相关性检索)。
  • forward() 方法:
    • 是工具的主入口,用于接收 query、执行检索并返回字符串格式的结果。
    • 调用 self.retriever.invoke(query) 返回 top-k 个文档。
    • 最后将每个文档内容拼接成字符串输出

Enhanced Retrieval Capabilities

当构建自主性检索增强生成(RAG)系统时,智能体还可以借鉴以下复杂策略:

  • 查询重构:智能体并非直接使用用户的原始查询,而是精心设计优化后的搜索词,使其与目标文档更匹配。
  • 多步检索:智能体可以执行多次搜索,依据初始检索结果来调整后续的查询。
  • 来源整合:整合来自多个渠道的信息,如网页搜索和本地文档。
  • 结果验证:在将检索到的内容纳入回复之前,会对其相关性和准确性进行分析。

Code Agents

代码代理通过自动化重复任务来加速开发,同时保持代码质量。他们擅长生成样板代码、执行系统重构以及通过静态分析识别潜在问题。代理将访问外部文档和存储库的检索功能与函数调用相结合,以执行创建文件或运行测试等具体操作。

在以下示例中,我们创建了一个代码智能体,它能够获取两个位置之间的运动时间。这里,我们使用 @tool 装饰器来定义一个可用作工具的自定义函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from smolagents import CodeAgent, HfApiModel, tool

@tool
def get_travel_duration(start_location: str, destination_location: str, departure_time: Optional[int] = None) -> str:
"""Gets the travel time in car between two places.

Args:
start_location: the place from which you start your ride
destination_location: the place of arrival
departure_time: the departure time, provide only a `datetime.datetime` if you want to specify this
"""
import googlemaps # All imports are placed within the function, to allow for sharing to Hub.
import os

gmaps = googlemaps.Client(os.getenv("GMAPS_API_KEY"))

if departure_time is None:
from datetime import datetime
departure_time = datetime(2025, 1, 6, 11, 0)

directions_result = gmaps.directions(
start_location,
destination_location,
mode="transit",
departure_time=departure_time
)
return directions_result[0]["legs"][0]["duration"]["text"]

agent = CodeAgent(tools=[get_travel_duration], model=HfApiModel(), additional_authorized_imports=["datetime"])

agent.run("Can you give me a nice one-day trip around Paris with a few locations and the times? Could be in the city or outside, but should fit in one day. I'm travelling only via public transportation.")

Custom Function Agents

自定义函数智能体是一类借助专门的函数调用(或称为 tools)来执行任务的人工智能智能体。与通用智能体不同,自定义函数智能体专注于通过直接与应用程序的逻辑相集成,为高级工作流程提供支持。例如,你可以将数据库查询、系统命令或任何自定义实用程序作为独立函数开放,以供智能体调用。