语义热力学与叙事约束:把LLM输出token砍掉79%的工程实践
2026/8/28 6:08:53 网站建设 项目流程

如果你正在用大模型做 Agent、RAG 或者任何偏“生产级”的 LLM 应用,最近一定被同一个问题折磨过:token 不够用。

不是模型能力不行,而是每一轮对话、每一段工具调用结果、每一次系统提示词注入,都在消耗上下文窗口。换更贵的模型能解决质量,却解决不了成本;做文本截断能保住窗口,却往往把关键信息一起切掉。很多团队在模型选型和 RAG 方案上花了大量精力,最后发现真正卡住业务规模的,其实就是 token 预算。

但这里面藏着一个被低估的事实:大量 token 并不是“必须花”的,而是模型在输出时产生了大量叙事冗余——它用好几句话表达本来一句话就能说清楚的信息。模型不是不知道该简洁,而是没有人给它足够的“叙事约束”。

这篇文章想讲清楚一个思路:把 LLM 的输出看作一个语义系统,通过热力学式的“约束”来降低语义熵,让每个 token 都承载更多有效信息。这个思路对应到一个很形象的概念——Semantic Thermodynamics,中文可以叫“语义热力学”。

更重要的是,不仅讲概念,还会给出一个可以在本地跑通的完整实验,让你亲自测量:在同样的任务里,使用叙事约束和不使用叙事约束,输出 token 到底差多少。这也是“79% token reduction”这类数字最靠谱的理解方式:它不是所有场景的普适结论,而是在高冗余文本生成任务里,约束带来的真实收益。

1. 这篇文章真正要解决的问题

先说痛点。

假设你维护一个内部的 RAG 问答系统。用户上传一份 2000 token 的产品文档,系统召回 3 个片段,每个 500 token,再加上 system prompt 和用户问题,输入侧大概 4000 token。模型生成回答,如果没有任何输出约束,一次返回 800 token 是常有的事。这看起来很平常,但如果你的业务是每天几千次调用,这个成本就非常可观。

更麻烦的是 Agent 场景。Agent 需要多轮工具调用,每一轮都要把之前的对话历史、工具返回结果、中间思考塞进上下文。一个 5 轮调用的任务,输入输出累计可能轻松突破一两万 token。而在这其中,有很大一部分是“叙述性”的:模型在复述已知信息、在重复套话、在生成格式松散的过渡句。

传统优化手段有几种,但都有代价:

  • 换更小/更便宜的模型:质量可能下降。
  • 手动截断历史:可能丢失关键上下文。
  • 用摘要代替原文:摘要本身产生的 token 也很高,而且损失细节。

这些方法都默认 token 消耗是“输入侧”的问题,只要把输入压小就行。但实际上,输出侧的叙事冗余同样重要,而且往往被忽略

所谓叙事约束,不是简单地说“请简短回答”,而是从输出结构下手:告诉模型必须按什么模板、什么粒度、什么顺序来生成。约束越明确,模型的输出就越接近“最小语义集”,废话自然减少。

这篇文章适合谁?

  • 正在做 LLM 应用开发,想压 token 成本的技术人员。
  • 维护 RAG 或 Agent 系统,被上下文窗口撑爆困扰的工程师。
  • 对“结构化输出”“输出约束”有兴趣,但没时间系统整理方法的开发者。

读完之后,你能得到一个可以直接运行的示例,以及一套判断“什么时候该用约束”的实践指南。

2. Semantic Thermodynamics 的核心概念:把 LLM 输出看成语义系统

第一次看到“Semantic Thermodynamics”这个词,大概率会觉得它很玄学。它听起来像是物理学的分支,实际上它并不是一个严格的热力学理论,也不是某个官方标准,而是一种思考模型输出与 token 消耗之间关系的方式

通行的认识是:LLM 的每个输出 token,本质都是在“内容空间”中做一次选择。如果这个选择的随机性很高,模型就会输出大量低价值、可预测的过渡内容;如果选择被强烈约束,模型就必须把语义集中到有限几个 token 上。

可以用热力学里的概念来类比:

  • :在信息论里,熵表示不确定性。LLM 生成的文本中,如果候选词分布很分散、上下文信息弱,输出就更“混乱”,表现为结构松散、重复表达。这类输出可以看作“高语义熵”。
  • 自由能:热力学中,系统能对外做功的部分叫自由能。对应到 LLM 输出,真正对任务有价值的语义信息,就是“有效语义”。大量 token 消耗在维持“句式完整”“语气自然”“表达柔和”上,这些不是有效语义。
  • 约束/边界条件:把一个气体系统关进容器,它就不能无限膨胀。叙事约束也是一种“边界条件”,把模型的表达范围限定在一个紧凑的结构里。

所以,Semantic Thermodynamics 的通俗解释是:在模型输出能力不变的情况下,通过增加叙事约束,降低输出文本的语义熵,让每个 token 携带更多有效语义。

为什么叫“叙事”约束?因为约束的对象不是单个词汇,而是模型生成内容的组织方式。比如:

  • 输出必须分为 3 个章节。
  • 每章只能用列表。
  • 每项不超过 20 字。
  • 不要输出总结段落。
  • 不要重复问题中的背景信息。

这些约束都作用于“叙述结构”,所以叫 narrative constraints。

理解了这一点,你就抓住了标题里“79% token reduction”背后的逻辑:当任务本身冗余度高,约束带来的收益就极大。反过来,如果任务本身已经很紧凑,比如直接生成 JSON 数据,约束能带来的空间就有限。

3. LLM Token 成本构成:为什么“叙事冗余”会影响预算

要真正理解约束的价值,得先把 token 成本拆开看。

3.1 Token 成本的三部分

一次完整的 LLM 调用,token 消耗由三部分组成:

组成部分含义典型来源
输入 token系统提示、用户输入、检索结果、对话历史Prompt 设计与 RAG 召回
输出 token模型生成的内容回答、总结、工具调用参数
缓存/日志 token重复调用时的历史记录、日志分析多轮 Agent、长期会话

很多优化方案只盯着第一项,比如把 system prompt 写得更短、减少检索片段。但输出 token 同样重要,尤其是在生成型任务中。

3.2 输出侧冗余的真实场景

举一个非常常见的例子。

你让模型把开发记录整理成周报,模型可能会这样输出:

“本周我们团队主要围绕订单服务展开了一系列优化工作。首先完成了日志采集系统的搭建,并成功接入了 order-service 和 payment-service 两个核心服务。其次……”

这段文本信息密度很低。真正有效信息只有“搭建日志采集,接入两个服务”,其余都是叙事连接。如果任务规模再大一点,比如整理本周 20 条开发记录,模型很容易生成 800 到 1000 token 的周报。

而如果加上约束,要求“只输出三章列表,每项不超过 25 字”,同一份开发记录,模型可能只需要 200 token 就能表达同样的信息。

这就是叙事冗余在输出侧造成的浪费。它不像输入侧那样直观,但累计起来非常惊人。

3.3 传统压缩方案 vs 叙事约束

有人会说,那直接在 Prompt 里加一句“请简短回答”不就行了?

区别很大。

方法原理问题
直接要求“简短”模型自行判断压缩程度效果不稳定,容易丢失关键信息或仍然冗长
截断输出切断长文本破坏语义完整性
摘要/压缩中间结果用另一轮 LLM 调用压缩内容增加额外 token 消耗,且摘要也可能冗余
叙事约束固定输出结构,限制粒度需要设计模板,但效果可预测、可复用

叙事约束的优势在于“可预期”。你规定模型输出 3 章、每章 3 条列表,它就会接近这个结构。你可以提前估算输出 token 上限,这对成本控制是非常有价值的。

4. 叙事约束的四种落地方式

叙事约束不是一个单一技巧,而是一类方法的合集。在实际工程中,常见的有四种落地方式:

4.1 输出结构约束

这是最直接的一种。在 system prompt 里明确告诉模型:输出必须包含哪些章节、章节的顺序是什么、每个章节用什么样的排版。

示例:

请将下面的会议纪要整理为项目周报,并严格遵守以下约束: 1. 只输出三个章节:# 本周进展、# 问题与风险、# 下周计划。 2. 每个章节使用无序列表,不允许出现段落式描述。 3. 不要输出任何总结、建议或客套话。

结构约束的本质是“定义模板”。模型在模板内填充内容时,不会浪费 token 在过渡句上。

4.2 输出格式约束

把输出格式限定为 JSON、CSV、YAML 等机器可读格式。这不仅能压缩 token,还能让下游程序直接解析,减少额外 JSON 解析和清洗成本。

示例:

请输出 JSON 格式,字段为: { "summary": "不超过50字的一句话总结", "items": ["不超过20字的关键进展"], "risk": "无则填null" }

需要注意,JSON 的字段名本身也会消耗 token,所以字段名尽量短。但可读性也不能太差,团队内部需要约定一套通用的短字段命名。

4.3 思维链压缩

推理任务中,思维链(Chain of Thought)能提升效果,但也会带来大量中间 token。叙事约束在这里的作用是:保留关键推理步骤,删除重复推理过程

可以这样约束:

请分步骤给出推理过程,但每个步骤不超过一行,并且只保留与结论直接相关的推理。

这属于“轻量约束”,保留了思维链的能力,但限制了它的膨胀。

4.4 多轮上下文压缩

这个更适合 Agent 场景。当对话历史超过一定长度时,用一次带叙事约束的 LLM 调用,把历史压缩成“关键事实列表”,而不是用原始文本继续拼接。

示例压缩指令:

请将以下多轮对话压缩为事实清单: 1. 每行一个事实,不超过20字。 2. 只保留对后续任务有影响的决定、结论和未解决问题。 3. 不要输出对话过程的描述。

这样在后续调用中,输入历史从几千 token 降到几百 token。压缩本身虽然消耗一次调用,但总体上通常是节省的,而且上下文精度更高。

5. 完整示例:用叙事约束降低 LLM Token 消耗

前面讲了概念和方法,这一节用一个可以实际运行的脚本,验证叙事约束对 token 的影响。

5.1 环境准备

建议使用 Python 3.9+。需要安装两个依赖:

pip install openai tiktoken

如果你还没有设置 API Key,先设置环境变量:

export OPENAI_API_KEY="你的_API_Key"

Windows 下使用:

set OPENAI_API_KEY=你的_API_Key

文中下面的示例使用 OpenAI 接口风格,模型选择上建议使用你实际可用的模型,比如gpt-4o-mini。脚本里通过变量统一配置,方便替换。

5.2 完整实验脚本

场景:把一段开发记录整理成技术周报。对比“无约束”和“叙事约束”两种模式下,输出 token 的差异。

# 文件路径:narrative_constraint_demo.py import os import textwrap import tiktoken from openai import OpenAI client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) encoder = tiktoken.get_encoding("cl100k_base") # 未约束版本 FREESTYLE_SYSTEM = ( "你是技术团队负责人,请根据开发记录整理一份技术周报。" "要求表达自然、内容完整、逻辑通顺。" ) # 叙事约束版本 CONSTRAINED_SYSTEM = textwrap.dedent("""\ 请把开发记录整理成技术周报,并严格遵守以下叙事约束: 1. 只输出三个章节:# 本周进展、# 问题与风险、# 下周计划; 2. 每个章节使用无序列表,每项不超过 25 字; 3. 不输出问候语、总结段落、补充解释; 4. 总列表项不超过 8 个。 """) DEV_RECORDS = textwrap.dedent("""\ 周一:搭建日志采集,接入 order-service 与 payment-service。 周二:完成订单超时取消任务,覆盖测试通过。 周三:修复支付回调偶发超时,根因是数据库连接池不足。 周四:订单服务 QPS 压测由 800 提升到 1200。 周五:数据看板联调完成,导出按钮样式待调。 """) def call_and_count(system_prompt: str, user_content: str, model: str = "gpt-4o-mini"): """调用模型并返回生成文本和 token 使用量""" resp = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_content}, ], temperature=0.3, ) output_text = resp.choices[0].message.content return output_text, resp.usage def local_prompt_token_count(): """本地统计两类 prompt 的输入 token,方便不调用 API 也能对比""" free_prompt = FREESTYLE_SYSTEM + "\n" + DEV_RECORDS con_prompt = CONSTRAINED_SYSTEM + "\n" + DEV_RECORDS return len(encoder.encode(free_prompt)), len(encoder.encode(con_prompt)) if __name__ == "__main__": free_prompt_tk, con_prompt_tk = local_prompt_token_count() print(f"未约束 prompt token: {free_prompt_tk}") print(f"约束 prompt token: {con_prompt_tk}") print("\n======== 未约束版本 ========") free_text, free_usage = call_and_count(FREESTYLE_SYSTEM, DEV_RECORDS) print(free_text) print(f"\n[token] prompt={free_usage.prompt_tokens}, " f"completion={free_usage.completion_tokens}, " f"total={free_usage.total_tokens}") print("\n======== 叙事约束版本 ========") con_text, con_usage = call_and_count(CONSTRAINED_SYSTEM, DEV_RECORDS) print(con_text) print(f"\n[token] prompt={con_usage.prompt_tokens}, " f"completion={con_usage.completion_tokens}, " f"total={con_usage.total_tokens}") if con_usage.completion_tokens and free_usage.completion_tokens: reduction = (1 - con_usage.completion_tokens / free_usage.completion_tokens) * 100 print(f"\n输出 token 下降比例: {reduction:.1f}%")

5.3 脚本关键逻辑说明

脚本分为三部分:

  1. 本地计算 prompt 的 token 数。通过 tiktoken 估算输入侧的差异。在这个例子里,约束版 system prompt 会更长一些,这是因为它包含了详细规则,但这部分成本是一次性且可复用的。
  2. 使用同一个开发记录,分别调用两次模型。一次“自由发挥”,一次“叙事约束”。输出文本本身打印出来,可以直观感受两者差异。
  3. 通过 API 返回的usage字段,精确获得输出 token 数,并计算下降比例。

这里有一个容易被忽略的细节:如果你在系统提示词中写了一套叙事约束,它会被复用到后续所有调用中,所以 prompt 本身多消耗的 token 是值得的。只要约束能让每次输出节省 200 token,调用 10 次就节省了 2000 token,远大于 prompt 增加的部分。

5.4 运行与验证

运行命令:

python narrative_constraint_demo.py

如果一切正常,你会看到两类输出文本和 token 统计。

判断实验是否成功的标准:

  • 两类版本都生成了周报内容。
  • 约束版的输出结构严格符合 3 章列表要求。
  • 约束版输出 token 明显少于未约束版。
  • 约束版的正文仍然覆盖了开发记录中的关键事实:日志接入、超时取消、支付回调修复、QPS 提升、数据看板联调。

这最后一点最重要。Token 减少的代价不能是信息损失。约束后的输出应该更精炼,而不是更残缺。

6. 运行结果与效果验证

以示例中的开发记录和模型表现来看,典型结果大致如下:

模式输出 token 范围优点风险
未约束700 - 1100表达自然,阅读体验好存在大量过渡句和重复描述
叙事约束150 - 250token 少,结构可预期,便于程序解析需要人工确认信息覆盖度

如果你运行后的下降比例恰好是 70% 左右,说明任务冗余度较高;如果只有 30%,说明这个任务本身已经足够紧凑,比如输入本身是高度结构化数据。79% 这个数字之所以会被用来做标题,通常对应的是最典型的“周报/纪要/文档摘要”类任务。不要把它当作所有场景都能复现的结果。

如何更严谨地验证约束是否有效?

建议做一个 20 条样本的小测试:

  1. 准备 20 个不同的输入文本。
  2. 每条分别用自由模式和约束模式生成。
  3. 记录输出 token。
  4. 人工检查每条输出是否覆盖关键信息点。

如果平均下降比例在 40% 以上,且 90% 的样本没有丢失关键信息,说明这套约束模板适合你的业务,可以放到生产环境里复用。如果某些样本丢失信息,就要调整约束规则的粒度,比如把“每项不超过 25 字”放宽到“不超过 40 字”。

7. 常见问题与排查方法

在实际工程中,叙事约束并不是加上就有效果。下面几个问题非常典型:

问题现象可能原因排查方式解决方案
模型输出不符合指定结构约束规则模糊或相互冲突检查 system prompt,是否出现“要简洁又要完整”这类矛盾表述将规则拆成可执行的序号条款,并配一个输出示例
信息丢失,关键点没写出来约束过强,列表项数量限制过严对比约束前后输出的信息点覆盖数量适当放宽字数上限,或允许“超出部分单独用小字补充”
模型仍然输出大段解释约束只写了“不要输出解释”,但没有给出替代结构检查是否定义了“如果必须解释,应放在哪个字段”增加一个comment字段,把必须的解释集中放在末尾
本地 token 统计与 API 计费不一致tiktoken encoding 选择与模型不匹配使用模型对应的 encoding;以 API 返回 usage 为准计费与优化决策以 API 返回数据为准,本地统计只做估算
用了约束后质量下降temperature 设置过高,输出随机性增加在约束场景下调低 temperature 到 0.2 - 0.4生产环境建议 temperature 固定,不用默认值
结构化输出偶尔不是合法 JSON模型没有稳定遵循 JSON 格式开启 response_format=json_object 等结构化输出能力同时做 JSON 解析失败重试,不要把格式正确性完全交给模型

7.1 一个容易踩坑的案例

有一种错误做法是,把叙事约束写在用户消息里,而不是系统提示词里。

当约束出现在用户消息中时,模型可能把约束和业务输入混在一起理解,优先级没有 system prompt 高。生产环境建议把稳定的叙事约束模板放在 system prompt 中,把每次变化的文本放在 user message 中。这样既保证约束稳定生效,又方便统一更新模板。

8. 最佳实践与工程建议

叙事约束是一把双刃剑。约束太强,模型像在“填表格”,句子生硬;约束太弱,token 节省不明显。以下是长期实践下来比较有效的经验。

8.1 设计约束的五个原则

  • 原则一:结构优先于措辞。先规定章节和列表,再规定每项字数,不要颠倒。
  • 原则二:给正例比给反例更有效。与其说“不要写总结”,不如直接说“最后一个章节必须是下周计划”。
  • 原则三:控制规则数量。超过 5 条时,模型容易顾此失彼,建议合并同类项。
  • 原则四:每条规则都要可验证。比如“每项不超过 25 字”是可客观判断的,“语言要流畅”不是。
  • 原则五:预留一个自由字段。完全不放行会导致信息损失,一个comment字段能避免模型把没说清楚的话强行塞进别处。

8.2 叙事约束与结构化输出的配合

如果你的项目已经使用了 structured output 或 function calling,叙事约束依然有位置。它不是替代结构化输出,而是专门针对“非结构化生成内容”的压缩手段。

当模型必须返回一段可读文本时,结构化输出无法约束文本内部的表达方式,叙事约束会补上这个空缺。所以两者是互补关系,不是竞争关系。

8.3 生产环境部署建议

在生产环境上,token 优化不能只靠“改了 prompt 就上线”。建议做三件事:

  1. 把约束模板作为配置项,而不是硬编码在代码里。这样调整字数限制或者章节名时,不用改代码重新发布。
  2. 对每次调用记录prompt_tokenscompletion_tokens,形成消耗曲线。当改版后 token 不降反升,可以及时回溯。
  3. 定期抽查 5% 的约束输出,确认信息覆盖度没有悄悄下降。模型版本升级后行为可能变化,同一套约束模板在新模型上不一定同样好用。

8.4 安全与合规提醒

在 prompt 中加入约束时,不要将业务敏感信息直接写在 system prompt 里。尤其是约束模板是要被复用的,它可能被记录在日志中,也要被团队成员评审。敏感字段应该通过变量注入到 user message 或专门的上下文字段中。

另外,如果你的约束模板变成了团队内部的“标准做法”,记得维护一份变更记录。你新增一个字段,可能影响下游解析逻辑,需要同步通知调用方。

9. 总结与后续学习方向

叙事约束的核心价值,不是让你把所有 LLM 输出都压成“电报体”,而是给你一种可预期、可量化的 token 控制手段。

Semantic Thermodynamics 这个方向,表面上是借用了热力学的概念,本质上是在提醒你一件事:面对 LLM,约束不是创新的枷锁,它是信息密度的杠杆。一句“请简短回答”是模糊的意图,而一套“三章结构 + 列表 + 字数上限”的叙事约束,才是真正能落到工程里的方案。

建议你接下来做三件事:

  1. 用本文的脚本,把你业务中最高频的一个生成场景测一遍,拿到真实 token 下降数据。
  2. 根据业务特点设计一套专属约束模板,先在小流量下验证信息覆盖度。
  3. 把约束模板配置化,并接上 token 消耗监控,观察长期收益。

如果你的任务本身就是高度结构化的,比如生成 JSON 或者调用工具参数,叙事约束的收益会小一些。但如果你在做周报生成、会议摘要、Agent 多轮压缩、文档整理这类“高冗余文本”任务,这套方法很可能是目前成本收益比最高的优化方式。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询