智能体AgentAction执行动作的核心数据结构
目录
【智能体Agent】Action执行动作的核心数据结构
Action
from pydantic.v1 import BaseModel, Field
from typing import List, Optional, Dict, Any
class Action(BaseModel):
name: str = Field(description="Tool name")
args: Optional[Dict[str, Any]] = Field(description="Tool input arguments, containing arguments names and values")
def __str__(self):
ret = f"Action(name={self.name}"
if self.args:
for k, v in self.args.items():
ret += f", {k}={v}"
ret += ")"
return ret
Action
类及其相关代码的详细解析
一、类结构概览
from pydantic.v1 import BaseModel, Field
from typing import Optional, Dict, Any
class Action(BaseModel):
name: str = Field(description="工具名称")
args: Optional[Dict[str, Any]] = Field(description="工具输入参数,包含参数名和值")
def __str__(self):
ret = f"Action(name={self.name}"
if self.args:
for k, v in self.args.items():
ret += f", {k}={v}"
ret += ")"
return ret
二、核心设计解析
1. 数据建模 (Pydantic)
BaseModel继承 :
from pydantic.v1 import BaseModel class Action(BaseModel): ...
- 使用Pydantic v1(注意导入路径)实现数据验证
- 自动验证字段类型和约束条件(如
name
必须为字符串,args
必须为字典或None
)
字段定义 :
name: str = Field(description="工具名称") args: Optional[Dict[str, Any]] = Field(...)
name
字段:- 必须字段 :每个动作必须有工具名称
- 类型约束
:强制为
str
类型 - 元数据
:
description
用于生成API文档或LLM提示
args
字段:- 可选字段
:允许
None
值(某些工具不需要参数) - 动态结构
:
Dict[str, Any]
支持任意参数结构 - 类型安全 :字典键必须为字符串,值可为任意类型
- 可选字段
:允许
2. **运行时验证示例
# 合法实例
action1 = Action(name="search", args={"query": "Python"})
action2 = Action(name="finish") # args为None
# 非法实例(会抛出ValidationError)
Action(name=123) # 类型错误(name必须为str)
Action(name="calc", args="x=1") # 类型错误(args必须为字典)
三、字符串表示优化
def __str__(self):
ret = f"Action(name={self.name}"
if self.args:
for k, v in self.args.items():
ret += f", {k}={v}"
ret += ")"
return ret
输出示例 :
print(Action(name="search", args={"query": "AI", "limit": 5})) # 输出: Action(name=search, query=AI, limit=5)
设计目的 :
- 调试友好
:在日志或中间步骤(如
__format_thought_observation
)中清晰展示动作内容 - 可读性
:比默认的
Action(name='search', args={'query': 'AI'})
更简洁
- 调试友好
:在日志或中间步骤(如
四、在ReAct框架中的作用
1. 动作解析流程
LLM输出
解析器
Action对象
工具执行
自然语言+JSON混合文本
提取JSON → robust_parser.parse()
传递name和args
LLM输出
解析器
Action对象
工具执行
2. 关键交互点
输出解析 :
# 在ReActAgent.__step()中 json_action = self.__extract_json_action(response) action = self.robust_parser.parse(json_action)
- 确保LLM输出的JSON符合
Action
模型结构
- 确保LLM输出的JSON符合
工具执行 :
# 在ReActAgent.__exec_action()中 tool = self.__find_tool(action.name) observation = tool.run(action.args)
- 通过
name
匹配工具,传递args
参数
- 通过
五、设计亮点与注意事项
1. 版本选择
from pydantic.v1 import ... # 而非直接import pydantic
- 可能原因
:
- 兼容性:项目中其他组件依赖Pydantic v1
- 迁移成本:v2版本存在重大变更(如校验逻辑、字段声明方式)
2. 动态参数设计
args: Optional[Dict[str, Any]] # 而非预定义结构
优势 :
- 支持任意工具的参数结构
- 无需为每个工具创建子类
风险 :
- 类型安全需工具自行验证(如
tool.run()
内部需校验参数)
- 类型安全需工具自行验证(如
3. **字段描述的作用
Field(description="...")
- 实际应用
:
在LLM提示模板中,通过
format_instructions
自动生成格式说明:# ReActAgent.__init_prompt_templates() format_instructions=self.output_parser.get_format_instructions()
生成的提示示例:
请按以下格式响应: ```json { "name": "工具名称", "args": {"参数名": "值"} # 可选字段 }
六、扩展建议
1. 参数校验增强
# 可为特定工具定义参数模型
from pydantic.v1 import validator
class SearchAction(Action):
@validator('args')
def validate_args(cls, v):
if 'query' not in v:
raise ValueError("搜索工具必须包含query参数")
return v
- 适用场景 :对关键工具的参数做强制约束
2. 版本迁移准备
# 条件导入示例
try:
from pydantic.v1 import BaseModel
except ImportError:
from pydantic import BaseModel
- 前瞻性 :为过渡到Pydantic v2做准备
3. 日志优化
def __repr__(self):
return f"Action(name={self.name!r}, args={self.args!r})"
- 调试增强
:区分
__str__
(用户友好)和__repr__
(开发调试)
七、典型使用场景
场景1:LLM生成动作
# LLM输出示例
response = """
需要搜索AI相关新闻:
```json
{
"name": "web_search",
"args": {"query": "AI news 2023", "max_results": 5}
}
“”"
解析结果
action = Action(name=“web_search”, args={“query”: “AI news 2023”, “max_results”: 5})
#### 场景2:工具执行
```python
class SearchTool(BaseTool):
name = "web_search"
def run(self, args):
query = args["query"] # 依赖Action的参数结构正确
max_results = args.get("max_results", 10)
return search_api(query, max_results)
场景3:异常处理
# 当LLM返回错误格式时
invalid_json = '{"name": 123}' # name应为字符串
try:
action = Action.parse_raw(invalid_json)
except ValidationError as e:
print(e)
# 输出: 1 validation error for Action
# name -> str type expected
该
Action
类的设计充分体现了以下原则:
- 明确性 :通过类型注解明确数据结构
- 灵活性 :支持任意工具的参数格式
- 可调试性 :自定义字符串表示
- 兼容性 :适配LangChain的解析机制
这些特性使其成为连接LLM推理与工具执行的核心枢纽,在ReAct框架中起到承上启下的关键作用。