首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

大语言模型:下一代 DSL 编写者

摘要

向前沿大语言模型索要 Python 代码,你就会得到 Python 代码。向它索要团队自定义的标记语言,你得到的只会是“貌似”标记的东西:凭空发明的关键字、猜出来的参数名以及规范中从未出现过的语法结构——而模型输出这些内容时还一副笃定无误的样子。人们下意识的补救办法是使用更多的提示词、更长的上下文和更好的检索手段。真正的治本之策是在大模型接触到你的语言之前就敲定设计方案:从一开始就不要使用外部语法...

DSL Python TDG RAG API 向前沿大语言模型索要 你就会得到 向它索要团队自定义的标记语言 你得到的只会是 标记的东西
2026-09-23 1 阅读 约10分钟阅读 作者: Irakli Betchvaia
分享:
字号:
向前沿大语言模型索要 Python 代码,你就会得到 Python 代码。向它索要团队自定义的标记语言,你得到的只会是“貌似”标记的东西:凭空发明的关键字、猜出来的参数名以及规范中从未出现过的语法结构——而模型输出这些内容时还一副笃定无误的样子。人们下意识的补救办法是使用更多的提示词、更长的上下文和更好的检索手段。真正的治本之策是在大模型接触到你的语言之前就敲定设计方案:从一开始就不要使用外部语法。这个方案有个名字:类型化领域锚定(Typed Domain Grounding,TDG)。它可以用你现有的类型系统马上落地实现。 流利度即频率 大模型能熟练编写 Kotlin、TypeScript、Python 和 SQL 代码,最主要的原因是:这些语言在训练数据中出现了数百万次。粗略来看,语法能力本质上是训练数据出现频次的函数——代码大模型基准测试直接记录了这种关系:按频率和流行度对语言分类,结果显示低资源语言对应的模型表现性能会随之下降[8]。语料密集之处,生成结果更为可靠;语料稀疏之处,生成结果会退化为东拼西凑的模仿,但输出语气不变,看起来依旧信心十足。正因为没有明显的失败信号,这种失败才如此容易被忽略。 从大模型的视角来看,每一门全新设计的外部领域特定语言,其精确语法在训练语料中的出现频次都等于零。尽管如此,大模型通常仍能从它见过的、语法相近的文法、API 和标记符号中继承可迁移的先验知识。但这种迁移并不能解决问题;恰恰相反,它正是下文所说的插值失效背后的根源。 当模型遇到陌生的标记语法时,并不会直接抛出明显的错误,而是会做插值推断。它会悄悄挪用 Mermaid 或 PlantUML 里的箭头语法;调用你的 API “理应存在”但实际并不存在的 addRelation 或 withLabel;或是给只接受两个入参的结构传入三个参数——只因为某个语法相近的同类语法是三参数的。每一处错误都是大模型基于语料算出的最高概率补全,但被用在了语料库里从未出现过的语言上。输出的文本行文流畅、缩进工整,但却是错的。 传统领域特定语言的一个优点反而让这个问题变得更糟:宽松容错。绘图工具与配置解析器在设计上本就具备容错性——遇到无法识别的代码行就直接跳过,按最优猜测进行渲染,对拼写错误不会抛出报错。对人类使用者而言,这是友好的特性;但对于 AI 来说,这就是一个陷阱门。 大模型生成了一张包含十个类的图,其中有一个凭空发明的关系关键字。解析器跳过了那一行。最终进入设计文档的是一张看起来专业、实则缺少一条关联关系的图。 人类如果输入错误,会察觉到问题,因为人类本意就是要建立这个关联关系。但大模型不存在任何意图;下游工程师被九个正确的类和整洁的排版所麻痹,根本不会怀疑这张图是不完整的。 锚定语言,而不仅仅是事实 在日常的大模型工程中,“锚定”几乎已经成了 RAG 的同义词。检索相关文档,放入上下文,大模型的输出就能锚定在真实来源上。这是数据空间层面的锚定,用来约束模型对客观世界的描述。但这对我们的问题毫无帮助:即便大模型上下文中的事实完美无误,它仍然可能生成语法凭空捏造的 DSL 语句。 在没有检索的情况下被要求绘制支付系统图,大模型可能让支付服务直接写入账本,而实际上两者之间存在消息队列——语法无可挑剔,内容却是错的。检索可以修复这个问题。但当文档已经放进上下文后,大模型虽然能够正确描述队列这一组件,却会用一种一知半解的标记语法来表达。在这种情况下,内容是对的,标记语法却是错的。再多的检索也无济于事,因为问题根源在于模型对目标语言的掌握能力上,而不在于它的知识。 类型化领域锚定的是另一个维度。它不是把答案的内容锚定在检索到的数据中,而是把标记符号锚定在模型本就懂得如何生成的结构之中——也就是锚定能力空间。两者是正交的,可以很好地组合在一起:通过 RAG 检索事实,再通过类型化、编译器检查的 DSL 来表达它们。 图 1. 两个锚定空间。(来源:作者使用谷歌的 Nano Banana 创建) 在图 1 中,RAG 在数据空间对回答的内容进行锚定。TDG 则在能力空间对语言进行锚定——两者是正交、可组合的流水线,而非竞争者。 这条原则可以浓缩为一句话:“永远不要发明大模型从未见过的语法:将领域逻辑嵌入它已经熟悉的语言,让编译器充当判定权威。” 五个构建块 TDG 是一组精简的设计约束。 嵌入式,而非外部式 将领域逻辑实现为主流宿主语言中的内部 DSL,不需要新语法,也不需要定制的解析器。那些读起来像是专用语言的代码,本质上就是普通的宿主语言代码,因此现有的工具链(高亮、补全、跳转到定义、安全重命名、调试器,以及评审者熟悉的 diff)都是开箱即用——如果从零自研这些能力,每一项都可能是耗时数年的工程。 按训练数据亲和度选择宿主语言 经典的嵌入式 DSL 相关文献(如 Paul Hudak 和 Martin Fowler 的著作)会权衡表达能力、类型系统强度和工具生态。TDG 增加了一个在 LLM 出现之前不可能存在的评判标准:语料覆盖度。Kotlin、TypeScript 或 Python 自带充足的先验生成能力,无需额外投入。前沿实验室不会公开精确的训练数据配比,但这套论证只需关注差距本身即可。任何主流语言在公开代码中的样本量都远高于一门全新 DSL 所能达到的水平。一门优雅但小众的语言则几乎没有这类优势。这些评判标准通常方向一致,但当它们产生分歧时,语料覆盖度就拥有一票话语权。 编译器即判定预言机 设计 API 时,要让领域错误表现为类型错误:优先使用命名参数而非位置参数,用枚举替代魔法字符串,构造器作用域只暴露当前上下文内合法的构造。密封类型层次结构可以让 API 限定关系端点只能是四类中的一种,模型若幻觉出第五种变体,就不存在对应的类型。接收者类型可以控制代码块内可见的函数集合。在类体外部写 attribute(...) 会直接触发名称解析失败。非法嵌套直接变成这门语言无法表达的语句。这里的严格性是实现手段,而非吹毛求疵。 生成—编译—修复(GCR) 大模型生成,编译器检查,诊断信息回流形成修复提示词。编译器反馈修复循环在自调试相关文献中已有充分论述 [1]——GCR 本身并不是 TDG 的创新点。TDG 创新的地方在于让这个熟悉的循环同时提供了两个用途:一是作为修复通道,用于修复损坏的输出;而是作为测量工具,统计某条 DSL 需要修复的频次,并定位其根本原因。修复提示词携带出错的代码片段、完整的诊断信息和源代码位置,使得有针对性的编辑成为可能,而不是盲目重新生成——后者只是从产生错误的那个分布里重新采样。这个循环是有边界的,在 kUML 的设置中最多尝试三次。如果能够成功修复,往往前几次就解决。一个在三次反馈后仍然失败,说明它缺失相关业务概念,而不是仅仅丢了一个逗号。 按需教学通道 嵌入式 DSL 解决了语法问题,但还有词汇层面的问题:存在哪些构造项、它们叫什么名字?如果把完整的 API 文档塞进每一个提示词里,会把五个相关构造项淹没在九十五条无关内容中。TDG 的解决方案是:让模型在生成过程中可以查询可调用的工具——例如可以实现为 MCP 服务器——它返回少量经过筛选、验证可用、能够直接编译的示例,且
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱