目录

智能体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 模型结构
  • 工具执行

    # 在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 类的设计充分体现了以下原则:

  1. 明确性 :通过类型注解明确数据结构
  2. 灵活性 :支持任意工具的参数格式
  3. 可调试性 :自定义字符串表示
  4. 兼容性 :适配LangChain的解析机制

这些特性使其成为连接LLM推理与工具执行的核心枢纽,在ReAct框架中起到承上启下的关键作用。