1 line
63 KiB
JSON
1 line
63 KiB
JSON
{"repo": "aws-samples/sample-bedrock-api-proxy", "files": {"docs/blog_ptc_reverse_engineering.md": {"b296b89f7fe3acd42f18539c182bcda400e7ffef": {"t": 1785747144.9391737, "n": 21012, "h": "f32f0e6dcf73a1f9", "c": "# Agent工具调用新范式:逆向工程 Anthropic Claude Programmatic Tool Calling 功能\n\n> 本文深入解析 Anthropic 最新发布的 Programmatic Tool Calling (PTC) 技术,并介绍如何通过自托管 Docker Sandbox 方案实现完全兼容的 PTC 功能,让任意大模型都能享受这一革命性的工具调用范式。\n\n## 一、背景:传统 Tool Use 的瓶颈\n\n在构建 AI Agent 时,工具调用(Tool Use / Function Calling)是连接模型与外部世界的桥梁。然而,传统的工具调用模式存在明显的效率瓶颈:\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│ 传统 Tool Use 流程 │\n├─────────────────────────────────────────────────────────────┤\n│ 用户请求 → 模型推理 → 工具调用1 → 模型推理 → 工具调用2 │\n│ → 模型推理 → 工具调用3 → 模型推理 → 最终响应 │\n│ │\n│ 问题:N 次工具调用 = N+1 次模型推理 │\n│ 所有中间结果都进入上下文,消耗大量 Token │\n└─────────────────────────────────────────────────────────────┘\n```\n\n以一个典型的业务场景为例:**\"查询工程团队哪些成员的 Q3 差旅费用超标?\"**\n\n传统方式需要:\n1. 获取团队成员列表 → 20 人\n2. 为每人获取费用记录 → 20 次工具调用,每次返回 50-100 条明细\n3. 获取预算标准 → 多次调用\n4. **所有 2000+ 条费用明细都进入模型上下文**\n5. 模型手动汇总、比对、筛选\n\n这种方式导致:\n- **Token 消耗巨大**:中间数据全部进入上下文\n- **延迟累积**:每次工具调用都需要一次完整的模型推理\n- **准确性下降**:模型需要在自然语言中处理大量数据,容易出错\n\n## 二、Programmatic Tool Calling:代码编排工具调用\n\n2024 年 11 月,Anthropic 发布了 **Programmatic Tool Calling (PTC)** 功能,从根本上改变了工具调用范式。\n\n### 2.1 核心思想\n\nPTC 的核心思想是:**让模型生成 Python 代码来编排工具调用,而不是逐个请求工具**。\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│ Programmatic Tool Calling 流程 │\n├─────────────────────────────────────────────────────────────┤\n│ 用户请求 → 模型生成 Python 代码 → 沙箱执行代码 │\n│ ↓ │\n│ 循环调用工具1,2,3... │\n│ 数据处理、过滤、聚合 │\n│ ↓ │\n│ 返回 print() 输出 │\n│ → 模型基于摘要输出给出最终响应 │\n│ │\n│ 优势:1 次模型推理 + 1 次代码执行 │\n│ 只有最终 print 输出进入上下文 │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### 2.2 官方 API 使用方式\n\n根据 Anthropic 官方文档,启用 PTC 需要:\n\n```python\n# 1. 标记工具可被代码执行环境调用\ntools = [\n {\n \"type\": \"code_execution_20250825\",\n \"name\": \"code_execution\"\n },\n {\n \"name\": \"get_expenses\",\n \"description\": \"获取员工费用记录\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"] # 关键配置\n }\n]\n\n# 2. 使用 beta API 调用\nresponse = client.beta.messages.create(\n model=\"claude-sonnet-4-5-20250929\",\n betas=[\"advanced-tool-use-2025-11-20\"],\n tools=tools,\n messages=[{\"role\": \"user\", \"content\": \"分析 Q3 费用超标情况\"}]\n)\n```\n\n### 2.3 模型生成的代码示例\n\n当启用 PTC 后,Claude 会生成类似这样的代码来完成任务:\n\n```python\nimport asyncio\nimport json\n\n# 获取团队成员\nteam_json = await get_team_members(department=\"engineering\")\nteam = json.loads(team_json)\n\n# 并行获取所有成员的费用数据\nexpense_tasks = [\n get_expenses(employee_id=m[\"id\"], quarter=\"Q3\")\n for m in team\n]\nexpenses_results = await asyncio.gather(*expense_tasks)\n\n# 分析超标情况\nexceeded = []\nfor member, exp_json in zip(team, expenses_results):\n expenses = json.loads(exp_json)\n # 只计算已批准的费用\n total = sum(e[\"amount\"] for e in expenses if e[\"status\"] == \"approved\")\n\n # 获取该员工的预算限额\n budget_json = await get_custom_budget(user_id=member[\"id\"])\n budget = json.loads(budget_json)\n\n if total > budget[\"travel_budget\"]:\n exceeded.append({\n \"name\": member[\"name\"],\n \"spent\": total,\n \"limit\": budget[\"travel_budget\"],\n \"over\": total - budget[\"travel_budget\"]\n })\n\n# 只输出超标人员摘要\nprint(json.dumps(exceeded, indent=2))\n```\n\n### 2.4 效率提升数据\n\n根据 Anthropic 官方测试数据:\n\n| 指标 | 传统 Tool Use | PTC | 提升 |\n|------|--------------|-----|------|\n| 平均 Token 消耗 | 43,588 | 27,297 | **37%↓** |\n| 模型推理次数 | N+1 次 | 1-2 次 | **显著降低** |\n| 知识检索准确率 | 25.6% | 28.5% | **11%↑** |\n| GIA 基准测试 | 46.5% | 51.2% | **10%↑** |\n\n## 三、自托管方案:Docker Sandbox 实现\n\n官方 PTC 使用 Anthropic 托管的沙箱环境,但在某些场景下我们需要:\n- 完全的控制权和自定义能力\n- 支持非 Claude 模型\n- 私有化部署\n- 自定义依赖包\n\n为此,我们实现了一个**完全兼容官方 PTC 机制**的自托管 Docker Sandbox 方案。\n\n### 3.1 整体架构\n\n```\n┌──────────────────────────────────────────────────────────────────┐\n│ 整体系统架构 │\n├──────────────────────────────────────────────────────────────────┤\n│ │\n│ ┌─────────────┐ ┌──────────────────┐ ┌───────────────┐ │\n│ │ 用户应用 │───▶│ Orchestrator │───▶│ Claude API │ │\n│ └─────────────┘ └────────┬─────────┘ └───────────────┘ │\n│ │ │\n│ ▼ │\n│ ┌────────────────┐ │\n│ │ ToolRegistry │ │\n│ │ 工具注册/执行 │ │\n│ └────────┬───────┘ │\n│ │ │\n│ ▼ │\n│ ┌───────────────────────────────────────────────────────────┐ │\n│ │ SandboxExecutor │ │\n│ │ ┌─────────────────────────────────────────────────────┐ │ │\n│ │ │ Docker Container │ │ │\n│ │ │ ┌─────────────────┐ ┌─────────────────────────┐ │ │ │\n│ │ │ │ Runner Script │◀──▶│ IPC 工具调用通道 │ │ │ │\n│ │ │ │ 执行用户代码 │ │ stdin/stdout/stderr │ │ │ │\n│ │ │ └─────────────────┘ └─────────────────────────┘ │ │ │\n│ │ │ │ │ │\n│ │ │ 安全限制: 无网络 | 只读文件系统 | 资源限制 │ │ │\n│ │ └─────────────────────────────────────────────────────┘ │ │\n│ └───────────────────────────────────────────────────────────┘ │\n│ │\n└──────────────────────────────────────────────────────────────────┘\n```\n\n### 3.2 核心组件\n\n#### 3.2.1 SandboxExecutor - Docker 沙箱执行器\n\n`SandboxExecutor` 是核心组件,负责在隔离的 Docker 容器中执行代码:\n\n```python\nfrom sandboxed_ptc import SandboxExecutor, SandboxConfig, ToolRegistry\n\n# 配置沙箱\nconfig = SandboxConfig(\n image=\"python:3.11-slim\",\n memory_limit=\"256m\",\n cpu_quota=50000, # 50% CPU\n timeout_seconds=60.0,\n network_disabled=True, # 禁用网络\n read_only=True, # 只读文件系统\n enable_session_reuse=True, # 启用容器复用\n session_timeout_seconds=270.0 # 会话超时 4.5 分钟\n)\n\nexecutor = SandboxExecutor(registry, config)\n\n# 执行代码\nresult, session_id = await executor.execute(\n code=\"x = 10\\nprint(x * 2)\",\n reuse_session=True\n)\n# 输出: 20\n\n# 复用会话,变量状态保持\nresult, session_id = await executor.execute(\n code=\"print(x + 5)\", # x 仍然存在\n session_id=session_id\n)\n# 输出: 15\n```\n\n#### 3.2.2 IPC 通信协议\n\n容器内代码与主进程通过自定义 IPC 协议通信:\n\n```\n┌─────────────────┐ ┌─────────────────┐\n│ Docker 容器 │ │ 主进程 │\n│ (用户代码) │ │ (SandboxExecutor)│\n├─────────────────┤ ├─────────────────┤\n│ │ 工具调用请求 │ │\n│ await tool() ─┼──── stderr ────────▶│ 解析请求 │\n│ │ │ │ │\n│ │ │ ▼ │\n│ │ │ ToolRegistry │\n│ │ │ 执行真实工具 │\n│ │ 工具调用结果 │ │ │\n│ 继续执行 ◀─┼──── stdin ─────────┼───────┘ │\n│ │ │ │\n│ print(结果) │ 最终输出 │ │\n│ ─┼──── stdout ────────▶│ 返回给模型 │\n└─────────────────┘ └─────────────────┘\n```\n\nIPC 消息格式:\n\n```python\n# 工具调用请求 (Container → Host, via stderr)\n__PTC_TOOL_CALL__{\"call_id\": \"uuid\", \"tool_name\": \"get_expenses\",\n \"arguments\": {\"employee_id\": \"ENG001\", \"quarter\": \"Q3\"}}__PTC_END_CALL__\n\n# 工具调用结果 (Host → Container, via stdin)\n__PTC_TOOL_RESULT__{\"call_id\": \"uuid\", \"result\": [...], \"error\": null}__PTC_END_RESULT__\n\n# 最终输出 (Container → Host, via stdout)\n__PTC_OUTPUT__{\"success\": true, \"output\": \"分析结果...\", \"error\": null}__PTC_END_OUTPUT__\n```\n\n#### 3.2.3 安全设计\n\nDocker 容器运行时应用多层安全限制:\n\n```yaml\nsecurity:\n network_disabled: true # 禁用网络访问\n read_only: true # 只读文件系统\n user: sandbox (non-root) # 非特权用户\n cap_drop: [ALL] # 移除所有 Linux capabilities\n security_opt: [no-new-privileges] # 禁止提权\n mem_limit: 256m # 内存限制\n cpu_quota: 50000 # CPU 限制 (50%)\n```\n\n### 3.3 与官方 PTC 的对比\n\n| 特性 | 官方 PTC | Docker Sandbox |\n|------|---------|---------------|\n| 沙箱环境 | Anthropic 托管 | 自托管 Docker |\n| 控制权 | 有限 | **完全** |\n| 自定义依赖 | 不支持 | **完全支持** |\n| 网络访问 | 受限 | **可配置** |\n| 会话持久化 | 支持 | 支持 |\n| 调试能力 | 有限 | **完全** |\n| 部署灵活性 | 受限 | **灵活** |\n| 成本 | 按使用计费 | 本地资源 |\n| **非 Claude 模型支持** | 不支持 | **支持** |\n\n## 四、实战演示:多模型 PTC 效果\n\n我们使用 `notebook3.ipynb` 中的示例来演示 PTC 在不同模型上的效果。\n\n### 4.1 测试场景:企业差旅费用审计\n\n#### 业务背景\n\n我们模拟了一个**企业费用管理系统**,包含以下 Mock API 工具:\n\n| 工具名称 | 功能描述 | 返回数据量 |\n|---------|---------|-----------|\n| `get_team_members(department)` | 获取部门团队成员列表 | 8 人(工程部) |\n| `get_expenses(employee_id, quarter)` | 获取员工某季度所有费用明细 | 20-50 条/人 |\n| `get_custom_budget(user_id)` | 查询员工自定义预算额度 | 1 条 |\n\n#### 数据特点\n\n**团队成员数据**:工程部门有 8 名成员,涵盖 junior、mid、senior、staff、principal 五个级别。\n\n**费用明细数据**:每位员工每季度有 20-50 条费用记录,每条记录包含丰富的元数据:\n- 基础信息:expense_id、date、amount、currency、status\n- 分类信息:category(travel/lodging/meals/software/equipment/conference/office/internet)\n- 审计信息:approved_by、receipt_url、payment_method、project_code、notes\n- 商户信息:store_name、store_location\n\n**预算规则**:\n- 标准差旅预算:$5,000/季度\n- 部分员工有自定义预算例外(如 Staff Engineer $8,000、Principal Engineer $12,000)\n- **关键规则**:只有 `status=\"approved\"` 的费用才计入预算\n\n#### 测试任务\n\n测试问题:\n> \"Which engineering team members exceeded their Q3 travel budget? Standard quarterly travel budget is $5,000. However, some employees have custom budget limits. For anyone who exceeded the $5,000 standard budget, check if they have a custom budget exception.\"\n\n#### 为什么这是一个好的 PTC 测试用例?\n\n1. **多步骤工具调用**:需要先获取团队成员 → 逐个获取费用明细 → 对超标者查询自定义预算\n2. **大量中间数据**:8 人 × 20-50 条费用 = 160-400 条费用记录,传统模式下全部进入上下文\n3. **复杂过滤逻辑**:只统计 approved 状态、travel/lodging 类别的费用\n4. **条件分支判断**:先与 $5,000 比较,超标再查自定义预算,再次比较\n5. **数据聚合输出**:最终只需输出超标人员名单,而非全部明细\n\n### 4.2 测试代码\n\n```python\nimport anthropic\nfrom anthropic.types.beta import BetaTextBlock, BetaToolUseBlock\n\n# 配置 PTC 工具\nptc_tools = [\n {\n \"type\": \"code_execution_20250825\",\n \"name\": \"code_execution\",\n },\n {\n \"name\": \"get_team_members\",\n \"description\": \"获取部门团队成员列表\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"]\n },\n {\n \"name\": \"get_expenses\",\n \"description\": \"获取员工费用记录\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"]\n },\n {\n \"name\": \"get_custom_budget\",\n \"description\": \"获取员工自定义预算\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"]\n }\n]\n\n# 通过代理服务调用(支持多种模型)\nclient = anthropic.Anthropic(\n api_key=os.environ.get('API_KEY'),\n base_url=os.environ.get('BASE_URL') # 代理服务地址\n)\n\nresponse = client.beta.messages.create(\n model=model_id, # 可以是 Claude、Qwen、MiniMax 等\n betas=[\"advanced-tool-use-2025-11-20\"],\n tools=ptc_tools,\n messages=[{\"role\": \"user\", \"content\": query}]\n)\n```\n\n### 4.3 多模型测试结果\n\n我们在以下模型上测试了相同的 PTC 任务:\n> 该任务的正确答案是,如果人名或者数字金额不对,则判断为❌ 不准确 \n1. **Alice Chen** \n - Budget: $5,000.00 | Actual: $9,876.54 | **+$4,876.54 over**\n\n2. **Emma Johnson** \n - Budget: $5,000.00 | Actual: $5,266.02 | **+$266.02 over**\n\n3. **Grace Taylor** \n - Budget: $5,000.00 | Actual: $6,474.46 | **+$1,474.46 over**\n\n\n| 模型 | API工具调用次数 | Token 消耗 | 执行时间 | 结果准确性 |\n|------|-------------|-----------|---------|-----------|\n| Claude Sonnet 4.5 | 4 | ~12.9k | 19.4s | ✅ 准确 |\n| Claude Opus 4.5 | 4 | ~13.2k | 25s | ✅ 准确 |\n| MiniMax-M2 | 5 | ~18.9k | 61s | ❌ 不准确 |\n| Qwen3-Coder-480B | 13 | ~10.3k | 12s | ✅ 准确 |\n| Qwen3-235B-2507 | 7 | ~15.9k | 47s | ❌ 不准确 |\n| Qwen3-Next-80B | 18 | ~9.9k | 23s | ✅ 准确 |\n\n注:Qwen3-Coder-480B和Qwen3-Next-80B的API调用次数偏多,是因为没有按照指示生成并行执行代码,而是串行调用API工具,导致耗时增加。 \n\n同样我在非PTC模式下也做了同样测试:\n| 模型 | API工具调用次数 | Token 消耗 | 执行时间 | 结果准确性 |\n|------|-------------|-----------|---------|-----------|\n| Claude Sonnet 4.5 | 4 | ~123k | 29s | ❌ 不准确 |\n| Claude Opus 4.5 | 4 | ~122k | 26s | ❌ 不准确 |\n| MiniMax-M2 | 5 | ~148.8k | 56s | ❌ 不准确 |\n| Qwen3-Coder-480B | 12 | ~481.5k | 43s | ❌ 不准确 |\n| Qwen3-235B-2507 | 7 | ~259.7k | 46s | ❌ 不准确 |\n| Qwen3-Next-80B | 12 | ~750.7k | 50s | ❌ 不准确 |\n\n#### PTC vs 非 PTC 模式对比分析\n\n| 模型 | Token (PTC) | Token (非PTC) | Token 节省率 | PTC准确 | 非PTC准确 |\n|------|------------|--------------|-------------|---------|----------|\n| Claude Sonnet 4.5 | 12.9k | 123k | **89.5%** | ❌ | ❌ |\n| Claude Opus 4.5 | 13.2k | 122k | **89.2%** | ✅ | ❌ |\n| MiniMax-M2 | 18.9k | 148.8k | **87.3%** | ❌ | ❌ |\n| Qwen3-Coder-480B | 10.3k | 481.5k | **97.9%** | ✅ | ❌ |\n| Qwen3-235B-2507 | 15.9k | 259.7k | **93.9%** | ❌ | ❌ |\n| Qwen3-Next-80B | 9.9k | 750.7k | **98.7%** | ✅ | ❌ |\n\n**核心发现**:\n\n1. **Token 消耗大幅降低**:所有模型在 PTC 模式下 Token 消耗均降低 **87%-99%**,平均节省约 **93%**\n2. **PTC 模式准确率更高**:在 PTC 模式下有 4 个模型给出正确答案,而非 PTC 模式所有模型都无法给出100%正确答案\n3. **Qwen3 系列表现亮眼**:Qwen3-Coder-480B 和 Qwen3-Next-80B 在 PTC 模式下表现优异,Token 节省率分别达 97.9% 和 98.7%\n4. **PTC 提升推理质量**:通过代码编排工具调用,模型可以更精确地处理数据过滤、聚合逻辑,减少在自然语言中处理大量数据导致的错误\n\n**关键发现**:通过我们的自托管 PTC 方案,**非 Claude 模型也能使用 PTC 范式**,显著提升工具调用效率。\n\n### 4.4 模型生成的代码对比\n\n**Claude Sonnet 4.5 生成的代码**:\n\n```python\nimport asyncio\nimport json\n\n# 获取工程团队成员\nteam_json = await get_team_members(department=\"engineering\")\nteam = json.loads(team_json)\n\n# 并行获取所有成员的 Q3 费用\nexpense_tasks = [get_expenses(employee_id=m[\"id\"], quarter=\"Q3\") for m in team]\nall_expenses = await asyncio.gather(*expense_tasks)\n\nexceeded_members = []\nfor member, exp_json in zip(team, all_expenses):\n expenses = json.loads(exp_json)\n total_travel = sum(\n e[\"amount\"] for e in expenses\n if e[\"category\"] == \"travel\" and e[\"status\"] == \"approved\"\n )\n\n if total_travel > 5000:\n # 检查是否有自定义预算\n budget_json = await get_custom_budget(user_id=member[\"id\"])\n budget = json.loads(budget_json)\n\n limit = budget[\"travel_budget\"]\n if total_travel > limit:\n exceeded_members.append({\n \"name\": member[\"name\"],\n \"spent\": total_travel,\n \"limit\": limit,\n \"exceeded_by\": total_travel - limit\n })\n\nprint(json.dumps(exceeded_members, indent=2, ensure_ascii=False))\n```\n\n**Qwen3-Next-80B 生成的代码**(风格略有不同但功能等效):\n\n```python\nimport json\nimport asyncio\n\nteam_data = await get_team_members(department=\"engineering\")\nmembers = json.loads(team_data)\n\nresults = []\nfor member in members:\n expenses_data = await get_expenses(employee_id=member[\"id\"], quarter=\"Q3\")\n expenses = json.loads(expenses_data)\n\n travel_total = sum(\n exp[\"amount\"] for exp in expenses\n if exp[\"category\"] == \"travel\" and exp[\"status\"] == \"approved\"\n )\n\n if travel_total > 5000:\n budget_data = await get_custom_budget(user_id=member[\"id\"])\n budget_info = json.loads(budget_data)\n actual_limit = budget_info[\"travel_budget\"]\n\n if travel_total > actual_limit:\n results.append(f\"{member['name']}: ${travel_total:.2f} (limit: ${actual_limit})\")\n\nprint(\"Exceeded budget:\\\\n\" + \"\\\\n\".join(results) if results else \"No one exceeded budget\")\n```\n\n## 五、PTC 方案的核心价值\n\n### 5.1 不仅仅是 Claude\n\n**我们方案的最大价值在于:PTC 范式不再是 Claude 专属**。\n\n通过 Docker Sandbox + API 代理的组合,任何支持 Function Calling 的大模型都可以使用 PTC:\n\n```python\n# 支持的模型列表\nsupported_models = [\n \"claude-sonnet-4-5-20250929\",\n \"claude-opus-4-5-20251101\",\n \"qwen.qwen3-coder-480b-a35b-v1:0\",\n \"qwen.qwen3-next-80b-a3b\",\n \"minimax.minimax-m2\",\n \"deepseek.deepseek-v3\",\n # ... 任何支持 tool_use 的模型\n]\n```\n\n### 5.2 适用场景\n\nPTC 特别适合以下场景:\n\n| 场景 | 传统方式问题 | PTC 优势 |\n|------|------------|---------|\n| **批量数据处理** | 中间结果撑爆上下文 | 只返回聚合摘要 |\n| **多工具组合** | N 次推理延迟累积 | 1 次推理 + 代码执行 |\n| **条件逻辑** | 每步都需模型决策 | 代码自动处理分支 |\n| **并行调用** | 串行等待 | asyncio.gather 并行 |\n| **数据过滤** | 模型手动筛选 | 代码高效过滤 |\n\n### 5.3 成本对比示例(基于实际测试)\n\n以本文 notebook3.ipynb 中的**企业差旅费用审计**测试为例:\n\n**任务**:分析 8 名工程团队成员的 Q3 差旅费用是否超标\n\n**数据规模**:\n- 8 人 × 20-50 条费用明细 = **160-400 条费用记录**\n- 每条记录包含 15+ 个字段(expense_id、date、amount、category、status、merchant...)\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│ 实际测试数据对比 │\n├─────────────────────────────────────────────────────────────────┤\n│ │\n│ 非 PTC 模式 (以 Claude Sonnet 4.5 为例): │\n│ ├─ API 调用次数: 4 次 │\n│ ├─ Token 消耗: ~123,000 │\n│ ├─ 执行时间: 29s │\n│ └─ 所有费用明细进入上下文,模型手动筛选汇总 │\n│ │\n│ PTC 模式 (以 Claude Sonnet 4.5 为例): │\n│ ├─ API 调用次数: 4 次 │\n│ ├─ Token 消耗: ~12,900 │\n│ ├─ 执行时间: 19.4s │\n│ └─ 代码在沙箱中处理数据,只返回超标人员摘要 │\n│ │\n│ ═══════════════════════════════════════════════════════════ │\n│ Token 节省: 89.5% | 时间节省: 33% | 准确性: PTC✅ 非PTC❌ │\n│ │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n**成本估算**(以 Claude Sonnet 定价 $3/$15 per 1M tokens):\n\n| 模式 | Token 消耗 | 输入成本 | 输出成本 | 总成本 |\n|------|-----------|---------|---------|--------|\n| 非 PTC | ~123,000 | $0.369 | ~$0.15 | **~$0.52** |\n| PTC | ~12,900 | $0.039 | ~$0.02 | **~$0.06** |\n| **节省** | 89.5% | - | - | **~88%** |\n\n如果是生产环境每天执行 1000 次类似查询:\n- 非 PTC:$520/天 → **$15,600/月**\n- PTC:$60/天 → **$1,800/月**\n- **月节省:$13,800(88%)**\n\n## 六、100% Anthropic API 兼容:anthropic_api_converter\n\n如果你希望在 AWS Bedrock 上使用完全兼容 Anthropic API 的服务(包括 PTC),可以使用开源项目 [anthropic_api_converter](https://github.com/xiehust/anthropic_api_converter)。\n\n### 6.1 项目简介\n\n这是一个轻量级 API 转换代理服务,让你无需修改代码即可:\n\n- 在 **Claude Code** 中使用 Bedrock 上的 Qwen3-Coder 等模型\n- 在 **Claude Agent SDK** 中混合使用不同模型\n- 完整支持 **Programmatic Tool Calling** API\n\n### 6.2 核心特性\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│ anthropic_api_converter │\n├──────────────────────────────────────────────────────────────┤\n│ ✅ 零代码迁移 - 完全兼容 Anthropic API 格式 │\n│ ✅ PTC 支持 - 业界首个在 Bedrock 上实现兼容 PTC 的代理 │\n│ ✅ 多模型支持 - Claude/Qwen/DeepSeek/MiniMax... │\n│ ✅ 流式响应 - 支持 SSE 实时流式输出 │\n│ ✅ 工具调用 - 完整的 Function Calling 支持 │\n│ ✅ 企业级 - API Key 管理、速率限制、用量追踪 │\n└──────────────────────────────────────────────────────────────┘\n```\n\n### 6.3 快速使用\n\n```bash\n# 设置环境变量,让 Claude Code 通过代理使用 Bedrock 模型\nexport CLAUDE_CODE_USE_BEDROCK=0\nexport ANTHROPIC_BASE_URL=http://your-proxy-url.com\nexport ANTHROPIC_API_KEY=sk-xxxx\nexport ANTHROPIC_DEFAULT_SONNET_MODEL=qwen.qwen3-coder-480b-a35b-v1:0\n\n# 启动 Claude Code,自动使用 Qwen3-Coder\nclaude\n```\n\n### 6.4 PTC 配置\n\n```python\n# 在代理服务中启用 PTC\nENABLE_PROGRAMMATIC_TOOL_CALLING=True\nPTC_SANDBOX_IMAGE=python:3.11-slim\nPTC_SESSION_TIMEOUT=270\nPTC_EXECUTION_TIMEOUT=60\nPTC_MEMORY_LIMIT=256m\nPTC_NETWORK_DISABLED=True\n```\n\n## 七、总结\n\nProgrammatic Tool Calling 代表了 AI Agent 工具调用的新范式:\n\n1. **效率革命**:从 N 次推理降至 1-2 次,Token 消耗降低 37%+\n2. **代码编排**:用 Python 表达复杂逻辑,比自然语言更精确\n3. **上下文隔离**:中间数据不进入模型上下文,只保留关键输出\n4. **并行执行**:通过 asyncio.gather 实现真正的并行工具调用\n\n通过我们的 **Docker Sandbox 自托管方案**,这一能力不再是 Claude 专属:\n\n- ✅ 完全兼容官方 PTC 协议\n- ✅ 支持任意大模型(Qwen、DeepSeek、MiniMax...)\n- ✅ 私有化部署,完全可控\n- ✅ 自定义依赖包和执行环境\n\n**这是 Agent 工具调用从\"对话式\"向\"程序化\"演进的重要一步。**\n\n---\n\n## 参考资料\n\n1. **Anthropic 官方文档**\n - [Introducing advanced tool use on the Claude Developer Platform](https://www.anthropic.com/engineering/advanced-tool-use)\n - [Programmatic Tool Calling Documentation](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling)\n - [PTC Cookbook](https://github.com/anthropics/claude-cookbooks/blob/main/tool_use/programmatic_tool_calling_ptc.ipynb)\n\n2. **开源项目**\n - [Sandboxed PTC - Docker Sandbox 实现](https://github.com/xiehust/claude_ptc)\n - [anthropic_api_converter - Anthropic API 代理](https://github.com/xiehust/anthropic_api_converter)\n\n3. **相关技术**\n - [Building Effective Agents - Anthropic Research](https://www.anthropic.com/research/building-effective-agents)\n - [Code Execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp)\n\n---\n\n> **作者注**:本文代码示例均来自实际项目,可在 GitHub 仓库中找到完整实现。欢迎 Star 和贡献!\n"}, "6d7e187f7a203fc4f5ea310f8f521ba27e8d5f84": {"t": 1785770701.4296293, "n": 21012, "h": "f32f0e6dcf73a1f9", "c": "# Agent工具调用新范式:逆向工程 Anthropic Claude Programmatic Tool Calling 功能\n\n> 本文深入解析 Anthropic 最新发布的 Programmatic Tool Calling (PTC) 技术,并介绍如何通过自托管 Docker Sandbox 方案实现完全兼容的 PTC 功能,让任意大模型都能享受这一革命性的工具调用范式。\n\n## 一、背景:传统 Tool Use 的瓶颈\n\n在构建 AI Agent 时,工具调用(Tool Use / Function Calling)是连接模型与外部世界的桥梁。然而,传统的工具调用模式存在明显的效率瓶颈:\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│ 传统 Tool Use 流程 │\n├─────────────────────────────────────────────────────────────┤\n│ 用户请求 → 模型推理 → 工具调用1 → 模型推理 → 工具调用2 │\n│ → 模型推理 → 工具调用3 → 模型推理 → 最终响应 │\n│ │\n│ 问题:N 次工具调用 = N+1 次模型推理 │\n│ 所有中间结果都进入上下文,消耗大量 Token │\n└─────────────────────────────────────────────────────────────┘\n```\n\n以一个典型的业务场景为例:**\"查询工程团队哪些成员的 Q3 差旅费用超标?\"**\n\n传统方式需要:\n1. 获取团队成员列表 → 20 人\n2. 为每人获取费用记录 → 20 次工具调用,每次返回 50-100 条明细\n3. 获取预算标准 → 多次调用\n4. **所有 2000+ 条费用明细都进入模型上下文**\n5. 模型手动汇总、比对、筛选\n\n这种方式导致:\n- **Token 消耗巨大**:中间数据全部进入上下文\n- **延迟累积**:每次工具调用都需要一次完整的模型推理\n- **准确性下降**:模型需要在自然语言中处理大量数据,容易出错\n\n## 二、Programmatic Tool Calling:代码编排工具调用\n\n2024 年 11 月,Anthropic 发布了 **Programmatic Tool Calling (PTC)** 功能,从根本上改变了工具调用范式。\n\n### 2.1 核心思想\n\nPTC 的核心思想是:**让模型生成 Python 代码来编排工具调用,而不是逐个请求工具**。\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│ Programmatic Tool Calling 流程 │\n├─────────────────────────────────────────────────────────────┤\n│ 用户请求 → 模型生成 Python 代码 → 沙箱执行代码 │\n│ ↓ │\n│ 循环调用工具1,2,3... │\n│ 数据处理、过滤、聚合 │\n│ ↓ │\n│ 返回 print() 输出 │\n│ → 模型基于摘要输出给出最终响应 │\n│ │\n│ 优势:1 次模型推理 + 1 次代码执行 │\n│ 只有最终 print 输出进入上下文 │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### 2.2 官方 API 使用方式\n\n根据 Anthropic 官方文档,启用 PTC 需要:\n\n```python\n# 1. 标记工具可被代码执行环境调用\ntools = [\n {\n \"type\": \"code_execution_20250825\",\n \"name\": \"code_execution\"\n },\n {\n \"name\": \"get_expenses\",\n \"description\": \"获取员工费用记录\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"] # 关键配置\n }\n]\n\n# 2. 使用 beta API 调用\nresponse = client.beta.messages.create(\n model=\"claude-sonnet-4-5-20250929\",\n betas=[\"advanced-tool-use-2025-11-20\"],\n tools=tools,\n messages=[{\"role\": \"user\", \"content\": \"分析 Q3 费用超标情况\"}]\n)\n```\n\n### 2.3 模型生成的代码示例\n\n当启用 PTC 后,Claude 会生成类似这样的代码来完成任务:\n\n```python\nimport asyncio\nimport json\n\n# 获取团队成员\nteam_json = await get_team_members(department=\"engineering\")\nteam = json.loads(team_json)\n\n# 并行获取所有成员的费用数据\nexpense_tasks = [\n get_expenses(employee_id=m[\"id\"], quarter=\"Q3\")\n for m in team\n]\nexpenses_results = await asyncio.gather(*expense_tasks)\n\n# 分析超标情况\nexceeded = []\nfor member, exp_json in zip(team, expenses_results):\n expenses = json.loads(exp_json)\n # 只计算已批准的费用\n total = sum(e[\"amount\"] for e in expenses if e[\"status\"] == \"approved\")\n\n # 获取该员工的预算限额\n budget_json = await get_custom_budget(user_id=member[\"id\"])\n budget = json.loads(budget_json)\n\n if total > budget[\"travel_budget\"]:\n exceeded.append({\n \"name\": member[\"name\"],\n \"spent\": total,\n \"limit\": budget[\"travel_budget\"],\n \"over\": total - budget[\"travel_budget\"]\n })\n\n# 只输出超标人员摘要\nprint(json.dumps(exceeded, indent=2))\n```\n\n### 2.4 效率提升数据\n\n根据 Anthropic 官方测试数据:\n\n| 指标 | 传统 Tool Use | PTC | 提升 |\n|------|--------------|-----|------|\n| 平均 Token 消耗 | 43,588 | 27,297 | **37%↓** |\n| 模型推理次数 | N+1 次 | 1-2 次 | **显著降低** |\n| 知识检索准确率 | 25.6% | 28.5% | **11%↑** |\n| GIA 基准测试 | 46.5% | 51.2% | **10%↑** |\n\n## 三、自托管方案:Docker Sandbox 实现\n\n官方 PTC 使用 Anthropic 托管的沙箱环境,但在某些场景下我们需要:\n- 完全的控制权和自定义能力\n- 支持非 Claude 模型\n- 私有化部署\n- 自定义依赖包\n\n为此,我们实现了一个**完全兼容官方 PTC 机制**的自托管 Docker Sandbox 方案。\n\n### 3.1 整体架构\n\n```\n┌──────────────────────────────────────────────────────────────────┐\n│ 整体系统架构 │\n├──────────────────────────────────────────────────────────────────┤\n│ │\n│ ┌─────────────┐ ┌──────────────────┐ ┌───────────────┐ │\n│ │ 用户应用 │───▶│ Orchestrator │───▶│ Claude API │ │\n│ └─────────────┘ └────────┬─────────┘ └───────────────┘ │\n│ │ │\n│ ▼ │\n│ ┌────────────────┐ │\n│ │ ToolRegistry │ │\n│ │ 工具注册/执行 │ │\n│ └────────┬───────┘ │\n│ │ │\n│ ▼ │\n│ ┌───────────────────────────────────────────────────────────┐ │\n│ │ SandboxExecutor │ │\n│ │ ┌─────────────────────────────────────────────────────┐ │ │\n│ │ │ Docker Container │ │ │\n│ │ │ ┌─────────────────┐ ┌─────────────────────────┐ │ │ │\n│ │ │ │ Runner Script │◀──▶│ IPC 工具调用通道 │ │ │ │\n│ │ │ │ 执行用户代码 │ │ stdin/stdout/stderr │ │ │ │\n│ │ │ └─────────────────┘ └─────────────────────────┘ │ │ │\n│ │ │ │ │ │\n│ │ │ 安全限制: 无网络 | 只读文件系统 | 资源限制 │ │ │\n│ │ └─────────────────────────────────────────────────────┘ │ │\n│ └───────────────────────────────────────────────────────────┘ │\n│ │\n└──────────────────────────────────────────────────────────────────┘\n```\n\n### 3.2 核心组件\n\n#### 3.2.1 SandboxExecutor - Docker 沙箱执行器\n\n`SandboxExecutor` 是核心组件,负责在隔离的 Docker 容器中执行代码:\n\n```python\nfrom sandboxed_ptc import SandboxExecutor, SandboxConfig, ToolRegistry\n\n# 配置沙箱\nconfig = SandboxConfig(\n image=\"python:3.11-slim\",\n memory_limit=\"256m\",\n cpu_quota=50000, # 50% CPU\n timeout_seconds=60.0,\n network_disabled=True, # 禁用网络\n read_only=True, # 只读文件系统\n enable_session_reuse=True, # 启用容器复用\n session_timeout_seconds=270.0 # 会话超时 4.5 分钟\n)\n\nexecutor = SandboxExecutor(registry, config)\n\n# 执行代码\nresult, session_id = await executor.execute(\n code=\"x = 10\\nprint(x * 2)\",\n reuse_session=True\n)\n# 输出: 20\n\n# 复用会话,变量状态保持\nresult, session_id = await executor.execute(\n code=\"print(x + 5)\", # x 仍然存在\n session_id=session_id\n)\n# 输出: 15\n```\n\n#### 3.2.2 IPC 通信协议\n\n容器内代码与主进程通过自定义 IPC 协议通信:\n\n```\n┌─────────────────┐ ┌─────────────────┐\n│ Docker 容器 │ │ 主进程 │\n│ (用户代码) │ │ (SandboxExecutor)│\n├─────────────────┤ ├─────────────────┤\n│ │ 工具调用请求 │ │\n│ await tool() ─┼──── stderr ────────▶│ 解析请求 │\n│ │ │ │ │\n│ │ │ ▼ │\n│ │ │ ToolRegistry │\n│ │ │ 执行真实工具 │\n│ │ 工具调用结果 │ │ │\n│ 继续执行 ◀─┼──── stdin ─────────┼───────┘ │\n│ │ │ │\n│ print(结果) │ 最终输出 │ │\n│ ─┼──── stdout ────────▶│ 返回给模型 │\n└─────────────────┘ └─────────────────┘\n```\n\nIPC 消息格式:\n\n```python\n# 工具调用请求 (Container → Host, via stderr)\n__PTC_TOOL_CALL__{\"call_id\": \"uuid\", \"tool_name\": \"get_expenses\",\n \"arguments\": {\"employee_id\": \"ENG001\", \"quarter\": \"Q3\"}}__PTC_END_CALL__\n\n# 工具调用结果 (Host → Container, via stdin)\n__PTC_TOOL_RESULT__{\"call_id\": \"uuid\", \"result\": [...], \"error\": null}__PTC_END_RESULT__\n\n# 最终输出 (Container → Host, via stdout)\n__PTC_OUTPUT__{\"success\": true, \"output\": \"分析结果...\", \"error\": null}__PTC_END_OUTPUT__\n```\n\n#### 3.2.3 安全设计\n\nDocker 容器运行时应用多层安全限制:\n\n```yaml\nsecurity:\n network_disabled: true # 禁用网络访问\n read_only: true # 只读文件系统\n user: sandbox (non-root) # 非特权用户\n cap_drop: [ALL] # 移除所有 Linux capabilities\n security_opt: [no-new-privileges] # 禁止提权\n mem_limit: 256m # 内存限制\n cpu_quota: 50000 # CPU 限制 (50%)\n```\n\n### 3.3 与官方 PTC 的对比\n\n| 特性 | 官方 PTC | Docker Sandbox |\n|------|---------|---------------|\n| 沙箱环境 | Anthropic 托管 | 自托管 Docker |\n| 控制权 | 有限 | **完全** |\n| 自定义依赖 | 不支持 | **完全支持** |\n| 网络访问 | 受限 | **可配置** |\n| 会话持久化 | 支持 | 支持 |\n| 调试能力 | 有限 | **完全** |\n| 部署灵活性 | 受限 | **灵活** |\n| 成本 | 按使用计费 | 本地资源 |\n| **非 Claude 模型支持** | 不支持 | **支持** |\n\n## 四、实战演示:多模型 PTC 效果\n\n我们使用 `notebook3.ipynb` 中的示例来演示 PTC 在不同模型上的效果。\n\n### 4.1 测试场景:企业差旅费用审计\n\n#### 业务背景\n\n我们模拟了一个**企业费用管理系统**,包含以下 Mock API 工具:\n\n| 工具名称 | 功能描述 | 返回数据量 |\n|---------|---------|-----------|\n| `get_team_members(department)` | 获取部门团队成员列表 | 8 人(工程部) |\n| `get_expenses(employee_id, quarter)` | 获取员工某季度所有费用明细 | 20-50 条/人 |\n| `get_custom_budget(user_id)` | 查询员工自定义预算额度 | 1 条 |\n\n#### 数据特点\n\n**团队成员数据**:工程部门有 8 名成员,涵盖 junior、mid、senior、staff、principal 五个级别。\n\n**费用明细数据**:每位员工每季度有 20-50 条费用记录,每条记录包含丰富的元数据:\n- 基础信息:expense_id、date、amount、currency、status\n- 分类信息:category(travel/lodging/meals/software/equipment/conference/office/internet)\n- 审计信息:approved_by、receipt_url、payment_method、project_code、notes\n- 商户信息:store_name、store_location\n\n**预算规则**:\n- 标准差旅预算:$5,000/季度\n- 部分员工有自定义预算例外(如 Staff Engineer $8,000、Principal Engineer $12,000)\n- **关键规则**:只有 `status=\"approved\"` 的费用才计入预算\n\n#### 测试任务\n\n测试问题:\n> \"Which engineering team members exceeded their Q3 travel budget? Standard quarterly travel budget is $5,000. However, some employees have custom budget limits. For anyone who exceeded the $5,000 standard budget, check if they have a custom budget exception.\"\n\n#### 为什么这是一个好的 PTC 测试用例?\n\n1. **多步骤工具调用**:需要先获取团队成员 → 逐个获取费用明细 → 对超标者查询自定义预算\n2. **大量中间数据**:8 人 × 20-50 条费用 = 160-400 条费用记录,传统模式下全部进入上下文\n3. **复杂过滤逻辑**:只统计 approved 状态、travel/lodging 类别的费用\n4. **条件分支判断**:先与 $5,000 比较,超标再查自定义预算,再次比较\n5. **数据聚合输出**:最终只需输出超标人员名单,而非全部明细\n\n### 4.2 测试代码\n\n```python\nimport anthropic\nfrom anthropic.types.beta import BetaTextBlock, BetaToolUseBlock\n\n# 配置 PTC 工具\nptc_tools = [\n {\n \"type\": \"code_execution_20250825\",\n \"name\": \"code_execution\",\n },\n {\n \"name\": \"get_team_members\",\n \"description\": \"获取部门团队成员列表\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"]\n },\n {\n \"name\": \"get_expenses\",\n \"description\": \"获取员工费用记录\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"]\n },\n {\n \"name\": \"get_custom_budget\",\n \"description\": \"获取员工自定义预算\",\n \"input_schema\": {...},\n \"allowed_callers\": [\"code_execution_20250825\"]\n }\n]\n\n# 通过代理服务调用(支持多种模型)\nclient = anthropic.Anthropic(\n api_key=os.environ.get('API_KEY'),\n base_url=os.environ.get('BASE_URL') # 代理服务地址\n)\n\nresponse = client.beta.messages.create(\n model=model_id, # 可以是 Claude、Qwen、MiniMax 等\n betas=[\"advanced-tool-use-2025-11-20\"],\n tools=ptc_tools,\n messages=[{\"role\": \"user\", \"content\": query}]\n)\n```\n\n### 4.3 多模型测试结果\n\n我们在以下模型上测试了相同的 PTC 任务:\n> 该任务的正确答案是,如果人名或者数字金额不对,则判断为❌ 不准确 \n1. **Alice Chen** \n - Budget: $5,000.00 | Actual: $9,876.54 | **+$4,876.54 over**\n\n2. **Emma Johnson** \n - Budget: $5,000.00 | Actual: $5,266.02 | **+$266.02 over**\n\n3. **Grace Taylor** \n - Budget: $5,000.00 | Actual: $6,474.46 | **+$1,474.46 over**\n\n\n| 模型 | API工具调用次数 | Token 消耗 | 执行时间 | 结果准确性 |\n|------|-------------|-----------|---------|-----------|\n| Claude Sonnet 4.5 | 4 | ~12.9k | 19.4s | ✅ 准确 |\n| Claude Opus 4.5 | 4 | ~13.2k | 25s | ✅ 准确 |\n| MiniMax-M2 | 5 | ~18.9k | 61s | ❌ 不准确 |\n| Qwen3-Coder-480B | 13 | ~10.3k | 12s | ✅ 准确 |\n| Qwen3-235B-2507 | 7 | ~15.9k | 47s | ❌ 不准确 |\n| Qwen3-Next-80B | 18 | ~9.9k | 23s | ✅ 准确 |\n\n注:Qwen3-Coder-480B和Qwen3-Next-80B的API调用次数偏多,是因为没有按照指示生成并行执行代码,而是串行调用API工具,导致耗时增加。 \n\n同样我在非PTC模式下也做了同样测试:\n| 模型 | API工具调用次数 | Token 消耗 | 执行时间 | 结果准确性 |\n|------|-------------|-----------|---------|-----------|\n| Claude Sonnet 4.5 | 4 | ~123k | 29s | ❌ 不准确 |\n| Claude Opus 4.5 | 4 | ~122k | 26s | ❌ 不准确 |\n| MiniMax-M2 | 5 | ~148.8k | 56s | ❌ 不准确 |\n| Qwen3-Coder-480B | 12 | ~481.5k | 43s | ❌ 不准确 |\n| Qwen3-235B-2507 | 7 | ~259.7k | 46s | ❌ 不准确 |\n| Qwen3-Next-80B | 12 | ~750.7k | 50s | ❌ 不准确 |\n\n#### PTC vs 非 PTC 模式对比分析\n\n| 模型 | Token (PTC) | Token (非PTC) | Token 节省率 | PTC准确 | 非PTC准确 |\n|------|------------|--------------|-------------|---------|----------|\n| Claude Sonnet 4.5 | 12.9k | 123k | **89.5%** | ❌ | ❌ |\n| Claude Opus 4.5 | 13.2k | 122k | **89.2%** | ✅ | ❌ |\n| MiniMax-M2 | 18.9k | 148.8k | **87.3%** | ❌ | ❌ |\n| Qwen3-Coder-480B | 10.3k | 481.5k | **97.9%** | ✅ | ❌ |\n| Qwen3-235B-2507 | 15.9k | 259.7k | **93.9%** | ❌ | ❌ |\n| Qwen3-Next-80B | 9.9k | 750.7k | **98.7%** | ✅ | ❌ |\n\n**核心发现**:\n\n1. **Token 消耗大幅降低**:所有模型在 PTC 模式下 Token 消耗均降低 **87%-99%**,平均节省约 **93%**\n2. **PTC 模式准确率更高**:在 PTC 模式下有 4 个模型给出正确答案,而非 PTC 模式所有模型都无法给出100%正确答案\n3. **Qwen3 系列表现亮眼**:Qwen3-Coder-480B 和 Qwen3-Next-80B 在 PTC 模式下表现优异,Token 节省率分别达 97.9% 和 98.7%\n4. **PTC 提升推理质量**:通过代码编排工具调用,模型可以更精确地处理数据过滤、聚合逻辑,减少在自然语言中处理大量数据导致的错误\n\n**关键发现**:通过我们的自托管 PTC 方案,**非 Claude 模型也能使用 PTC 范式**,显著提升工具调用效率。\n\n### 4.4 模型生成的代码对比\n\n**Claude Sonnet 4.5 生成的代码**:\n\n```python\nimport asyncio\nimport json\n\n# 获取工程团队成员\nteam_json = await get_team_members(department=\"engineering\")\nteam = json.loads(team_json)\n\n# 并行获取所有成员的 Q3 费用\nexpense_tasks = [get_expenses(employee_id=m[\"id\"], quarter=\"Q3\") for m in team]\nall_expenses = await asyncio.gather(*expense_tasks)\n\nexceeded_members = []\nfor member, exp_json in zip(team, all_expenses):\n expenses = json.loads(exp_json)\n total_travel = sum(\n e[\"amount\"] for e in expenses\n if e[\"category\"] == \"travel\" and e[\"status\"] == \"approved\"\n )\n\n if total_travel > 5000:\n # 检查是否有自定义预算\n budget_json = await get_custom_budget(user_id=member[\"id\"])\n budget = json.loads(budget_json)\n\n limit = budget[\"travel_budget\"]\n if total_travel > limit:\n exceeded_members.append({\n \"name\": member[\"name\"],\n \"spent\": total_travel,\n \"limit\": limit,\n \"exceeded_by\": total_travel - limit\n })\n\nprint(json.dumps(exceeded_members, indent=2, ensure_ascii=False))\n```\n\n**Qwen3-Next-80B 生成的代码**(风格略有不同但功能等效):\n\n```python\nimport json\nimport asyncio\n\nteam_data = await get_team_members(department=\"engineering\")\nmembers = json.loads(team_data)\n\nresults = []\nfor member in members:\n expenses_data = await get_expenses(employee_id=member[\"id\"], quarter=\"Q3\")\n expenses = json.loads(expenses_data)\n\n travel_total = sum(\n exp[\"amount\"] for exp in expenses\n if exp[\"category\"] == \"travel\" and exp[\"status\"] == \"approved\"\n )\n\n if travel_total > 5000:\n budget_data = await get_custom_budget(user_id=member[\"id\"])\n budget_info = json.loads(budget_data)\n actual_limit = budget_info[\"travel_budget\"]\n\n if travel_total > actual_limit:\n results.append(f\"{member['name']}: ${travel_total:.2f} (limit: ${actual_limit})\")\n\nprint(\"Exceeded budget:\\\\n\" + \"\\\\n\".join(results) if results else \"No one exceeded budget\")\n```\n\n## 五、PTC 方案的核心价值\n\n### 5.1 不仅仅是 Claude\n\n**我们方案的最大价值在于:PTC 范式不再是 Claude 专属**。\n\n通过 Docker Sandbox + API 代理的组合,任何支持 Function Calling 的大模型都可以使用 PTC:\n\n```python\n# 支持的模型列表\nsupported_models = [\n \"claude-sonnet-4-5-20250929\",\n \"claude-opus-4-5-20251101\",\n \"qwen.qwen3-coder-480b-a35b-v1:0\",\n \"qwen.qwen3-next-80b-a3b\",\n \"minimax.minimax-m2\",\n \"deepseek.deepseek-v3\",\n # ... 任何支持 tool_use 的模型\n]\n```\n\n### 5.2 适用场景\n\nPTC 特别适合以下场景:\n\n| 场景 | 传统方式问题 | PTC 优势 |\n|------|------------|---------|\n| **批量数据处理** | 中间结果撑爆上下文 | 只返回聚合摘要 |\n| **多工具组合** | N 次推理延迟累积 | 1 次推理 + 代码执行 |\n| **条件逻辑** | 每步都需模型决策 | 代码自动处理分支 |\n| **并行调用** | 串行等待 | asyncio.gather 并行 |\n| **数据过滤** | 模型手动筛选 | 代码高效过滤 |\n\n### 5.3 成本对比示例(基于实际测试)\n\n以本文 notebook3.ipynb 中的**企业差旅费用审计**测试为例:\n\n**任务**:分析 8 名工程团队成员的 Q3 差旅费用是否超标\n\n**数据规模**:\n- 8 人 × 20-50 条费用明细 = **160-400 条费用记录**\n- 每条记录包含 15+ 个字段(expense_id、date、amount、category、status、merchant...)\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│ 实际测试数据对比 │\n├─────────────────────────────────────────────────────────────────┤\n│ │\n│ 非 PTC 模式 (以 Claude Sonnet 4.5 为例): │\n│ ├─ API 调用次数: 4 次 │\n│ ├─ Token 消耗: ~123,000 │\n│ ├─ 执行时间: 29s │\n│ └─ 所有费用明细进入上下文,模型手动筛选汇总 │\n│ │\n│ PTC 模式 (以 Claude Sonnet 4.5 为例): │\n│ ├─ API 调用次数: 4 次 │\n│ ├─ Token 消耗: ~12,900 │\n│ ├─ 执行时间: 19.4s │\n│ └─ 代码在沙箱中处理数据,只返回超标人员摘要 │\n│ │\n│ ═══════════════════════════════════════════════════════════ │\n│ Token 节省: 89.5% | 时间节省: 33% | 准确性: PTC✅ 非PTC❌ │\n│ │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n**成本估算**(以 Claude Sonnet 定价 $3/$15 per 1M tokens):\n\n| 模式 | Token 消耗 | 输入成本 | 输出成本 | 总成本 |\n|------|-----------|---------|---------|--------|\n| 非 PTC | ~123,000 | $0.369 | ~$0.15 | **~$0.52** |\n| PTC | ~12,900 | $0.039 | ~$0.02 | **~$0.06** |\n| **节省** | 89.5% | - | - | **~88%** |\n\n如果是生产环境每天执行 1000 次类似查询:\n- 非 PTC:$520/天 → **$15,600/月**\n- PTC:$60/天 → **$1,800/月**\n- **月节省:$13,800(88%)**\n\n## 六、100% Anthropic API 兼容:anthropic_api_converter\n\n如果你希望在 AWS Bedrock 上使用完全兼容 Anthropic API 的服务(包括 PTC),可以使用开源项目 [anthropic_api_converter](https://github.com/xiehust/anthropic_api_converter)。\n\n### 6.1 项目简介\n\n这是一个轻量级 API 转换代理服务,让你无需修改代码即可:\n\n- 在 **Claude Code** 中使用 Bedrock 上的 Qwen3-Coder 等模型\n- 在 **Claude Agent SDK** 中混合使用不同模型\n- 完整支持 **Programmatic Tool Calling** API\n\n### 6.2 核心特性\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│ anthropic_api_converter │\n├──────────────────────────────────────────────────────────────┤\n│ ✅ 零代码迁移 - 完全兼容 Anthropic API 格式 │\n│ ✅ PTC 支持 - 业界首个在 Bedrock 上实现兼容 PTC 的代理 │\n│ ✅ 多模型支持 - Claude/Qwen/DeepSeek/MiniMax... │\n│ ✅ 流式响应 - 支持 SSE 实时流式输出 │\n│ ✅ 工具调用 - 完整的 Function Calling 支持 │\n│ ✅ 企业级 - API Key 管理、速率限制、用量追踪 │\n└──────────────────────────────────────────────────────────────┘\n```\n\n### 6.3 快速使用\n\n```bash\n# 设置环境变量,让 Claude Code 通过代理使用 Bedrock 模型\nexport CLAUDE_CODE_USE_BEDROCK=0\nexport ANTHROPIC_BASE_URL=http://your-proxy-url.com\nexport ANTHROPIC_API_KEY=sk-xxxx\nexport ANTHROPIC_DEFAULT_SONNET_MODEL=qwen.qwen3-coder-480b-a35b-v1:0\n\n# 启动 Claude Code,自动使用 Qwen3-Coder\nclaude\n```\n\n### 6.4 PTC 配置\n\n```python\n# 在代理服务中启用 PTC\nENABLE_PROGRAMMATIC_TOOL_CALLING=True\nPTC_SANDBOX_IMAGE=python:3.11-slim\nPTC_SESSION_TIMEOUT=270\nPTC_EXECUTION_TIMEOUT=60\nPTC_MEMORY_LIMIT=256m\nPTC_NETWORK_DISABLED=True\n```\n\n## 七、总结\n\nProgrammatic Tool Calling 代表了 AI Agent 工具调用的新范式:\n\n1. **效率革命**:从 N 次推理降至 1-2 次,Token 消耗降低 37%+\n2. **代码编排**:用 Python 表达复杂逻辑,比自然语言更精确\n3. **上下文隔离**:中间数据不进入模型上下文,只保留关键输出\n4. **并行执行**:通过 asyncio.gather 实现真正的并行工具调用\n\n通过我们的 **Docker Sandbox 自托管方案**,这一能力不再是 Claude 专属:\n\n- ✅ 完全兼容官方 PTC 协议\n- ✅ 支持任意大模型(Qwen、DeepSeek、MiniMax...)\n- ✅ 私有化部署,完全可控\n- ✅ 自定义依赖包和执行环境\n\n**这是 Agent 工具调用从\"对话式\"向\"程序化\"演进的重要一步。**\n\n---\n\n## 参考资料\n\n1. **Anthropic 官方文档**\n - [Introducing advanced tool use on the Claude Developer Platform](https://www.anthropic.com/engineering/advanced-tool-use)\n - [Programmatic Tool Calling Documentation](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling)\n - [PTC Cookbook](https://github.com/anthropics/claude-cookbooks/blob/main/tool_use/programmatic_tool_calling_ptc.ipynb)\n\n2. **开源项目**\n - [Sandboxed PTC - Docker Sandbox 实现](https://github.com/xiehust/claude_ptc)\n - [anthropic_api_converter - Anthropic API 代理](https://github.com/xiehust/anthropic_api_converter)\n\n3. **相关技术**\n - [Building Effective Agents - Anthropic Research](https://www.anthropic.com/research/building-effective-agents)\n - [Code Execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp)\n\n---\n\n> **作者注**:本文代码示例均来自实际项目,可在 GitHub 仓库中找到完整实现。欢迎 Star 和贡献!\n"}}}} |