引言
工具系统本质上是 LLM能力的外延 ,让AI能够与真实世界交互,执行具体的操作任务。 在我之前的认知中,LLM只是输入一堆文字后,再吐出一堆文字的东西。但是有个工具后,事情变得不一样了。这让我们编写一个可以与外界充分交互的Agent成为可能。
LLM和工具如何互动
工具在最开始会注册给LLM,这样LLM在思考的时候,就会选择是返回文本啊,还是直接调用工具,在Trae-Agent中,百分百是调用工具。下面是LLM和工具在Agent内是如何交互的流程图: 在TraeAgent中,有更详细的一些交互细节。一是使用ReAct模式,使用循环思考和执行任务,这里的思考是指LLM的思考,执行任务是指调用工具;二是调用工具用到工具执行器,LLM思考一次可能想调用多个工具,这里工具执行器可以决定是并行调用还是顺序调用。
我们再看一个图,这个图忽略了循环思考和执行任务,而是专注体现LLM思考后,如果调用具体的工具如Bash和编辑工具的一些交互细节:
如何定义工具
一个工具要被大模型使用需要具备以下核心要素: 继承Tool基类
python
class MyTool(Tool):
def __init__(self, model_provider: str | None = None):
super().__init__(model_provider)
实现四个核心抽象方法
python
// 1.工具名称
@override
def get_name(self) -> str:
return "tool_name" # 返回工具的唯一标识符
// 2.工具描述
@override
def get_description(self) -> str:
return "工具的详细描述,告诉LLM这个工具的功能和使用场景"
// 3. 参数定义
@override
def get_parameters(self) -> list[ToolParameter]:
return [
ToolParameter(
name="param_name",
type="string", # 支持 string, boolean, integer, array, object 等
description="参数描述",
required=True, # 是否必需
enum=["option1", "option2"] # 可选的枚举值
)
]
// 4. 执行逻辑
@override
async def execute(self, arguments: ToolCallArguments) -> ToolExecResult:
# 从 arguments 中获取参数
param_value = arguments.get("param_name")
try:
# 执行具体的工具逻辑
result = do_something(param_value)
return ToolExecResult(output=result)
except Exception as e:
return ToolExecResult(error=str(e), error_code=-1)
我们实现了这样一个工具类后,Trae-Agent会将其转换成如下的json格式传给LLM。
json
// 不同供应商的具体格式会稍有不同,比如
// 1. OpenAI格式
{
"type": "function",
"function": {
"name": "tool_name",
"description": "工具描述",
"parameters": {
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "参数描述"
}
},
"required": ["param1"]
},
"strict": true
}
}
// 2. Anthropic格式
{
"name": "tool_name",
"description": "工具描述",
"input_schema": {
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "参数描述"
}
},
"required": ["param1"]
}
}
// 3.Google Gemini格式
{
"name": "tool_name",
"description": "工具描述",
"parameters": {
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "参数描述"
}
},
"required": ["param1"]
}
}
核心工具介绍
Sequential Thinking Tool
通过观察Trae-Agent的执行轨迹,LLM第一次回答就会调用每次调用Sequential Thinking Tool,然后每次调用其他工具后,紧接着都会调用一次Sequential Thinking Tool。可见它在Trae-Agent中有多重要,是最最核心的一个工具。
这个工具本质上是为大模型提供了一个 结构化的思维框架 ,让AI能够像人类一样进行深入、灵活的思考过程,特别适合处理需要多步推理和可能需要调整思路的复杂任务。
在最初的系统提示词中,就包含了如果使用Sequential Thinking Tool的指示,包括它自己的描述中,也说了LLM如何使用它的指示,这让LLM在思考后,会主动调用Sequential Thinking Tool来记录分步思考的内容。 它要记录的参数如下。
- thought : 当前思考步骤的内容
- next_thought_needed : 是否需要继续思考
- thought_number : 当前思考步骤编号
- total_thoughts : 预计总思考步骤数
- branch_from : 分支思考的起始点
Sequential Thinking Tool工具在使用过程中没有什么魔法,它就是一个记事本,记录了LLM思考的步骤和状态,提醒LLM当前的思考进度。真的的思考、任务拆分还都是LLM自己的功能。
Bash Tool
当LLM决定当下要进行一些系统命令或操作文件系统时,就会调用这个工具。
具体包括:文件操作(创建、删除、移动、查看)、系统信息查询、软件安装、代码编译运行、网络操作、进程管理等任何需要通过命令行完成的任务。
比如LLM决定启用一个本地服务,就是发出这样的tool_call:
json
"tool_calls": [
{
"call_id": "call_myl3wjt78qbvsr3xag5da98p",
"name": "bash",
"arguments": {
"command": "python3 -m http.server 8000 & sleep 5; curl http://localhost:8000/simple_page.html",
"restart": false
},
"id": null
}
]
Agent收到这样的tool_call后,就调用Bash Tool进行执行吧。
Edit Tool
使用场景
Edit Tool 在需要查看、创建或编辑文件时会被调用。
具体包括:
- 查看文件内容或目录结构
- 创建新文件
- 替换文件中的特定字符串
- 在文件指定位置插入新内容
可传递的参数
- command (必需)
- 类型:string
- 描述:要执行的命令
- 可选值: view , create , str_replace , insert
- path (必需)
- 类型:string
- 描述:文件或目录的绝对路径
- 示例: /repo/file.py 或 /repo
- file_text (create命令必需)
- 类型:string
- 描述:创建文件时的文件内容
- old_str (str_replace命令必需)
- 类型:string
- 描述:要替换的原始字符串,必须完全匹配
- new_str (str_replace可选,insert必需)
- 类型:string
- 描述:替换后的新字符串或要插入的内容
- insert_line (insert命令必需)
- 类型:integer
- 描述:插入位置的行号,新内容将插入到该行之后
- view_range (view命令可选)
- 类型:array of integers
- 描述:查看文件的行号范围
- 示例: [11, 12] 显示第11-12行, [10, -1] 显示第10行到文件末尾
具体调用示例
如下,调用了edit tool,命令是create,创建了一个html并存放在path所在的地方。
swift
"tool_calls": [
{
"call_id": "call_68kbda5pvv6butr72idzsftd",
"name": "str_replace_based_edit_tool",
"arguments": {
"command": "create",
"file_text": "<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <title>Simple Web Page</title>\n</head>\n<body>\n <h1>Hello, World!</h1>\n</body>\n</html>",
"insert_line": 0,
"new_str": "",
"old_str": "",
"path": "/Users/chenchen/study/ai/trae-agent/simple_page.html",
"view_range": []
},
"id": null
}
]
TaskDone Tool
在整个任务完成并经过验证后会被调用,用于标记任务已完成。Agent 调用完 task_done 工具后会退出执行循环并开始"休息"。
总结
大模型有了工具调用这个机制,相当于给一个只会说的脑袋安装了四肢,让大模型可以操作四肢进行行动了,大模型+工具组成的这个东西就叫agent,它更像是一个可以实际行动的机器人了。
通过今天的了解,可以看到Trea-Agent整体的设计和代码并不复杂,适合我们学习如何编写一个专用领域的Agent。