Skip to content

决策不是执行:手写有限工具循环:练习答案 ​

参考实现 ​

保留正文定义,追加:

python
def execute(call):
    if call["name"] != "convert":
        raise ValueError("unknown tool")
    c = call["args"].get("c")
    if set(call["args"]) != {"c"} or type(c) not in (int, float):
        raise ValueError("invalid arguments")
    return {"fahrenheit": c * 9 / 5 + 32}

def run(policy, limit=3):
    history = [{"role": "user", "content": "转换 20 摄氏度"}]
    for _ in range(limit):
        action = policy(history)
        if action["type"] == "final":
            return {"status": "completed", "history": history, "answer": action["text"]}
        history.append({"role": "assistant", "call": action})
        try:
            result = {"ok": True, "data": execute(action)}
        except ValueError as error:
            result = {"ok": False, "error": str(error)}
        history.append({"role": "tool", "call_id": action["id"], "content": result})
    return {"status": "budget_exhausted", "history": history}

def repeats(history):
    return {"type": "call", "id": str(len(history)), "name": "convert", "args": {"c": 0}}
r = run(repeats, limit=2)
assert r["status"] == "budget_exhausted"
assert sum(m["role"] == "tool" for m in r["history"]) == 2
try:
    execute({"name": "convert", "args": {"c": True}})
except ValueError as e:
    assert str(e) == "invalid arguments"
else:
    raise AssertionError("bool accepted")
print("bounded and validated")

Python 的 bool 是 int 子类,所以这里用 type 精确检查,不能随意换成只判断 isinstance(c, int)。

返回正文

深化页面练习解答 ​

Agent 协议 ​

跨任务的结果必须拒绝回填;并行工具按 call_id 配对,部分失败应保留每个工具的独立状态。call ID 只关联模型调用,不能替代持久化业务幂等键。

Agent 状态与停止条件 ​

安全拒绝、用户取消和预算耗尽应优先于模型声称的完成。工具执行未知时先查询状态,明确失败才进入可恢复的重规划;越权和取消直接结束。

工具边界 ​

删除操作的确认应绑定具体用户、字段和有效期。工具结果即使包含提示注入文本,也只是数据,不能改变服务端白名单、身份和权限。沙箱、审计和租户隔离必须由执行器及基础设施保证。

用心记录每一步成长