1.简介
高效的人工智能系统需要为大语言模型提供某种访问真实世界的方式,例如,获取外部信息的搜索工具,或者为了完成任务对某些程序采取行动的能力。LLM应该具备代理(agent)的能力,代理是LLM通往外界的门户,具备相应能力的系统也被称为agent。
近日,Huggingface开放了最新的agent框架,smolagents,旨在简化智能体的实现,只需要三行代码便可快速生成一个具备搜索能力的简易agent,如下图所示:

图1 agent示例
smolagents具备以下特性:
- 简洁性:agent的逻辑被精简到大约千行代码。
- 多种agent支持: 除了经典的ToolCallingAgent与先进的Multi-Agent能力,smolagents最核心的特性是CodeAgent,该实现允许智能体通过生成代码来执行动作。
- 广泛的LLM支持:smolagents支持Huggingface上托管的大模型,并基于LiteLLM支持OpenAI、Anthropic等多个大模型供应商。
2.CodeAgent
(1)为什么选择CodeAgent?
CodeAgent是smolagents的核心特性,以下将从智能体执行的角度讨论为什么CodeAgent是优异的选择。智能体可按照代理级别进行大致分类,如下表所示:
|
代理级别 |
特点 |
形式 |
示例模式 |
|
★☆☆ |
LLM 输出决定基本工作流程 |
Router |
|
|
★★☆ |
LLM 输出决定函数执行 |
Tool call |
|
|
★★★ |
LLM 输出控制工作流程与迭代 |
Multi-step Agent |
|
|
★★★ |
一个智能体工作流可以启动另一个智能体工作流 |
Multi-Agent |
|
图1 智能体代理级别
简单来说,路由(Router)智能体只起到决定工作流程的作用,比如判断本次查询是否需要开启网络搜索;工具调用(Tool Call)智能体可以调用预先设计的工具(函数形式),但执行是单步的;多步骤(Multi-Step)智能体可在单次查询连续执行多个工具;多智能体(Multi-Agent)则允许智能体之间进行调度,开启新的工作流。
工具的调用对于扩充智能体的能力至关重要,尤其在多步骤智能体中。通常,每个步骤LLM都可以编写一个动作,这个动作以调用外部工具的形式出现。目前常见的格式(OpenAI、Anthropic、langchain等均采用)是使用JSON来传递信息,大模型将动作输出为包含工具名称与参数的JSON,然后解析这些JSON来确定具体要执行哪个工具并传递哪些参数。
然而,多篇论文研究表明,让LLM以代码形式而非JSON解析来调用工具效果要更好。一种很自然的想法是,编程语言设计的目的就是为了成为表达计算机动作的最佳方式,如果JSON格式是大模型调用工具的最佳形式,那JSON也将是最主流的编程语言,但事实并非如此。显然,使用代码编写的动作可以提供更强的结构化和逻辑清晰度,使LLM能够更好地理解和生成复杂的操作序列,如下图所示:

图2 JSON工具调用与Code工具调用
可见,代码工具调用可以采取更少的动作、以更简洁的方式完成任务。CodeAgent还具备以下优势:
- 组合性:代码的可嵌套性带来动作嵌套的可能,并允许定义一组动作进行重用。
- 对象管理:可定义对象作为输出,传输受限更少。
- 通用性:代码相比JSON更具备通用性。
- LLM训练数据支持:大量的优质动作代码已包含在LLM的训练数据中,这意味着LLM天然具备很强的CodeAgent能力。
(2)CodeAgent实战
采用HfApiModel提供大模型,引入huggingface_hub的login方法,在使用token登录后(token可免费申请),可免费使用默认的Qwen-Coder-32B模型。
from huggingface_hub import login
login("your_hf_token")
我们为CodeAgent添加两个工具,分别是自定义的获取时间工具get_current_time_tool与获取huggingface给定任务下载量最高模型的工具model_download_tool。
from smolagents import CodeAgent, HfApiModel
from transformers import tool
from huggingface_hub import list_models
from datetime import datetime
# 定义一个工具,用于获取给定任务的下载量最高的模型
@tool
def model_download_tool(task: str) -> str:
"""
This is a tool that returns the most downloaded model of a given task on the Hugging Face Hub.
It returns the name of the checkpoint.
Args:
task: The task for which
"""
most_downloaded_model = next(iter(list_models(filter=task, sort="downloads", direction=-1)))
return most_downloaded_model.id
# 定义一个工具,用于获取当前时间
@tool
def get_current_time_tool() -> str:
"""
This is a tool that returns the current time.
It returns the current time in the format of "HH:MM:SS".
"""
return datetime.now().strftime("%H:%M:%S")
# 创建一个CodeAgent,并添加工具和模型
agent = CodeAgent(tools=[model_download_tool, get_current_time_tool], model=HfApiModel())
启动agent,分别输入问题查看决策过程:
①现在的时间是?
决策过程如下图。可见,智能体自行编写了调用工具的代码并执行。Step 0编写的代码采用print方法,未能捕获输出,因而开启Step 1重新编写调用代码,成功获取Final Answer。

图3 决策过程1
②Huggingface中,text-to-video任务下载量最高的模型是?

图4 决策过程2
如图,可见决策过程中,Step 0编写了工具调用代码,同样采取了print方法,尽管Out为None,但智能体读取执行logs在Step 1直接做出了回答。
3.其他类型agents
smolagents也支持常见的ToolCalling形式,采用ToolCallingAgent类实现,采取常用的JSON形式来调用工具:
from smolagents import ToolCallingAgent, PythonInterpreterTool, TOOL_CALLING_SYSTEM_PROMPT
# 调整系统提示词
modified_prompt = TOOL_CALLING_SYSTEM_PROMPT
agent = ToolCallingAgent(tools=[PythonInterpreterTool()], model=model, system_prompt=modified_prompt)
smolagents通过设置ManagedAgent来实现多智能体,如下所示:
from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool, ManagedAgent
model = HfApiModel()
web_agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=model)
# 将代理封装入ManagedAgent
managed_web_agent = ManagedAgent(
agent=web_agent,
name="web_search",
description="Runs web searches for you. Give it your query as an argument."
)
# 创建一个manager_agent,用于管理managed_web_agent
manager_agent = CodeAgent(
tools=[], model=model, managed_agents=[managed_web_agent]
)
manager_agent.run("Who is the CEO of Hugging Face?")
4.总结
smolagents提出的CodeAgent思路为智能体决策提供了新的方向,由大模型直接生成代码调用工具的形式带来了更高的执行效率与可扩展性。但是,由于调用工具完全是大模型自行实现,CodeAgent对大模型的能力、尤其是Code能力也提出了更高的要求,若模型能力较弱,则可能出现agent失败的情况。随着开源agent框架逐渐涌现,结合实际应用场景,选择业务适应最佳的agent实现方案才是实现AIGC的应对之策。

被折叠的 条评论
为什么被折叠?



