简要回答
Martin Fowler 提出用 DSL 替代自然语言作为 LLM 的输入/输出接口。DSL 语法严格、类型安全、可验证,消除了自然语言的歧义性。三种实现模式:DSL 作为中间表示(LLM 做翻译者)、DSL 作为输出约束(外部验证)、DSL 作为状态机(限制行为空间)。
标准回答
一、问题:LLM 使用中的不可靠性
LLM 在实际工程中面临严重的可靠性问题:(1) 输出格式不稳定——即使明确要求 JSON 输出,仍可能产生格式错误、字段缺失或类型不匹配;(2) 语义漂移——长对话中逐渐偏离原始指令;(3) 幻觉注入——不确定时"编造"看似合理但实际错误的数据;(4) 指令遵循不一致——相同指令在不同上下文或不同模型版本中产生不同行为。Martin Fowler 在 2026 年 7 月指出:这些问题的根源在于自然语言的固有歧义性——自然语言是给人理解的,不是给机器精确执行的。
二、DSL 的解决思路
DSL(Domain-Specific Language)是针对特定问题域的专用编程语言。核心论点是:用 DSL 替代自然语言作为 LLM 的输入/输出接口。DSL 具有以下特性使其比自然语言更适合与 LLM 交互:(1) 语法严格——每条语句都有明确的语法定义,不存在歧义;(2) 类型安全——字段类型(整数、字符串、枚举)在语言层面约束;(3) 可验证——输出可以通过语法检查器自动验证,错误立即可见;(4) 可组合——小语句可以组合成复杂表达,支持模块化设计。
三、三种实现模式
(1) DSL 作为中间表示(IR):用户用自然语言描述意图 → LLM 翻译为 DSL → DSL 由传统程序执行。LLM 的角色从"执行者"降级为"翻译者",大幅降低出错概率。适用于数据查询、配置生成等场景。(2) DSL 作为输出约束:LLM 直接生成结果,但输出必须通过 DSL 语法检查器。不合法的输出被拒绝并要求重新生成。适用于代码生成、报告生成等场景。(3) DSL 作为对话状态机:整个对话流程用 DSL 定义状态转移规则。LLM 在每个状态下只能产生特定类型的输出,状态转移由 DSL 规则控制。适用于客服对话、流程审批等场景。
四、设计原则
设计用于 LLM 交互的 DSL 时,Fowler 建议:(1) 最小化语法——语法应尽可能简单,减少 LLM 学习成本;(2) 语义透明——每条语句的含义应直观明确,避免隐式行为;(3) 错误友好——语法错误信息应包含修复建议,方便 LLM 自我纠正;(4) 渐进式复杂度——简单任务用简单语法,复杂任务用高级语法;(5) 与 LLM 能力对齐——考虑上下文窗口限制和 token 效率。
五、工程实践
落地步骤:(1) 识别高频任务——找出最常让 LLM 执行的任务类型;(2) 定义 DSL 语法——为每类任务设计专用 DSL(可用 ANTLR、Tree-sitter 生成解析器);(3) 构建验证管道——LLM 输出 → DSL 语法检查 → 语义验证 → 执行,验证失败时自动重试(最多 3 次);(4) 建立 DSL 库——将常用模板沉淀为团队资产。DSL 不需要从零发明——SQL、GraphQL、JSON Schema 等都是成熟的 DSL,可以直接作为 LLM 的输出约束。
六、局限性与权衡
DSL+LLM 模式并非万能药:(1) 学习成本——团队需要学习新 DSL;(2) 维护成本——DSL 需要版本管理和向后兼容;(3) 灵活性损失——严格性意味着无法处理"灰色地带"的任务;(4) 过度工程化风险——简单任务用自然语言 prompt 已经足够好。建议在以下场景优先考虑:任务高频重复、错误代价高、需要审计追踪、多人协作。
常见误区
⚠️ 常见踩坑
误区一:DSL 可以完全消除 LLM 的不可靠性——DSL 显著提升可靠性,但不能消除。LLM 仍可能在 DSL 翻译中犯错,需要外部验证。
误区二:为所有任务都设计 DSL——简单任务用自然语言 prompt 已经足够好,DSL 适合高频重复、错误代价高的场景。
误区三:从零发明 DSL——SQL、GraphQL、JSON Schema 等都是成熟的 DSL,可以直接作为 LLM 的输出约束,不需要从零发明。
追问
追问 1:三种 DSL 实现模式如何选择?
选择取决于任务特性和可靠性需求:(1) DSL 作为 IR——可靠性最高(LLM 只做翻译,执行由传统程序完成),但灵活性最低。适合数据查询、配置生成等"翻译简单、执行复杂"的场景。(2) DSL 作为约束——可靠性高(外部验证保证格式正确),灵活性高(LLM 自由生成内容)。适合代码生成、报告生成等"内容多样、格式严格"的场景。(3) DSL 作为状态机——可靠性最高(限制行为空间),灵活性最低。适合客服对话、流程审批等"流程固定、变化少"的场景。
追问 2:如何验证 DSL 输出的正确性?
DSL 输出验证分两层:(1) 语法验证——使用 ANTLR/Tree-sitter 生成的解析器检查输出是否符合 DSL 语法定义。语法错误立即返回给 LLM 并要求重新生成。(2) 语义验证——检查 DSL 语句的语义是否合理。例如:查询的表是否存在、字段类型是否匹配、操作是否在权限范围内。语义验证需要领域特定的规则引擎。验证失败时自动重试(最多 3 次),每次重试将错误信息包含在 prompt 中帮助 LLM 自我纠正。
🔗 相似问题
同一考点的不同问法,换着练更稳
没找到想看的面试题?把你想看的告诉我们 →
延伸学习
按主题分类的相关资源,便于系统复习
