内容
# Zest
Zest 是一种专为 LLM 工具调用而设计的编程语言。它可以转换为 Python 并在长期的 Python 命名空间中执行,从而使代理能够自由访问 Python 生态系统(pandas、numpy、requests、BeautifulSoup 等),并提供比原始 Python 更简洁的语法表面。
## 诚实的结果
在捆绑的基准测试(10 个单次任务,3 个多回合流程;所有输出都等同于 Python 比较)上的令牌节省:
| 比较 | 节省 |
| --- | --- |
| 单次 vs Python | **13.4%** |
| 多回合 vs 朴素 Python(无会话 — 重新发出帮助程序) | **43.9%** |
| 多回合 vs **会话感知 Python MCP**(公平比较) | **8.8%** |
第三行是最重要的。v0.1-v0.4 的 43.9% 标题在技术上是正确的,但框架误导:大部分差距来自于*注册表的存在*,而不是语言。适当构建的 Python MCP 可以在调用之间保持全局变量(捆绑的 `python-mcp` 服务器正是如此),这缩小了大部分差距。
诚实的语言级胜利大约在 **9-15%** 的令牌输出,集中在:
- **管道** — `xs | f | g` 比 `g(f(xs))` 更短,尤其是对于 3+ 个阶段。
- **裸键记录** — `{name: "x"}` 省略了每个键的引号。
- **自动打印** — 终端值不需要 `print(...)` 仪式。
- **输出截断** — 但 Python MCP 同样可以采用这一点(Zest 的 `zest_repr` 被捆绑的 `python-mcp` 重用)。
在 **18 个真实代理测试会话** 中,更大的故事并没有在源令牌基准测试中可见:**重试率从 4-5/回合降低到 0.25-0.7/回合**,因为教学错误被迭代。每次重试都会重新发出完整的源代码。一个将误用变成一次往返修复的教学错误在生产中节省的令牌比任何单一语法特性都多。
## 工具列表
| 特性 | 为什么存在 |
| --- | --- |
| 管道(`xs \| f \| g`),裸键记录,自动打印 | 语言级别的令牌胜利 |
| 三引号字符串,格式规范插值,切片/扩展/计算键语法 | 与 Python 的质量对齐 |
| 约 80 个名称的前奏,具有类型感知调度 | `where` 在 DataFrame 上执行 `.query`,在列表上执行 `filter` 等 |
| 磁盘上的持久会话存储(`--session=name`) | 帮助程序和绑定在 MCP 重启后存活 |
| 输出截断(`zest_repr`) | DataFrame 限制在 ~30 行,无论大小如何 |
| 解析和运行时阶段的教学错误 | 降低重试率;*真正的*令牌成本杠杆 |
| MCP 服务器(`zest-mcp`)通过 stdio | Claude Desktop / Claude Code 的直接替代 |
| 兄弟 `python-mcp` 用于公平比较 | 控制臂;让你测试“Zest 在这里是否增加价值?” |
## 快速入门
```bash
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest # 391 个测试
zest run examples/01_hello.zest
zest repl
```
```zest
# 30 秒游览
xs = [1, 2, 3, 4, 5]
xs | map (_+1) | filter (_>3) | sum # 18
double(x) = x * 2 # 单行定义
process(text) => # 多行定义
out = text | trim # 最后一个表达式返回
out | upper
# 记录具有裸键 — 无引号。扩展和计算键也适用。
people = [{name: "alice", age: 30}, {name: "bob", age: 25}]
people | filter (_.age > 28) | map (_.name) | join ", "
{...defaults, timeout: 60, (key): val} # 扩展 + 计算
# 三种 lambda 形式;选择最适合的。
xs | map (_+1) # 隐含 `_`
xs | map {_+1} # 大括号 lambda
xs | map (p => p.score) # 1-参数箭头
# 赋值 + 切片语法。
xs[0] = 99
df["revenue"] = df["price"] * df["qty"]
"hello world"[:5]
# 带有中间绑定的多行 if 表达式(v0.4):
result = if x > 3 =>
a = compute(x)
b = process(a)
b
else =>
fallback(x)
# 通过 reduce / accumulate 进行状态迭代(无 `for` 循环):
rows | reduce(((s, r) => {...s, (r.id): r.value}), {init: {}})
# 错误传播;`?` 捕获并替换为 None。
config = read "config.json"? | json?
if x > 0 => "pos" else => "neg"
match v =>
1 => "one"
_ => "other"
```
## MCP 集成
```json
{
"mcpServers": {
"zest": {
"command": "/path/to/zest-lang/.venv/bin/zest-mcp",
"args": [],
"env": { "ZEST_SESSION": "default" }
}
}
}
```
或通过 Claude Code:
```bash
claude mcp add zest --scope local --env ZEST_SESSION=default \
/path/to/zest-mcp
```
LLM 获得三个工具:
* `zest_run(source)` — 执行 Zest 源代码。返回截断的 stdout、终端值的 repr 和已注册函数的列表。
* `zest_inspect()` — 列出已注册的帮助程序。
* `zest_drop(name)` — 删除已注册的帮助程序。
`zest_run` 工具描述(~3000 个令牌,经过提示工程设计)是项目中最关键的文件 — 当代理误用语言时,修复几乎总是在那里,而不是在运行时。
### 与 Python MCP 比较
捆绑的 `python-mcp` 是一个控制臂服务器,具有相同的形状(持久全局变量、自动导入、输出截断、已注册函数跟踪)。使用它来对比 Zest 和苹果对苹果的 Python 基线:
```bash
ZEST_PY_SESSION=default python-mcp # 在 stdio 上提供
```
基准测试框架(`benchmarks/compare.py`)报告三列:Zest vs 朴素 Python vs 会话感知 Python。会话感知列是诚实的比较。
## 路线图
Python-MCP 比较揭示了什么:投资于只有*语言*才能提供的功能。基础设施级功能(注册表、截断、自动导入)可以在任何 MCP 中复制。
### 最有价值的 v0.5+ 工作
| 项目 | 为什么重要 |
| --- | --- |
| **工具描述自调** | 记录每个解析/运行时错误,并自动反馈到描述中。复合重试率胜利。 |
| **回合间基于差异的输出** | 当同一个大 DataFrame 在多个回合中出现时,发送 `<unchanged from turn N>` 而不是重新截断。对于具有结构化信封的语言,独特的每回合节省。 |
| **`@memo` 装饰的帮助程序** | 在多个回合中缓存昂贵的帮助程序。适合注册模型,在长时间会话中节省实际计算。 |
| **现实世界的基准测试语料库** | 合成 13 任务语料库可能低估或高估实际胜利。带有权限的真实 Claude 工具调用记录( transcripts)将告诉我们。 |
### 较低优先级
| 项目 | 备注 |
| --- | --- |
| 多会话多路复用 | MCP 管道,而不是语言级 — 延迟。 |
| 标记符感知前奏重命名 | 审核:只有 5 个名称的成本超过 1 个 BPE 标记;重命名成本比标记符可读性更高。 |
| `!` 标记的可确认副作用 | 细分。可能对生产安全有用;不是令牌胜利。 |
## 语言如何诞生 — 18 次会话
在 v0.1 中交付(按照原始的 `HANDOFF.md`),然后在真实代理测试会话中迭代 18 次。每个会话都会出现 2-7 个摩擦点;每个后续提交都会通过运行时错误、教学差距或真正的缺少功能来解决它们。累积添加(按字母顺序,不是按时间顺序):
- **语言**:项赋值,切片语法,扩展(记录 + 列表),计算键,多行 if 表达式体,1-参数 lambda 缩写,三引号字符串,格式规范插值,点管道阶段可调用方法调用 kwargs 解包。
- **前奏(~30 个新增 v0.1 之外)**:`reduce`/`fold`/`accumulate`,`count_by`/`group_by`,`tail`/`head`,`sort`,`len`,`chars`,`flat_map`,`contains`,`keys`/`values`,`dataframe`,`rows`,`assoc`/`dissoc`,`findall`/`search`/`re_match`/`sub`,`dict`/`list`/`set`/`tuple`(构造函数)。
- **教学错误(降低重试率的杠杆)**:Python 关键字形状,`=`-kwargs,列表推导,切片,原始字符串前缀,正则表达式/除法歧义,前奏名称遮蔽,未知转义,多裸参数,三元,walrus,`..`-typo for 扩展,dict-set vs `set` 构造函数,多行 lambda 体,方法-kwargs 冲突,保留关键字作为变量名。加上上下文感知“你是否意味着”建议。
- **可发现性**:`@help` 和 `@help name` 用于前奏查找。
- **持久性**:磁盘上的命名会话(`--session=name`),基于源代码重放的调用不会在重启时重新触发。
## 布局
```
src/zest/
lexer.py # tokenizer: indents, interpolation, regex, units
ast.py # dataclass nodes
parser.py # recursive descent
transpiler.py # Zest AST → Python AST
runtime.py # ZestSession, RunResult, registry, helpers
errors.py # teaching-grade error formatting + suggestions
repr.py # truncated repr for DataFrames / ndarrays / strings
prelude.py # ~100 names + pipeline dispatch
cli.py # zest run / zest repl
mcp_server.py # MCP stdio server
python_mcp_server.py # CONTROL ARM: same shape, plain Python
tool_description.py # the LLM-facing `zest_run` description (~3000 tokens)
benchmarks/
compare.py # tiktoken cl100k_base, three-way comparison
single/ # 10 paired .zest / .py tasks
multi/ # 3 flows × {turn{1,2,3}.zest, turn{1,2,3}.py,
# session_turn{1,2,3}.py}
examples/ # runnable .zest demos
tests/ # 391 tests across lexer/parser/transpiler/runtime/integration
```
## 许可证
MIT