2026-07-14 21:28:52 +08:00
2026-07-14 21:28:52 +08:00
2026-07-14 21:00:40 +08:00

个人模块 README — B3

模块 B3:说明生成与工具调用模块 | 负责人:周炜伦 20235904


1. 模块概述

1.1 模块名称

B3 — 说明生成与工具调用模块 (Tool Layer: Schema & Execution)

1.2 模块说明

B3 是 Skill(B2) 与 LLM(B4) 之间的桥梁层,承担两个核心职责:

  1. 生成工具描述(tools_schema):将 tools.yaml 中的工具定义转换为 OpenAI Function Calling 格式的 JSON Schema,让 LLM 知道"有哪些工具、每个工具需要什么参数"
  2. 执行工具调用(execute_tool_calls):接收 B4 返回的 tool_calls,校验工具名和参数合法性,调用 B2 的 Skill 函数,将结果封装为标准 ToolMessage 返回给 B1
B3 的核心定位:
                    ┌──────────┐
    tools.yaml  ──► │   B3     │ ──► tools_schema (给 LLM 看)
                    │          │
    tool_calls  ──► │ Tool     │ ──► ToolMessage (给 B1)
                    │ Layer    │
                    └────┬─────┘
                         │ 调用 B2 Skill
                         ▼
                    ┌──────────┐
                    │   B2     │
                    └──────────┘

1.3 完成情况概览

类型 完成情况
基础要求 ✅ 全部完成:读取 tools.yaml 生成 tools_schema(8个工具/含name+description+parameters+required+returns)、校验 tool_calls 并执行 B2 Skill、输出 JSON 格式记录
进阶要求 ✅ 5 项全部完成:自动从 Python 函数签名生成 schema、可恢复错误重试(指数退避)、tool_call 结果缓存(SHA256 键+TTL)、批量统计压测(~110条覆盖全部工具)、不同 schema 详尽度对比实验
可独立运行的演示 ✅ CLI 独立运行 + Web Demo(端口 8082)+ 统计压测按钮
与团队系统集成情况 ✅ 通过 get_tools_schema() 和 execute_tool_calls() 被 B1 调用,是 B1 Agent Loop 中不可或缺的工具调用环节

2. 环境、模型与数据依赖

2.1 运行环境

项目 要求
Python 版本 3.10
必要依赖 PyYAML
是否需要模型 不需要(B3 只做配置解析和参数校验)
是否需要 GPU 不需要
是否需要外部数据集 不需要

2.2 模型依赖

B3 不加载模型。它只做配置解析、参数校验和函数调用调度。

2.3 数据集或样例数据依赖

数据或文件 来源 项目内相对路径 用途
configs/tools.yaml 项目自带 agent/configs/ 工具定义配置(toolsets + 每个工具的 module/function/description/parameters/returns)
data/messages/ai_message_with_tool_calls.json 项目自带 agent/data/messages/ 模拟 B4 返回的 tool_calls(用于独立演示)
b3_tool_call_*.json 项目自带 agent/data/messages/ 异常测试样例(unknown_tool/missing_required/safe_exec)

2.4 安装步骤

conda create -n b3_env python=3.10 -y
conda activate b3_env
cd agent
pip install -r requirements.txt

3. 文件结构与接口边界

3.1 文件结构

agent/
├── code/
│   ├── b3_tool_layer.py         # 核心:Schema生成+工具执行(324行)
│   ├── b3_cache.py              # 进阶:tool_call结果缓存(SHA256键+TTL,70行)
│   ├── b3_stats.py              # 进阶:工具调用统计(次数/成功率/平均耗时,101行)
│   └── b3_schema_generator.py   # 进阶:从Python函数签名自动生成Schema(145行)
├── demo/
│   ├── b3_demo_server.py        # Web Demo 服务器(端口 8082)+ 统计压测API
│   └── templates/b3_index.html  # Web Demo 前端(含统计压测按钮)
├── experiments/
│   ├── compare_tool_schemas.py      # 不同Schema详尽度对比实验
│   └── compare_schema_injection.py  # 不同Schema注入位置对比实验
├── configs/
│   └── tools.yaml               # 工具定义配置文件
└── B3_VERIFICATION.md           # 模块验证说明书

3.2 接口边界

类型 来源 / 去向 数据格式 说明
输入 B1 → get_tools_schema() 函数调用(tools_config路径 + toolset名) B1 在 Agent Loop 开始时调用一次
输入 B1 → execute_tool_calls() 函数调用(tool_calls列表 + tools_config) B1 在每次 B4 返回 tool_calls 时调用
输出 get_tools_schema() → B1 list[dict](OpenAI Function Calling 格式) 传给 B4 做工具绑定
输出 execute_tool_calls() → B1 list[dict](ToolMessage 列表) 追加到 messages 后再次调用 B4
调用 B2 B3 → run_skill() Python 函数调用 通过 B2 的 SKILL_MODULES 注册表

4. 基础要求实现与演示

4.1 基础功能说明

功能 入口函数 说明
导出 Schema get_tools_schema() 读取 tools.yaml → 按 toolset 筛选 → 生成 OpenAI 格式的 JSON Schema 列表
执行工具调用 execute_tool_calls() 接收 tool_calls → 校验工具名 → 校验参数类型/必填 → 调用 B2 → 封装 ToolMessage

4.2 基础功能实现路径

文件 / 函数 作用
b3_tool_layer.py:_load_tools_config() 读取 tools.yaml,校验 tools 和 toolsets 两个顶层 key
b3_tool_layer.py:_resolve_toolset() 从 toolsets 中取出指定 toolset 的工具名列表
b3_tool_layer.py:_parameter_schema() 将 tools.yaml 中的参数定义转为 JSON Schema(type/properties/required/additionalProperties)
b3_tool_layer.py:get_tools_schema() 遍历工具名,为每个工具生成 OpenAI 格式的 schema 记录
b3_tool_layer.py:_validate_args() 校验参数:必填项检查 + 类型检查 + 未知参数检查
b3_tool_layer.py:execute_tool_calls() 主执行流程:标准化 → 缓存查 → 校验 → B2 调用 → ToolMessage 封装

4.3 基础功能演示命令

cd agent/code

# 导出 Schema
python b3_tool_layer.py --tools_config ../configs/tools.yaml \
  --toolset basic_tools --export_schema --outdir ../outputs/B3_tools

# 执行工具调用
python b3_tool_layer.py --tools_config ../configs/tools.yaml \
  --toolset basic_tools --tool_calls ../data/messages/ai_message_with_tool_calls.json \
  --execute --outdir ../outputs/B3_tools

观察要点:

  • tools_schema.json 包含 8 个工具的完整定义
  • tool_messages.json 中每个 ToolMessage 的 status=success
  • B3 从 tools.yaml 读取 data_root 配置,自动注入给 B2

4.4 基础功能输出格式

输出文件 格式 说明
tools_schema.json JSON 数组 8 个工具的 OpenAI Function Calling 格式描述
tool_schema_report.json JSON 对象 toolset、tool_count、tools 名称列表
tool_messages.json JSON 数组 本次执行的 ToolMessage 列表
tool_call_log.jsonl JSONL 每个 tool_call 的完整执行记录

5. 进阶要求实现与演示

5.1 选择的进阶要求

进阶要求 是否完成 对应文件 简要说明
进阶1:自动 Schema 生成 ✅ b3_schema_generator.py 从 Python 函数 type hints + docstring 自动推断参数类型和描述
进阶2:可恢复错误重试 ✅ b3_tool_layer.py:execute_tool_calls() 指数退避重试(TimeoutError/ConnectionError 等),input/fatal 类不重试
进阶3:Tool Call 缓存 ✅ b3_cache.py SHA256 键 + TTL 过期 + 磁盘持久化
进阶4:批量统计压测 ✅ b3_stats.py + b3_demo_server.py 自动生成 ~110 条 tool_calls 覆盖全部 8 个工具,含正常/边界/错误场景
进阶5:Schema 对比实验 ✅ experiments/compare_tool_schemas.py minimal/standard/detailed 三种详尽度对比

5.2 进阶1:自动 Schema 生成

b3_schema_generator.py 无需手写 tools.yaml,直接从 Python 函数签名生成 Schema:

  • 参数类型:通过 inspect.signature() + type hints 推断(str→string, int→integer, bool→boolean 等)
  • 参数描述:从 docstring 的 Args: 段解析
  • 必填参数:默认值 <Parameter.empty> 的即为必填
# 全部 8 个工具
python b3_schema_generator.py --all --outdir ../outputs/B3_tools/auto_schema

# 单个工具
python b3_schema_generator.py --module skills.calculator --function calculator --outdir ../outputs/B3_tools/auto_single

5.3 进阶2:可恢复错误重试

execute_tool_calls() 支持 --retry 参数:

# 只在遇到可恢复错误时重试(TimeoutError/ConnectionError等)
# 指数退避:delay = retry_delay * (2^attempt)
# 不可恢复错误(input/fatal 类)直接返回,不浪费重试
python b3_tool_layer.py --tools_config ../configs/tools.yaml \
  --toolset basic_tools --tool_calls ../data/messages/ai_message_with_tool_calls.json \
  --execute --outdir ../outputs/B3_tools/retry_test --retry 3 --retry_delay 0.5

5.4 进阶3:Tool Call 结果缓存

b3_cache.py 实现基于 SHA256 的缓存:

  • 键:SHA256(tool_name + sorted(args))[:16]
  • TTL:默认 300 秒,过期自动删除
  • 存储:{outdir}/.tool_cache/{hash}.json
# 第一次:cache miss → 执行 Skill → 缓存
python b3_tool_layer.py --tools_config ../configs/tools.yaml \
  --toolset basic_tools --tool_calls ../data/messages/ai_message_with_tool_calls.json \
  --execute --outdir ../outputs/B3_tools/cache_test --cache

# 第二次:cache hit → 直接返回缓存
python b3_tool_layer.py --tools_config ../configs/tools.yaml \
  --toolset basic_tools --tool_calls ../data/messages/ai_message_with_tool_calls.json \
  --execute --outdir ../outputs/B3_tools/cache_test --cache

5.5 进阶4:批量统计压测

点击 B3 前端 "📊 统计压测" 按钮,后端自动生成 ~110 条 tool_calls,覆盖全部 8 个工具的正常/边界/错误场景:

工具 用例数 覆盖
calculator 20 加减乘除、幂运算、括号、浮点、取模
file_reader 22 3 个正常文件 × 多次 + 不存在文件 + 非 txt 文件
local_file_search 16 15 个关键词 + 不存在目录
table_analyzer 6 CSV 分析 × 5 + 不存在文件
format_converter 11 JSON × 5 + Markdown × 5 + 空文本异常
safe_executor 17 列表/字符串/循环/类型转换 + import 违规 + 语法错误
read_and_convert 5 JSON 转换 × 3 + Markdown 转换 × 2
search_and_analyze 8 正常 × 5 + 错误目录 + 无CSV目录 + 不匹配关键词

执行完后返回完整的 tool_stats_report.md:

# Tool Call Statistics Report
| Tool | Calls | Success | Error | Rate | Avg(ms) | Min(ms) | Max(ms) |
|------|-------|---------|-------|------|---------|---------|---------|
| calculator | 20 | 20 | 0 | 100.0% | 0.15 | 0.03 | 0.52 |
| file_reader | 22 | 20 | 2 | 90.9% | 0.51 | 0.21 | 1.23 |
...

5.6 进阶5:Schema 对比实验

experiments/compare_tool_schemas.py 生成三种详尽程度的 Schema 并对比:

Level 做法 Schema 大小
minimal 去掉所有 description 和 x-returns ~2540 chars
standard 原样保留 tools.yaml 定义 ~7728 chars
detailed 追加类型约束和额外说明 ~8403 chars
cd experiments
python compare_tool_schemas.py --outdir ../outputs/exp_schema_compare

6. 与团队系统的集成说明

B3 通过两个公开函数被 B1 调用:

# B1 调用位置:b1_agent_runtime.py 第370行
from b3_tool_layer import execute_tool_calls, get_tools_schema

# 第381行:获取工具描述
tools_schema = get_tools_schema(str(tools_file), runtime["toolset"], str(output_dir))

# 第533-535行:执行工具调用
tool_messages = execute_tool_calls(
    tool_calls, str(tools_file), runtime["toolset"], str(output_dir),
    use_cache=True, track_stats=True, retry=1,
)

B3 内部通过 b2_run_skill_fn() 调用 B2 的 Skill 函数。tools.yaml 中的 data_root 配置(../data)被 B3 解析后注入给 B2,确保 B2 的 resolve_data_path() 能找到正确的数据目录。


7. 已知问题与后续改进

问题 当前原因 后续改进
自动 Schema 生成无 x-returns 详情 仅从函数签名推断,无法获取返回值结构 可解析 docstring 的 Returns 段
缓存仅基于 name+args 不区分 data_root,不同数据目录下同参数调用会命中同一缓存 可将 data_root 纳入缓存键
统计压测需手动触发 前端按钮调用,非自动 可添加每次 B1 调用后自动汇总的统计
S
Description
No description provided
Readme
60 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 74.2%
HTML 25.8%