先记住这个答案
enum 的可靠性来自双重保障:生成阶段,模型依据 schema 调整输出分布,使非法 token 概率被压低;校验阶段,服务端可逐字比对,拒绝任何不在列表中的值并返回结构化错误。描述文案只影响模型的理解倾向,模型可能因措辞、大小写或同义词产生偏离。更重要的是,enum 让工具的行为契约可被程序化验证,不依赖模型对文字的解释能力。
- enum 提供校验层硬约束,描述只作软提示
- enum 可缩小模型采样空间,降低非法输出概率
- enum 值需与业务语义精确对应,过多时需权衡
enum 在生成与校验两阶段同时生效
语言模型在解码时根据工具 schema 构建上下文,enum 字段相当于给出一个显式的候选词表。模型在生成参数时,会优先从这个有限集合中抽取,因为 schema 里的 enum 列表被视为强约束,其概率分布被重塑,非法字符串的生成概率大幅降低,尽管并非绝对为零。
服务端拿到模型产出的参数后,JSON Schema 校验器会进行严格比对,如果值不在枚举列表内,校验立即失败并返回错误。这一步不依赖于模型自我修正,运行时的行为是确定性的。描述文案则没有这样的结构,它只是自然语言,模型可能忽略细节或产生语义等价但不匹配的变体。
排序工具降序参数的意外输入
假设一个内容搜索工具,参数 order 描述为“升序或降序,请用 asc 或 desc”。用户问“按最近时间从新到旧排序”,模型有时会输出 order: "descending",甚至 order: "newest"。这些值语义上正确,但不符合约定,后端如果直接执行会导致默认排序或报错。
把 order 在 schema 中定义为 enum: ["asc", "desc"]。模型在解码时会受到 enum 列表的强引导,更倾向于从这两个值中选择,输出 descending 的可能性很低;即使模型仍输出非法值,服务端的 schema 校验会立刻返回错误(如“order 必须是 asc 或 desc”),Agent 可以据此让模型重试。描述文案无法提供这种硬性保证,只能靠模型自觉。
enum 的适应范围与代价
当枚举值本身不封闭,例如允许用户自定义标签时,强行用 enum 会阻断合理输入,此时应使用 string 加长度限制和格式提示。另外,如果枚举值数量巨大(如几百个城市名),enum 会显著增加 token 占用,每次请求都携带完整列表反而拉高成本,还可能干扰模型对语境的感知。
枚举值的语义可读性也很关键。若值是 1、2、3 这类无意义的数字,建议辅以描述说明对应关系,但校验错误信息需要同时给出映射,否则模型难以自我纠正。因此使用 enum 时,应让每个值都有清晰、不重叠的语义,并在描述中解释当某个值不可用时的替代方案。
容易答错的地方
- 描述能代替enum
- 描述只是改变模型的“期望”,不构成约束。实践中模型输出不在描述指定范围内的值的频率仍然存在,而enum可以从机制上降低这种频率,并在校验时兜底,二者不能等同。
- enum保证模型不会输出非法值
- enum并非绝对限制解码,模型仍有小概率输出不在列表中的值,可能是格式化噪声或近似拼写。因此服务端校验不可省略,enum只是提高合规率并统一错误出口。
面试官还会怎么问?
enum 对模型输出的影响能完全替代运行时校验吗?
不能。模型解码受多种因素影响,即使enum缩小空间,实践中仍会出现非法值,尤其当上下文干扰较强或模型较小时。运行时校验是最后防线,两者必须共存。
当枚举值数量多大时需要放弃enum?
当枚举值数量较多时,需要权衡 token 成本,若值可预测且变化频繁,可改用正则或外部字典校验。具体阈值没有绝对数字,取决于模型上下文预算和业务容错度。
enum值冲突时如何配合描述?
描述需为每个enum值提供语义解释和适用条件;错误信息也要包含合法值列表及含义,这样模型才能根据错误自动选择正确的枚举值,而不是盲目重发。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。