Token Lab搜索

APPLIED AI / READ → RUN → MODIFY → TEST

工具型助手:验证、执行与追踪

实现将工具调用提议转为有边界、可检查动作的执行层。

学习指南与本课目录LEARNING CONTRACT

理解 → 实现 → 研究

目标:解释本课机制、复现一个例子、测试一个失败案例。读完不自动代表掌握。

1 · 你在哪里会用到它

ChatGPT 可以连接应用,OpenAI API 文档也把 function calling 描述为多步交互:应用执行工具,再返回结果。本例接收预写调用列表,运行本地订单查询,演示执行控制,而非自主规划或 ChatGPT 连接器内部实现。

官方产品/API 文档 ↗

来源核对日期 2026-10-25。产品行为来自官方公开说明,下方代码是独立教学实现。

2 · 关键工程决策

模型输出工具名和参数只是提议,不是权限。分派前验证允许列表和参数契约,限制实际执行次数,按调用 ID 缓存结果,并拒绝同 ID 搭配不同参数。轨迹应区分阻止、无效、重放与执行。只读样例让你无需发消息或改真实系统即可测试边界。

  1. call-1 使用 lookup_order 查询 A17,执行一次。
  2. 重复 call-1 返回缓存结果,不额外消耗执行预算。
  3. delete_order 不在允许列表内,被阻止。
  4. 最终 executed 为 1。将 budget 改成 0,查询在执行前被阻止。

3 · 运行并修改输入

完全在浏览器运行,无模型调用、网络请求、API Key 或上传。输入为 JSON,这是确定性组件演示,不是生成式助手。

{
  "executed": 1,
  "trace": [
    {
      "id": "call-1",
      "status": "executed",
      "result": {
        "status": "shipped",
        "tracking": "DEMO-123"
      }
    },
    {
      "id": "call-1",
      "status": "replayed",
      "result": {
        "status": "shipped",
        "tracking": "DEMO-123"
      }
    },
    {
      "id": "call-2",
      "status": "blocked_tool"
    }
  ]
}

初始输出是构建时实际计算的示例结果。修改后点击运行以计算你的结果。

4 · 完整源代码

需要现代浏览器或 Node.js 18+。下载模块,将下方 runner 存为同目录 demo.mjs,执行 node demo.mjs,无需 npm 依赖。

下载源代码 ↓
// Execute a supplied tool plan against a local read-only fixture. No agent/LLM.
export const example = {budget: 2, calls: [
  {id: 'call-1', name: 'lookup_order', arguments: {order_id: 'A17'}},
  {id: 'call-1', name: 'lookup_order', arguments: {order_id: 'A17'}},
  {id: 'call-2', name: 'delete_order', arguments: {order_id: 'A17'}}
]};
export function run({budget, calls}) {
  if (!Number.isInteger(budget) || budget < 0 || budget > 10) throw Error('budget must be 0–10');
  if (!Array.isArray(calls) || calls.length > 20) throw Error('At most 20 calls');
  const orders = new Map([['A17', {status: 'shipped', tracking: 'DEMO-123'}]]);
  const cache = new Map(); let executed = 0;
  const trace = calls.map(call => {
    if (!call || typeof call.id !== 'string' || typeof call.name !== 'string') return {status: 'invalid_call'};
    if (call.name !== 'lookup_order') return {id: call.id, status: 'blocked_tool'};
    const args = call.arguments;
    if (!args || typeof args !== 'object' || Array.isArray(args) ||
        Object.keys(args).length !== 1 || typeof args.order_id !== 'string') return {id: call.id, status: 'invalid_arguments'};
    const fingerprint = JSON.stringify([call.name, args.order_id]);
    if (cache.has(call.id)) {
      const prior = cache.get(call.id);
      return {id: call.id, status: prior.fingerprint === fingerprint ? 'replayed' : 'id_conflict',
        ...(prior.fingerprint === fingerprint ? {result: prior.result} : {})};
    }
    if (executed >= budget) return {id: call.id, status: 'budget_exhausted'};
    executed++;
    const result = orders.get(args.order_id) || {status: 'not_found'};
    cache.set(call.id, {fingerprint, result});
    return {id: call.id, status: 'executed', result};
  });
  return {executed, trace};
}
import {run, example} from './bounded-tools.mjs';
console.log(JSON.stringify(run(example), null, 2));

5 · 失败案例与生产差距

缓存仅存在于一次运行中。真实有副作用工具需要持久幂等、授权、超时、取消和审计轨迹。重放相同 ID 与使用新 ID 重复请求不同。只读状态返回不能被描述成订单已修改的证据。

6 · 你的实现练习

测试未知工具、多余参数键、相同 ID 查询不同订单及预算耗尽。在加入任何写操作前,先设计超时与审批状态机。

交付修改后的代码、至少一个成功与一个失败案例,并解释测试不能证明什么。

继续学习关联知识点 →
← 全部实战教程
MATHEMATICAL REVIEW · 2026-10-26

假设、参考实现与验收

只有实际执行消耗预算。重放要求调用 ID 和参数一致。白名单失败阻止该调用,不自动终止整个给定计划。

已复核实现、不变性及声明的证据边界;保留原有验收测试。

运行前:预测一个边界情况

只有实际执行消耗预算。重放要求调用 ID 和参数一致。白名单失败阻止该调用,不自动终止整个给定计划。

提示:隔离假设

固定基线输入,只改变一个参数或边界;同时比较数值与声明单位。单例通过仅验证该样例。

最小可运行算例

将算例及所链接模块保存在同一目录。使用 Node.js 22 或更高版本,然后运行 node application-bounded-tools.mjs. 无需第三方运行依赖。

import {run,example} from './application-bounded-tools-core.mjs';
console.log(run(example));

测试与迁移

只有实际执行消耗预算。重放要求调用 ID 和参数一致。白名单失败阻止该调用,不自动终止整个给定计划。

在下方笔记记录输入、代码版本、期望值和实测值;再构造违反上述假设的反例,解释原结论为何不再成立。

下载完整代码包(.tar.gz) · 完整参考代码与回归检查

预测、检验与证据记录

展开答案前先预测一个结果;练习后记录差异和迁移测试。记录仅存本地,在不同语言版本间共用。

打开记录/导出/清除 →

数学复核范围逐篇记录,不代表完成论文实证复现;可在笔记中记录疑似错误。 复核范围