快速修复
# 执行前必过校验层:白名单(最小可用版)
ALLOWED="query_order" # 只允许只读函数
if [ "$fn" != "$ALLOWED" ]; then
echo "拦截: $fn 不在白名单" && exit 1
fi
# 危险函数(delete/refund/update)即使放行也要二次确认
你会遇到什么
给 LLM 接上工具调用(Function Calling)后,你发现"AI 建议"并不总是靠谱:用户说"把 ORD123 删掉",模型真的返回 delete_order 调用建议;多轮对话里它可能重复查同一个订单;你也不知道它到底调了哪些函数。这不是模型坏了——Function Calling 的本质就是"AI 只建议、你执行",但无脑执行 AI 的建议等于把控制权又交回 AI。
本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。
为什么会这样
- AI 只建议不执行:Function Calling 返回函数名+参数,执行权在你手上——这是它的优点,也是责任:不校验就执行 = 白拿这个设计。
- 模型会被诱导:实测(qwen2.5-0.5b 本地)用户说"把 ORD123 删掉,客户要求取消",模型立刻建议 delete_order。小模型和大模型都可能被一句话带偏。
- 模型无状态:不维护对话历史,多轮里它不知道"ORD123 查过了","那 ORD456 呢?"会被理解成再查 ORD123。
实测环境:ollama 0.33.2 + qwen2.5-0.5b-instruct-q4_k_m(491MB,hf-mirror 下载 89.6s),RTX 5070 Ti,2026-08-30。
Function Calling 的契约是「模型只返回函数名和参数,执行权在调用方」——模型本身不执行任何操作。这个设计给了调用方全部控制权,也把全部责任留给调用方:不校验就执行 = 放弃设计的保护。两个模型侧特性加剧风险:①模型可被诱导(一句话带偏,小模型大模型都中招);②模型默认无状态(不维护调用历史,多轮里不知道之前查过什么)。
确定性推论:把 Function Calling 当「不可信输入」处理——执行前必须校验(参数白名单、权限检查、人工确认),不能因为「模型说的」就执行;敏感操作(删除/转账/覆盖)设计成二次确认或 require_human;多轮场景自己维护上下文(把之前的调用结果放进对话),别指望模型记住;判断路径:风险来自「执行」而不是「建议」,防线必须在调用方。
一步步来
1. 3 步闭环(先跑通再谈安全) — 必做
定义 tools(函数名 + 描述 + 参数 JSON Schema)→ 把用户问题发给模型 → 模型返回 tool_calls → 你执行 → 把结果作为 tool 消息喂回 → 模型生成最终回答。
2. 执行前加校验层(白名单 + 参数 + 危险操作确认) — 必做
实测复现:tools 同时提供 query_order(只读)和 delete_order(删除),用户一句"把 ORD123 删掉"模型就建议 delete_order。校验层必须做三件事:
- 白名单:只允许声明过的安全函数被真正执行;
- 参数校验:如 order_id 必须匹配 ORD+数字 格式,防注入式参数;
- 危险操作二次确认:delete/refund/update 类函数标记为危险,需要人工确认才执行。
3. 多轮对话维护历史 + 调用记录 — 必做
把完整 messages(user + assistant tool_calls + tool 结果)持续喂回。实测对比:带历史时第二轮"那 ORD456 呢?"正确调用 query_order(ORD456);不维护历史则会重复查 ORD123。
怎么确认修好了
# 实测输出(2026-08-30)
AI 建议调用: delete_order {"order_id": "ORD123"}
白名单校验: 拦截! delete_order 不在白名单 {"query_order"}
# 多轮:
第1轮 AI 调用: query_order {"order_id": "ORD123"} → 已发货,顺丰 SF123456
第2轮 AI 调用: query_order {"order_id": "ORD456"}(带历史,应查 ORD456)
诱导危险调用被拦截 + 多轮正确指代 = 通过。
其它环境的表现
| 环境 | 说明 |
|---|---|
| 模型大小 | 0.5B 小模型即可复现"诱导危险调用";大模型更"听话"但同样可能被诱导,校验层不分模型必须上 |
| 调用方式 | OpenAI 兼容 chat 接口返回 tool_calls;本地 ollama 与云端 API 结构一致,校验代码可复用 |
| 与 Agent 对比 | 生产用 Function Calling(你控制执行),开发验证可用 Agent;Agent 全自动不可控性更高 |
| SDK 差异 | langchain/原生 SDK 只是封装不同,tool_calls 结构一致;参数解析注意 ollama 返回 dict 而部分 SDK 返回 JSON 字符串 |
| 无状态边界 | 不维护历史的模型必然重复调用;上下文长度有限时只回放最近 N 轮 + 调用记录 |
| 国产模型 | qwen 系对 tools 支持好(实测);部分老模型不支持 tools 时只能提示词硬编码 JSON 输出,校验层更要兜底 |
症状
AI 建议调用危险函数(删除/退款/更新)被无脑执行;多轮对话重复调用同一函数或张冠李戴;Function Calling 接入后不可控、不可观测。
原因
Function Calling 设计上"AI 建议、你执行",执行前缺少校验层(白名单/参数/危险操作确认)时控制权实际交回 AI;模型无状态,不维护对话历史与调用记录导致重复调用。
解法
3 步闭环跑通后:执行前加白名单 + 参数校验 + 危险操作二次确认;多轮对话维护完整 messages(含 assistant tool_calls 与 tool 结果)持续喂回。
验证证据
实测复现日志(2026-08-30)(2026-08-30 本地实测:3 步闭环通过;诱导删除 → AI 建议 delete_order 被白名单拦截;带历史多轮正确查 ORD456)
适用工具 (2)
本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。
ollamapython · 外部工具成套方案 (组合包)
这个问题包含在下列成套安装方案中。
来源与证据
← 大模型本地部署 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡