ByteNoteByteNote
把提示词写成 Lisp:让大模型稳定输出一张 SVG 卡片
字

字节笔记本

2026年10月7日 · 约 7 分钟读完

把提示词写成 Lisp:让大模型稳定输出一张 SVG 卡片

API中转
¥120

2024 年 9 月,一段用类 Lisp 语法写的提示词在中文 AI 社区刷屏。它叫「汉语新解」,功能一句话就能说清:输入任意一个汉语词汇,模型先给出一句辛辣的隐喻式解释,再把它排版成一张 400×600 的 SVG 卡片。有意思的不是段子本身,而是写法——整份提示词没有一个「请你」「希望你」,通篇都是 defun。本文以它为样本,拆解这种「提示词即程序」的写法为什么好使,以及把它迁移到别的任务时该注意什么。

一、三段式结构:角色、流程、输出

这份提示词全长不到三十行,却把一次生成拆成三层,各管各的。

角色层定义了一个「新汉语老师」:风格对标王尔德、鲁迅、林语堂,擅长一针见血,表达靠隐喻,批判走讽刺幽默。注意它没有写「你要风趣深刻」,而是把抽象形容词换成可枚举的参照系——模型对「像鲁迅一样」的还原度,远高于对「语言风趣」的还原度。

流程层是主函数 汉语新解,本质是一条流水线:

lisp
(一句话表达
  (隐喻
    (一针见血
      (辛辣讽刺
        (抓住本质 用户输入)))))

「写得好」被分解成四个算子:先抓本质,再讽刺,再收拢成一句,最后打成隐喻。这等于把思维链显式写进了代码,模型不必自己领悟步骤,顺着括号一层层执行即可。

输出层是 SVG-Card 函数,把版式规格全部钉死:画布 400×600、边距 20、标题毛笔楷体、最小字号 16、蒙德里安式配色;卡片元素固定为居中标题、分隔线、词语本体、拼音、英文、日文注音和解释正文。另有一条内联 few-shot 负责钉风格——「委婉」的示例是「刺向他人时,决定在剑刃上撒上止痛药」。风格基准、思考流程、输出规格三样东西全部前置声明之后,生成时的自由度就被压缩到了「内容」本身。

更彻底的是连交互入口都被程序化了:提示词末尾约定启动时先运行 start 函数,于是对话的第一句话固定是「说吧,他们又用哪个词来忽悠你了?」——开场白不是模型即兴发挥,而是脚本的一部分。从这个细节能看出作者的思路:凡是希望稳定出现的东西,一律写成代码。

汉语新解提示词的三层结构解剖:角色层、流程层、输出层

二、为什么 S 表达式比自然语言好使

同样的信息用自然语言写,动辄上千字,问题不在写不出来,而在约束会互相淹没:格式要求写在第五段,模型读到第十段时权重已经被稀释。S 表达式的优势有三个。

其一,约束即数据。角色、流程、输出规格各自独立成块,改配色不用动流程,换流程不影响角色,天然模块化。

其二,函数组合显式化了推理顺序。自然语言提示词里的步骤要靠模型自己领会先后,嵌套括号则把顺序写成了语法。

其三,声明式规格消除歧义。比起「输出一张美观的卡片」,(设置画布 '(宽度 400 高度 600 边距 20)) 没有任何二义性。

这和社区常见的 YAML、JSON 结构化提示词是同一思路。Lisp 的差别在于括号嵌套天然表达「函数调用链」,而且主流模型的训练语料里 Lisp 代码密度足够高,这种格式几乎不会被读错。

顺带一提,把提示词写成代码还带来一个常被忽视的好处:它变得可测试。自然语言提示词改了半句,效果是变好还是变坏只能凭感觉;结构化版本改一个函数、换一条 few-shot,都能用同一批输入词回归抽查,改动的影响范围一目了然。

三、实测:三个词,三张卡片

实测输入「内幕」,卡片上的解释是:「权力的自助餐:普通人只能闻到香味,而有些人已经在厨房里偷吃完了。」

输入「共同富裕」,得到的是「社会主义大合唱:台上领唱高喊『共同富裕』,台下群众合唱『共同幻想』,只有寥寥几人悄声低吟『独自富裕』。」

输入「美女」,则是「社会的美容院:给女性贴上标准化的『美丽』标签,把独特灵魂打磨成千篇一律的橱窗模特。」

三次输出的结构全部合规:每次都是不同的柔和底色,词语配三语注音,解释用 tspan 手动断行,留白干净。稳定的不是文笔——换个模型文笔会变——稳定的是「隐喻加单句加卡片」这个骨架,这正是把输出规格前置声明换来的确定性。

汉语新解的生成流水线与输出卡片预览

四、迁移:单词记忆卡片是同一副骨架

同一作者还有一份同构的提示词,把流程换成记忆卡片:分解词根 → 词根联想 → 创造生动故事 → 设计 SVG 卡片。实测输入 cat,输出一张 800×600 的卡片:词源区块追溯到古英语 catt、拉丁语 cattus;记忆故事用首字母法「Curious And Tranquil, Always Tiptoes」,三个短语的首字母恰好拼出 CAT;再配一个纯 SVG 绘制的猫脸和一句融入故事元素的例句。

两份提示词骨架完全一致:角色定义、流程管道、SVG 规格、内联示例,变的只是中间那根管道。这验证了此类写法的可复用性——它是模板,不是孤例。

五、SVG 直出的四个坑

真要把「模型直出 SVG」用进生产,有几个坑要先踩平。

字体:生成的 SVG 里常见 @import 引谷歌字体,浏览器里没问题,一旦转 PNG 或离线渲染就会失效,务必写好字体回退。

换行:SVG 的 text 不会自动折行,断行要靠 tspan 加 dy 手动排版,文字超宽也不会自己缩;提示词里的「自动缩放,最小字号 16」就是防溢出设计,但模型算得并不总准,长句仍可能出界。

动画:SVG 原生的 animate、animateTransform 在浏览器里能播,转位图就全部丢失,别指望一段「会动的大海」能直接导出成动图。

迭代方式:对输出不满意,别整段重写提示词,用增量指令补元素。实测把一幅只有天、海、太阳、海鸥的简单海景改成有漂移的云、帆船、游鱼、摇曳海草的丰富场景,靠的是「不太丰富,再加东西」这类短指令——模型会用 symbol 定义云朵,再用 use 复用多份。增量迭代远比推倒重来省力。

六、把提示词当代码养

这套写法真正值得学的不是某个段子,而是一种姿态:把 prompt 当 DSL,把模型当运行时。角色、流程、输出三分离,意味着可以版本管理;固定输入抽查输出,就是最朴素的回归测试;跑通的模板可以换管道复用。开发者玩提示词的天然优势,恰恰是这些工程习惯。

也要说清边界:S 表达式不会提升模型智力,它提升的是约束的传达效率。对发散型任务(头脑风暴、自由聊天)过度结构化反而压死灵气;它最适合的是输出结构固定、风格要求明确、需要批量复用的生成任务——内容营销卡片、学习卡片、固定版式的配图都算此类。下一次当你和模型来回拉扯输出格式时,不妨把那段「请输出……要求……」改成三行 defun,把格式争议变成格式声明。

相关文章

分享: