---
layout: post.njk
source: https://yage.ai/share/llm-smaller-executable-world-20260718.html
speaker: yage.ai
title: |-
  LLM 需要一个更小的可执行世界：DSL、FastAPI 与 Context
  Infrastructure
date: '2026-07-18'
summary: 文章探讨了如何通过设计领域特定语言（DSL）和有限的API来为大型语言模型（LLM）构建一个更小、更可执行的世界。核心思想是，将复杂的自然语言指令转化为结构化的程序表示，从而缩小模型的表达边界，提高任务的精确性和可靠性。这涉及到利用FastAPI等技术定义原子操作，以及DSL负责描述完整计划，形成Context Infrastructure闭环。
area: tech-engineering
category: ai-application
tags:
  - dsl
  - fastapi
  - context-infrastructure
  - llm-workflow
people: []
companies_orgs: []
products_models: []
media_books: []
draft: true
status: evergreen
---

## DSL
最大的缺点，正在变得没那么重要

我以前做 AI
控制天文望远镜时，认真考虑过一条路线：设计一门只允许拍照、对焦、指向星体等有限操作的小型语言。这就是
DSL，针对特定领域设计的编程语言。它能把 AI
的活动范围限制在安全边界里，问题是成本太高。设计语言、编写解释器，再补上循环和分支，做着做着就会重新发明一门编程语言。所以我在当时的文章里放弃了这条路，最后选择
Python、受限类库、AST 分析和沙箱。

后来，AI 改变了这笔账。我在《一次性软件与被压缩的现实》里写过：制造专用工具的成本大幅下降后，为一个很小、甚至只出现一次的需求现场写工具，也可能比凭经验凑合更经济。这个判断同样适用于
DSL。AI 不仅能使用一门现成语言，也能帮人试验抽象、写解析器、补 validator
和准备示例。

2026 年 7 月 14 日，分布式系统工程师 Unmesh Joshi 发表了 DSLs Enable
Reliable Use of LLMs。他提出两阶段做法：先让人和 LLM
通过真实实现寻找领域概念，把稳定部分做成 DSL；语言稳定后，再让 LLM
把自然语言需求翻译成 DSL
程序，交给编译器、模拟器和测试执行。生成后的程序进入代码库，成为后续修改时的
source of truth。

这篇文章让我重新理解了 DSL 的价值。它不只是一种新语法，更是在给 LLM
建一个更小的可执行世界。过去最难承受的是建造这个世界的成本；现在，这项成本也在下降。

## LLM
需要的不是更多道路，而是一个更小的世界

自然语言给 LLM
的表达空间几乎没有边界。同一个要求可以有很多说法，省略的前提也很难穷尽。模型如果直接用自然语言向系统发指令，系统连结果怎么解析都不一定知道。

Python 和 JavaScript
消除了语法上的含糊。代码能运行、能复现，也能测试。但通用编程语言仍给模型留下大量选择：它可以调用文件系统、创建线程、打开网络连接，也可以用几十种方法实现同一个
delay。语法变精确了，模型能触发的外部效果依然很多。

领域 API 和 DSL
又缩小了一层。系统只开放拍照、对焦、启动任务、查询状态这些有限动作，并规定哪些组合合法。模型不再面对整个操作系统，只需要在团队已经理解的动作里选择。这里所说的“可执行语义世界”，指的就是模型能表达哪些动作、这些动作怎样组合，以及系统会检查哪些规则。

自然语言、通用编程语言与领域边界逐层缩小
LLM 的可执行世界

世界缩小以后，系统会在执行前排除一部分无效路径。检查十个领域动作及其组合，也比审计任意生成的
Python
程序容易。不过，缩小世界只能排除规则已经覆盖的错误，正确答案不会因此自动出现。

## FastAPI 其实已经很像 DSL

FastAPI 是一个用 HTTP 接口暴露 Python
操作的服务端框架。一个更常见的例子是 GitHub
REST API：agent 可以通过固定 endpoint 创建 issue、读取 pull request
或触发 workflow，无须理解 GitHub 后端怎样保存对象和调度任务。用 FastAPI
写出的领域服务也在做同一件事，把内部实现藏在一组稳定操作后面。

这已经在缩小 agent 的世界。API
告诉模型有哪些原子动作，也可以通过认证、权限和参数校验限制每个动作。不过，控制面变小，不代表模型最终能造成的影响一定小。GitHub
API 可以触发一份 GitHub
Actions workflow，而 workflow 里的 run 仍能执行 shell
command，读写文件或访问网络。判断边界是否足够窄，最终还是要看动作会触发哪些外部效果。

API 还有另一个特点：组合逻辑通常留在 agent 里。模型创建 pull
request，查看 CI
状态，再决定是否合并。完整计划存在于运行轨迹中，不一定有一份独立文件。前三步已经改变系统后，第四步失败，回滚也会变得麻烦。

GitHub Actions workflow 又向 DSL 迈了一步。YAML
文件不只列出单个动作，还保存触发条件、jobs、依赖关系和完整步骤。系统可以在产生副作用之前解析它、检查一部分跨步骤规则、交给人
review，也可以把它存进 Git，日后 diff 或
replay。可以用一个不严格但实用的公式理解两者关系：

DSL ≈ 领域 API + 组合规则 + 可保存的程序表示

如果 FastAPI 的某个 endpoint 接收一整份包含步骤、依赖和错误处理的
JSON plan，这个 request body 就在承担 DSL
程序的角色，服务端负责解释和执行它。反过来，一门 DSL
最终也常常编译成一连串 API calls。两者没有清晰的敌我边界。

## DSL 与 API 最适合叠在一起

交互式任务适合直接调用 API。模型提交一次修改，读到 CI
错误，再决定下一步，观察和行动不断交替。提前写完整计划，反而可能拿走它根据现场情况调整的能力。

另一类任务需要先看全貌。部署计划、权限变更、分布式故障场景往往包含多个步骤和跨步骤约束。系统最好在第一步执行前，就知道后面会修改什么、失败后如何处理。DSL
或结构化 JSON plan 在这一层保存完整意图，parser 和 validator
先做检查，通过后再交给 FastAPI、MCP 或 CLI 执行。

Context Infrastructure、DSL 计划层与
FastAPI 执行层组成持续进化的闭环

因此，FastAPI 可以负责原子操作，DSL
负责描述完整计划。前者处理“具体怎样执行”，后者处理“这些操作怎样组成一个领域任务”。系统不需要在两者之间二选一。

## 创建之后，不必立刻决定它能活多久

传统团队引入 DSL
以前，通常要先回答一个问题：这门语言以后会不会反复使用？解析器、validator、示例、迁移工具都需要人来维护，如果没有足够使用量，前期投入很难收回。

AI
降低了这些工件的生产成本，也改变了决策顺序。团队可以先为眼前几个相似任务建立领域边界，实际运行后再决定它的寿命。这里不要求
DSL 用完即弃，也不要求它从第一天起就是永久基础设施。

如果它反复解决同类问题，可以继续留在代码库，逐步提升为稳定组件；如果只有几个
primitive
有用，就把它们拆出来；如果对应任务消失了，归档或删除也没有问题。生命周期从创建前的预测，变成了使用后的观察结果。

保留代码本身成本不高，真正的代价是维护和上下文污染。实验 DSL 可以留在
archive
中，却不必默认加载给每一次任务。稳定、反复出现的部分再进入活跃文档、examples
和工具描述。这样既保留未来复用的可能，也不会让模型每次面对一堆过期接口。

## DSL 也可以成为
Context Infrastructure 的一部分

项目使用 DSL 以后，会积累三类材料：成功运行的程序、失败时的 validator
errors，以及人类对错误结果的纠正。下一次任务到来时，这些材料比一份抽象语法说明更有用。模型可以看到这个项目过去怎样表达同类任务、哪些组合会失败、团队后来修改了什么。

如果系统持续捕获这些记录，从中提炼稳定模式，再按任务需要加载相关部分，它们就进入了我此前讨论的
Context
Infrastructure。这套基础设施不只是保存聊天记录，而是把项目自己的判断、示例和纠正组织成模型能继续使用的
context。

Context Infrastructure 与 DSL
的约束力度不同。前者告诉模型什么重要、过去怎样判断；后者直接规定能调用什么动作，以及这些动作怎样组合。一个影响模型如何理解任务，另一个限制模型最终能提交什么程序。

每次执行又会产生新的候选材料。成功程序可以成为后续示例；失败可能来自模型写错程序，也可能暴露语言、validator
或任务本身的问题。人和系统先分类、提炼这些记录，确认稳定模式后再更新
Context。模型消费代码库中的 context
完成任务，经过筛选的结果再回到代码库，推动这套本地语言继续变化。

## 缩小世界的代价，是可能把正确答案一起删掉

领域边界太宽，模型仍然有大量无用路径；边界太窄，新需求可能根本无法表达。这里的判断重点不在
DSL
是否图灵完备，而在两个更具体的问题：模型最终能触发哪些外部效果，也就是
effect surface；系统又允许这些动作怎样组合。

即便 DSL 程序通过 parser 和
compiler，也只能证明它符合已经写下来的规则。业务结果仍需要独立测试。否则，同一个模型可能同时误解任务、生成程序，又写出与误解一致的
expectation，最后得到一份顺利通过但方向错误的结果。

Tickloom
展示了这几层怎样组合。它用 Java internal DSL
描述服务器、客户端、读写和网络故障，再用确定性模拟器、断言和一致性
checker 检查场景行为。DSL
限制表达，模拟器负责执行，测试判断已有断言覆盖到的结果。

不过，Tickloom 是一个工程案例，不是 DSL
可靠性的系统实验。项目没有比较同一批任务在自然语言、JSON、普通 Java 和
DSL 下的生成成功率，也没有跨模型
benchmark。它能说明机制如何工作，不能证明 DSL 已经普遍提高 LLM
的任务正确率。

## 从“给模型写
prompt”到“给模型建世界”

LLM 项目早期常把主要精力放在 prompt
上：补一条规则，增加一个例子，再提醒模型不要犯上次的错误。随着项目积累，真正稳定的资产可能转移到别处：领域中的对象和动作、受限
API、DSL、validator、成功程序，以及每次失败后留下的纠正。

FastAPI 定义模型可以调用的原子能力，DSL
把这些能力组合成一份完整计划，Context Infrastructure
保存项目为什么这样设计，以及过去使用中学到了什么。它们共同把通用模型带进一个项目自己的可执行世界。

Joshi 的文章讨论的是 LLM 如何与 DSL
配合。沿着成本变化继续推一步，它还提示了另一种可能：AI
既能在受限世界里工作，也能降低建造和修改这个世界的成本。团队可以更早建立专用边界，把它放进代码库，再让真实使用决定哪些部分继续存在。

这条路线仍有清楚的前提。领域动作需要相对稳定，系统要能检查关键结果，边界也不能窄到排除正常需求。条件满足时，给模型写更长的说明未必是最有效的投入。给它建立一个更小、能执行、会积累经验的世界，可能更接近可靠的工程系统。