第10章实践:受控学习便签助手——工具调用、沙盒与权限边界

预计 2×45 分钟。先完成"观察与运行",再完成"单变量修改与解释"。


第1步:需求与背景

为什么做这个

当你对AI助手说"帮我创建一个学习笔记",你期望它真的创建了一个文件。但大语言模型本身没有任何文件操作能力——它只能生成文字。那文件到底是谁创建的?

答案是:模型提出请求,宿主程序执行请求。模型输出的是一段结构化的 JSON("我想调用 create_note 工具,参数是这些"),然后由运行在电脑上的程序检查这个请求是否合法、是否安全,最后才真正执行。

这就是工具调用(tool calling)的核心机制:模型没有魔法,它只是"提议",真正"执行"的是你写的代码。

项目目标

制作一个受控学习便签助手:

明确不做

系统全景

自然语言任务
    ↓
模型生成 tool_call JSON(提议)
    ↓
Schema 校验 → 权限检查 → 路径安全检查 → 内容安全检查
    ↓(全部通过)
沙盒工具执行(创建文件 / 列出文件 / 计算结果)
    ↓
审计日志记录:提议、校验结果、执行结果、时间戳
    ↓
人工确认:日志证明已执行 ≠ 模型声称已创建

第2步:数据与信号

工具定义长什么样

打开 data/tool_schemas.json,你会看到三个工具的完整定义。每个工具包含:

JSON Schema:给参数画边界

JSON Schema 是一种"参数的规则说明书"。以 create_note 为例:

{
  "type": "object",
  "properties": {
    "filename": {
      "type": "string",
      "pattern": "^[a-zA-Z0-9_\\u4e00-\\u9fa5\\-]+\\.md$"
    },
    "content": {
      "type": "string",
      "maxLength": 500
    }
  },
  "required": ["filename", "content"],
  "additionalProperties": false
}

这段 Schema 说了什么?

  1. filename 必须是字符串,且只能包含字母、数字、中文、下划线、短横线,必须以 .md 结尾
  2. ✅ 今日清单.md — 合法
  3. ❌ ../../etc/passwd — 包含路径分隔符和 ..
  4. ❌ notes.txt — 不是 .md 后缀
  5. content 必须是字符串,不超过 500 字符
  6. ✅ "复习第10章要点" — 合法
  7. ❌ 一段 1000 字符的长文 — 超过长度限制
  8. additionalProperties: false — 不允许出现未声明的字段
  9. ✅ {"filename": "a.md", "content": "hi"} — 合法
  10. ❌ {"filename": "a.md", "content": "hi", "shell": true} — 多了未声明字段

全局安全规则

除了每个工具自己的 Schema,还有全局规则:

{
  "max_content_length": 500,
  "allowed_extensions": [".md"],
  "blocked_patterns": ["..", "/", "\\", "<script", "import ", "exec(", "eval(", "os.", "sys.", "__"],
  "audit_log": "audit.log"
}

这些规则在所有工具调用时都会检查,不管模型怎么提议。


第3步:AI原理

工具调用的完整流程

工具调用不是"模型直接操作文件",而是分四个阶段:

阶段1:提议(Proposal)

模型收到用户请求后,不是直接写文件,而是生成一段结构化 JSON:

{
  "tool": "create_note",
  "arguments": {
    "filename": "今日清单.md",
    "content": "1. 复习工具调用\n2. 完成攻击测试\n3. 写实验报告"
  }
}

这只是一段文字——模型"说"它想调用这个工具,但它自己什么都没做。

阶段2:校验(Validation)

宿主程序收到这段 JSON 后,依次检查:

  1. Schema 校验:参数类型、格式、长度是否符合工具定义?
  2. 权限检查:这个工具是否有权做请求的操作?
  3. 路径安全:文件名是否包含路径穿越(..、/、\)?
  4. 内容安全:内容是否包含注入攻击(<script>、exec())?

任何一步失败,调用就被拒绝,不会执行。

阶段3:执行(Execution)

只有全部校验通过,宿主程序才在沙盒目录中真正执行操作:

# 伪代码
sandbox_path = SANDBOX_ROOT / validated_filename
sandbox_path.write_text(validated_content, encoding="utf-8")

注意:文件写入操作是宿主程序做的,不是模型做的。模型只是"提议"了参数。

阶段4:日志(Logging)

每次调用(无论成功或失败)都写入审计日志:

[2026-08-19T10:30:00] PROPOSE tool=create_note filename=今日清单.md → VALID → EXECUTED
[2026-08-19T10:30:05] PROPOSE tool=create_note filename=../../etc/passwd → REJECTED(reason=path_traversal)

"模型声称"vs"日志证明"

这是本章最核心的区别:

模型声称 日志证明
来源 模型输出的文字 宿主程序的执行记录
可靠性 可能出错、幻觉 来自真实文件系统操作
例子 "我已经创建了笔记" audit.log 第5行:create_note 今日清单.md → EXECUTED

模型可能说"我已经创建了文件",但实际上:
- 参数校验失败了,文件根本没创建
- 模型产生了幻觉,并没有真正发起工具调用
- 工具执行时出错了(磁盘满、权限不足)

只有审计日志才是执行证据。

为什么需要这么多层防护

防护层 防什么 如果缺少
JSON Schema 参数格式不合法 模型可能传入错误类型的参数
路径检查 路径穿越攻击 模型可能被诱导写入系统文件
内容检查 文档注入 笔记内容可能包含恶意代码
额外属性检查 未声明字段 模型可能被诱导传入 shell: true
沙盒隔离 越权操作 文件可能写入沙盒外的目录
审计日志 事后追溯 出了问题无法定位原因

第4步:协同开发

使用 Qwen Code 完成以下任务(选择一项):

任务A:修改一条 schema 限制
- 把 create_note 的内容长度限制从 500 改为 1000
- 或者把文件名规则改为也允许 .txt 后缀
- 先预测:这个修改扩大了什么能力?新增了什么风险?需要增加什么测试?

任务B:新增一个低风险工具 append_checklist
- 功能:向已有笔记末尾追加一行待办事项
- 要求:定义完整的 JSON Schema、权限和风险等级
- 先预测:这个工具和 create_note 有什么区别?需要哪些额外测试?

协同流程:
1. 在 Qwen Code 中描述你的选择(原始意图)
2. 查看 Qwen Code 的修改建议(AI方案)
3. 审查差异,接受或改写(人工审查)
4. 运行修改后的代码(实际变更)
5. 对比预测和实际结果(最终判断)


第5步:测试与边界

必测项目

测试 输入 预期结果 防御层
正常-创建 create_note("清单.md", "复习要点") 文件创建,日志记录 EXECUTED —
正常-列出 list_files() 返回文件列表 —
正常-计算 calc("2+3*4") 返回 14 —
攻击-路径穿越 create_note("../../etc/passwd", "hacked") REJECTED: path_traversal 路径检查
攻击-超长内容 create_note("a.md", "x"*1000) REJECTED: content_too_long Schema maxLength
攻击-未声明字段 create_note("a.md", "hi", shell=true) REJECTED: additional_properties Schema additionalProperties
攻击-文档注入 create_note("a.md", "<script>alert(1)</script>") REJECTED: blocked_pattern 内容检查
攻击-危险计算 calc("os.system('rm -rf /')") REJECTED: invalid_expression Schema pattern
离线 无模型可用 使用预录 tool_call JSON 完成全部测试 离线兜底

人工兜底


第6步:交付与验收

交付物

  1. 正常工具轨迹:至少3次正常调用的完整四段证据(提议→校验→执行→日志)
  2. 攻击防御日志:至少5种攻击的防御结果,每种包含攻击输入、拒绝原因和防御层
  3. Schema 差异记录:B档修改的 before/after 对比,新增能力和风险分析
  4. audit.log:完整的审计日志文件
  5. 人工确认记录:至少一次"模型声称 vs 日志证明"的对比分析

验收标准


第7步:迁移与拓展

核心方法迁移

本章学到的"模型提议→程序校验→沙盒执行→审计日志"模式,可以迁移到:

  1. 真实产品中的AI助手:ChatGPT 的 Code Interpreter、Claude 的 Computer Use 都采用类似机制——模型生成工具调用,平台校验并执行
  2. 企业内部的AI工作流:AI生成SQL查询 → DBA审核 → 只读副本执行 → 审计日志
  3. 智能家居控制:AI提议"把空调调到26度" → 权限检查(是否在允许时间) → 设备执行 → 操作日志

拓展任务(选做)

与后续章节的衔接