考察点
这道题出自腾讯大模型应用岗一面,是 Function Calling 的边界认知题。第一问考你是否理解「模型只生成、不执行」这条安全底线;第二问更刁钻,tool_choice=required 是个容易想当然的参数,面试官想看你是否踩过「强迫调用导致幻觉参数」的坑。追问常往幻觉调用的防护、强制指定函数的合理场景走。
参考答案
toolcalls 不是直接执行的
模型返回的 tool_calls,本质是一段结构化文本——和模型输出的其他 token 没有物理区别,只是格式遵守了工具 schema。它表达的是「模型认为应该这样调用」,不是「调用已经发生」。
执行链路完整是这样的:应用拿到 tool_calls 后,先按注册的工具白名单匹配函数名,匹配不上就是幻觉调用,直接拦截;然后解析 arguments 字符串,按 JSON Schema 做参数校验,类型错、枚举越界、必填缺失都在这层拦;接着是业务层校验——当前用户有没有权限调这个工具、参数指向的资源是否合法(比如模型把 user_id 填成了别人的);全部通过才执行,执行结果回填给模型。
为什么要这么多层?因为模型是概率系统,它的输出不可信是默认前提。如果 tool_calls 直通执行,等于把数据库写权限、消息发送权限交给一个会产生幻觉的组件。我见过真实的坑:一个「删除过期会话」的清理工具,模型在参数里把 before_date 填成了未来时间,要不是业务校验层挡了一道「删除范围超过阈值需人工确认」,半张表就没了。应用侧是唯一的执行网关,这不是架构洁癖,是生产安全的底线。
toolchoice 的四种语义
tool_choice 控制模型的调用决策,取值有四种:
auto(默认):模型自己判断调不调、调哪个。对话类场景的标准选择。none:禁止调用,即使传了 tools 也只输出文本。适合临时关闭工具能力做 A/B,或防注入场景。required:必须调用一个工具,但不指定哪个。- 指定函数名:强制调用某一个工具。
required 的坑:被迫编造幻觉调用
设想用户问「你怎么看最近的 AI 新闻」——一个纯观点问题,不需要任何工具。但 tool_choice=required 下,模型被剥夺了「不调用」的选项,它只能硬选一个工具编造参数调出去:可能把「AI 新闻」塞进 get_stock_price(company="AI新闻") 这种驴唇不对马嘴的调用。后果不只是这次调用无意义——如果工具是写操作,幻觉参数就产生了脏数据;如果是付费 API,就是白烧钱;回填结果后模型还要基于这个文不对题的结果强行圆一个回答,回答质量也塌了。
实践建议:required 和指定函数只用在「语义上必然有工具」的场景——结构化信息抽取(强制调 save_extracted_record 把结果吐成 JSON)、表单填充、NL2SQL 这类输入输出都收口的任务。开放对话场景一律 auto,再靠 system prompt 引导调用倾向。更稳的做法是在 FC 之前加一层轻量意图路由,先判断「这个问题需不需要工具」,需要才带上 tools 请求模型,从源头避免误触发。
可能的追问
- 怎么系统性减少幻觉调用? 答:三层——工具 description 写清「什么时候该用、什么时候不该用」;应用侧白名单加参数校验兜底;观测上统计每个工具的调用成功率和纠错率,异常工具下线整改。
- 强制指定某个函数的场景有哪些? 答:结构化抽取是最典型的——把非结构化文本强制过
submit_extraction工具输出 JSON,等于把 FC 当类型安全的解析器用,比让模型直接输出 JSON 稳定得多。 - tool_choice=none 有什么用? 答:复用同一套带工具的对话流水线,但某些请求(如敏感问题、注入嫌疑输入)临时禁用工具;也用于对比实验,量化工具对回答质量的影响。