義熱力學(xué)與敘事約束:把LLM輸出token砍掉79%的工程實(shí)踐)
如果你正在用大模型做 Agent、RAG 或者任何偏“生產(chǎn)級(jí)”的 LLM 應(yīng)用最近一定被同一個(gè)問(wèn)題折磨過(guò)token 不夠用。不是模型能力不行而是每一輪對(duì)話、每一段工具調(diào)用結(jié)果、每一次系統(tǒng)提示詞注入都在消耗上下文窗口。換更貴的模型能解決質(zhì)量卻解決不了成本做文本截?cái)嗄鼙W〈翱趨s往往把關(guān)鍵信息一起切掉。很多團(tuán)隊(duì)在模型選型和 RAG 方案上花了大量精力最后發(fā)現(xiàn)真正卡住業(yè)務(wù)規(guī)模的其實(shí)就是 token 預(yù)算。但這里面藏著一個(gè)被低估的事實(shí)大量 token 并不是“必須花”的而是模型在輸出時(shí)產(chǎn)生了大量敘事冗余——它用好幾句話表達(dá)本來(lái)一句話就能說(shuō)清楚的信息。模型不是不知道該簡(jiǎn)潔而是沒(méi)有人給它足夠的“敘事約束”。這篇文章想講清楚一個(gè)思路把 LLM 的輸出看作一個(gè)語(yǔ)義系統(tǒng)通過(guò)熱力學(xué)式的“約束”來(lái)降低語(yǔ)義熵讓每個(gè) token 都承載更多有效信息。這個(gè)思路對(duì)應(yīng)到一個(gè)很形象的概念——Semantic Thermodynamics中文可以叫“語(yǔ)義熱力學(xué)”。更重要的是不僅講概念還會(huì)給出一個(gè)可以在本地跑通的完整實(shí)驗(yàn)讓你親自測(cè)量在同樣的任務(wù)里使用敘事約束和不使用敘事約束輸出 token 到底差多少。這也是“79% token reduction”這類(lèi)數(shù)字最靠譜的理解方式它不是所有場(chǎng)景的普適結(jié)論而是在高冗余文本生成任務(wù)里約束帶來(lái)的真實(shí)收益。1. 這篇文章真正要解決的問(wèn)題先說(shuō)痛點(diǎn)。假設(shè)你維護(hù)一個(gè)內(nèi)部的 RAG 問(wèn)答系統(tǒng)。用戶上傳一份 2000 token 的產(chǎn)品文檔系統(tǒng)召回 3 個(gè)片段每個(gè) 500 token再加上 system prompt 和用戶問(wèn)題輸入側(cè)大概 4000 token。模型生成回答如果沒(méi)有任何輸出約束一次返回 800 token 是常有的事。這看起來(lái)很平常但如果你的業(yè)務(wù)是每天幾千次調(diào)用這個(gè)成本就非常可觀。更麻煩的是 Agent 場(chǎng)景。Agent 需要多輪工具調(diào)用每一輪都要把之前的對(duì)話歷史、工具返回結(jié)果、中間思考塞進(jìn)上下文。一個(gè) 5 輪調(diào)用的任務(wù)輸入輸出累計(jì)可能輕松突破一兩萬(wàn) token。而在這其中有很大一部分是“敘述性”的模型在復(fù)述已知信息、在重復(fù)套話、在生成格式松散的過(guò)渡句。傳統(tǒng)優(yōu)化手段有幾種但都有代價(jià)換更小/更便宜的模型質(zhì)量可能下降。手動(dòng)截?cái)鄽v史可能丟失關(guān)鍵上下文。用摘要代替原文摘要本身產(chǎn)生的 token 也很高而且損失細(xì)節(jié)。這些方法都默認(rèn) token 消耗是“輸入側(cè)”的問(wèn)題只要把輸入壓小就行。但實(shí)際上輸出側(cè)的敘事冗余同樣重要而且往往被忽略。所謂敘事約束不是簡(jiǎn)單地說(shuō)“請(qǐng)簡(jiǎn)短回答”而是從輸出結(jié)構(gòu)下手告訴模型必須按什么模板、什么粒度、什么順序來(lái)生成。約束越明確模型的輸出就越接近“最小語(yǔ)義集”廢話自然減少。這篇文章適合誰(shuí)正在做 LLM 應(yīng)用開(kāi)發(fā)想壓 token 成本的技術(shù)人員。維護(hù) RAG 或 Agent 系統(tǒng)被上下文窗口撐爆困擾的工程師。對(duì)“結(jié)構(gòu)化輸出”“輸出約束”有興趣但沒(méi)時(shí)間系統(tǒng)整理方法的開(kāi)發(fā)者。讀完之后你能得到一個(gè)可以直接運(yùn)行的示例以及一套判斷“什么時(shí)候該用約束”的實(shí)踐指南。2. Semantic Thermodynamics 的核心概念把 LLM 輸出看成語(yǔ)義系統(tǒng)第一次看到“Semantic Thermodynamics”這個(gè)詞大概率會(huì)覺(jué)得它很玄學(xué)。它聽(tīng)起來(lái)像是物理學(xué)的分支實(shí)際上它并不是一個(gè)嚴(yán)格的熱力學(xué)理論也不是某個(gè)官方標(biāo)準(zhǔn)而是一種思考模型輸出與 token 消耗之間關(guān)系的方式。通行的認(rèn)識(shí)是LLM 的每個(gè)輸出 token本質(zhì)都是在“內(nèi)容空間”中做一次選擇。如果這個(gè)選擇的隨機(jī)性很高模型就會(huì)輸出大量低價(jià)值、可預(yù)測(cè)的過(guò)渡內(nèi)容如果選擇被強(qiáng)烈約束模型就必須把語(yǔ)義集中到有限幾個(gè) token 上??梢杂脽崃W(xué)里的概念來(lái)類(lèi)比熵在信息論里熵表示不確定性。LLM 生成的文本中如果候選詞分布很分散、上下文信息弱輸出就更“混亂”表現(xiàn)為結(jié)構(gòu)松散、重復(fù)表達(dá)。這類(lèi)輸出可以看作“高語(yǔ)義熵”。自由能熱力學(xué)中系統(tǒng)能對(duì)外做功的部分叫自由能。對(duì)應(yīng)到 LLM 輸出真正對(duì)任務(wù)有價(jià)值的語(yǔ)義信息就是“有效語(yǔ)義”。大量 token 消耗在維持“句式完整”“語(yǔ)氣自然”“表達(dá)柔和”上這些不是有效語(yǔ)義。約束/邊界條件把一個(gè)氣體系統(tǒng)關(guān)進(jìn)容器它就不能無(wú)限膨脹。敘事約束也是一種“邊界條件”把模型的表達(dá)范圍限定在一個(gè)緊湊的結(jié)構(gòu)里。所以Semantic Thermodynamics 的通俗解釋是在模型輸出能力不變的情況下通過(guò)增加敘事約束降低輸出文本的語(yǔ)義熵讓每個(gè) token 攜帶更多有效語(yǔ)義。為什么叫“敘事”約束因?yàn)榧s束的對(duì)象不是單個(gè)詞匯而是模型生成內(nèi)容的組織方式。比如輸出必須分為 3 個(gè)章節(jié)。每章只能用列表。每項(xiàng)不超過(guò) 20 字。不要輸出總結(jié)段落。不要重復(fù)問(wèn)題中的背景信息。這些約束都作用于“敘述結(jié)構(gòu)”所以叫 narrative constraints。理解了這一點(diǎn)你就抓住了標(biāo)題里“79% token reduction”背后的邏輯當(dāng)任務(wù)本身冗余度高約束帶來(lái)的收益就極大。反過(guò)來(lái)如果任務(wù)本身已經(jīng)很緊湊比如直接生成 JSON 數(shù)據(jù)約束能帶來(lái)的空間就有限。3. LLM Token 成本構(gòu)成為什么“敘事冗余”會(huì)影響預(yù)算要真正理解約束的價(jià)值得先把 token 成本拆開(kāi)看。3.1 Token 成本的三部分一次完整的 LLM 調(diào)用token 消耗由三部分組成組成部分含義典型來(lái)源輸入 token系統(tǒng)提示、用戶輸入、檢索結(jié)果、對(duì)話歷史Prompt 設(shè)計(jì)與 RAG 召回輸出 token模型生成的內(nèi)容回答、總結(jié)、工具調(diào)用參數(shù)緩存/日志 token重復(fù)調(diào)用時(shí)的歷史記錄、日志分析多輪 Agent、長(zhǎng)期會(huì)話很多優(yōu)化方案只盯著第一項(xiàng)比如把 system prompt 寫(xiě)得更短、減少檢索片段。但輸出 token 同樣重要尤其是在生成型任務(wù)中。3.2 輸出側(cè)冗余的真實(shí)場(chǎng)景舉一個(gè)非常常見(jiàn)的例子。你讓模型把開(kāi)發(fā)記錄整理成周報(bào)模型可能會(huì)這樣輸出“本周我們團(tuán)隊(duì)主要圍繞訂單服務(wù)展開(kāi)了一系列優(yōu)化工作。首先完成了日志采集系統(tǒng)的搭建并成功接入了 order-service 和 payment-service 兩個(gè)核心服務(wù)。其次……”這段文本信息密度很低。真正有效信息只有“搭建日志采集接入兩個(gè)服務(wù)”其余都是敘事連接。如果任務(wù)規(guī)模再大一點(diǎn)比如整理本周 20 條開(kāi)發(fā)記錄模型很容易生成 800 到 1000 token 的周報(bào)。而如果加上約束要求“只輸出三章列表每項(xiàng)不超過(guò) 25 字”同一份開(kāi)發(fā)記錄模型可能只需要 200 token 就能表達(dá)同樣的信息。這就是敘事冗余在輸出側(cè)造成的浪費(fèi)。它不像輸入側(cè)那樣直觀但累計(jì)起來(lái)非常驚人。3.3 傳統(tǒng)壓縮方案 vs 敘事約束有人會(huì)說(shuō)那直接在 Prompt 里加一句“請(qǐng)簡(jiǎn)短回答”不就行了區(qū)別很大。方法原理問(wèn)題直接要求“簡(jiǎn)短”模型自行判斷壓縮程度效果不穩(wěn)定容易丟失關(guān)鍵信息或仍然冗長(zhǎng)截?cái)噍敵銮袛嚅L(zhǎng)文本破壞語(yǔ)義完整性摘要/壓縮中間結(jié)果用另一輪 LLM 調(diào)用壓縮內(nèi)容增加額外 token 消耗且摘要也可能冗余敘事約束固定輸出結(jié)構(gòu)限制粒度需要設(shè)計(jì)模板但效果可預(yù)測(cè)、可復(fù)用敘事約束的優(yōu)勢(shì)在于“可預(yù)期”。你規(guī)定模型輸出 3 章、每章 3 條列表它就會(huì)接近這個(gè)結(jié)構(gòu)。你可以提前估算輸出 token 上限這對(duì)成本控制是非常有價(jià)值的。4. 敘事約束的四種落地方式敘事約束不是一個(gè)單一技巧而是一類(lèi)方法的合集。在實(shí)際工程中常見(jiàn)的有四種落地方式4.1 輸出結(jié)構(gòu)約束這是最直接的一種。在 system prompt 里明確告訴模型輸出必須包含哪些章節(jié)、章節(jié)的順序是什么、每個(gè)章節(jié)用什么樣的排版。示例請(qǐng)將下面的會(huì)議紀(jì)要整理為項(xiàng)目周報(bào)并嚴(yán)格遵守以下約束 1. 只輸出三個(gè)章節(jié)# 本周進(jìn)展、# 問(wèn)題與風(fēng)險(xiǎn)、# 下周計(jì)劃。 2. 每個(gè)章節(jié)使用無(wú)序列表不允許出現(xiàn)段落式描述。 3. 不要輸出任何總結(jié)、建議或客套話。結(jié)構(gòu)約束的本質(zhì)是“定義模板”。模型在模板內(nèi)填充內(nèi)容時(shí)不會(huì)浪費(fèi) token 在過(guò)渡句上。4.2 輸出格式約束把輸出格式限定為 JSON、CSV、YAML 等機(jī)器可讀格式。這不僅能壓縮 token還能讓下游程序直接解析減少額外 JSON 解析和清洗成本。示例請(qǐng)輸出 JSON 格式字段為 { summary: 不超過(guò)50字的一句話總結(jié), items: [不超過(guò)20字的關(guān)鍵進(jìn)展], risk: 無(wú)則填null }需要注意JSON 的字段名本身也會(huì)消耗 token所以字段名盡量短。但可讀性也不能太差團(tuán)隊(duì)內(nèi)部需要約定一套通用的短字段命名。4.3 思維鏈壓縮推理任務(wù)中思維鏈Chain of Thought能提升效果但也會(huì)帶來(lái)大量中間 token。敘事約束在這里的作用是保留關(guān)鍵推理步驟刪除重復(fù)推理過(guò)程??梢赃@樣約束請(qǐng)分步驟給出推理過(guò)程但每個(gè)步驟不超過(guò)一行并且只保留與結(jié)論直接相關(guān)的推理。這屬于“輕量約束”保留了思維鏈的能力但限制了它的膨脹。4.4 多輪上下文壓縮這個(gè)更適合 Agent 場(chǎng)景。當(dāng)對(duì)話歷史超過(guò)一定長(zhǎng)度時(shí)用一次帶敘事約束的 LLM 調(diào)用把歷史壓縮成“關(guān)鍵事實(shí)列表”而不是用原始文本繼續(xù)拼接。示例壓縮指令請(qǐng)將以下多輪對(duì)話壓縮為事實(shí)清單 1. 每行一個(gè)事實(shí)不超過(guò)20字。 2. 只保留對(duì)后續(xù)任務(wù)有影響的決定、結(jié)論和未解決問(wèn)題。 3. 不要輸出對(duì)話過(guò)程的描述。這樣在后續(xù)調(diào)用中輸入歷史從幾千 token 降到幾百 token。壓縮本身雖然消耗一次調(diào)用但總體上通常是節(jié)省的而且上下文精度更高。5. 完整示例用敘事約束降低 LLM Token 消耗前面講了概念和方法這一節(jié)用一個(gè)可以實(shí)際運(yùn)行的腳本驗(yàn)證敘事約束對(duì) token 的影響。5.1 環(huán)境準(zhǔn)備建議使用 Python 3.9。需要安裝兩個(gè)依賴(lài)pip install openai tiktoken如果你還沒(méi)有設(shè)置 API Key先設(shè)置環(huán)境變量export OPENAI_API_KEY你的_API_KeyWindows 下使用set OPENAI_API_KEY你的_API_Key文中下面的示例使用 OpenAI 接口風(fēng)格模型選擇上建議使用你實(shí)際可用的模型比如gpt-4o-mini。腳本里通過(guò)變量統(tǒng)一配置方便替換。5.2 完整實(shí)驗(yàn)?zāi)_本場(chǎng)景把一段開(kāi)發(fā)記錄整理成技術(shù)周報(bào)。對(duì)比“無(wú)約束”和“敘事約束”兩種模式下輸出 token 的差異。# 文件路徑narrative_constraint_demo.py import os import textwrap import tiktoken from openai import OpenAI client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) encoder tiktoken.get_encoding(cl100k_base) # 未約束版本 FREESTYLE_SYSTEM ( 你是技術(shù)團(tuán)隊(duì)負(fù)責(zé)人請(qǐng)根據(jù)開(kāi)發(fā)記錄整理一份技術(shù)周報(bào)。 要求表達(dá)自然、內(nèi)容完整、邏輯通順。 ) # 敘事約束版本 CONSTRAINED_SYSTEM textwrap.dedent(\ 請(qǐng)把開(kāi)發(fā)記錄整理成技術(shù)周報(bào)并嚴(yán)格遵守以下敘事約束 1. 只輸出三個(gè)章節(jié)# 本周進(jìn)展、# 問(wèn)題與風(fēng)險(xiǎn)、# 下周計(jì)劃 2. 每個(gè)章節(jié)使用無(wú)序列表每項(xiàng)不超過(guò) 25 字 3. 不輸出問(wèn)候語(yǔ)、總結(jié)段落、補(bǔ)充解釋 4. 總列表項(xiàng)不超過(guò) 8 個(gè)。 ) DEV_RECORDS textwrap.dedent(\ 周一搭建日志采集接入 order-service 與 payment-service。 周二完成訂單超時(shí)取消任務(wù)覆蓋測(cè)試通過(guò)。 周三修復(fù)支付回調(diào)偶發(fā)超時(shí)根因是數(shù)據(jù)庫(kù)連接池不足。 周四訂單服務(wù) QPS 壓測(cè)由 800 提升到 1200。 周五數(shù)據(jù)看板聯(lián)調(diào)完成導(dǎo)出按鈕樣式待調(diào)。 ) def call_and_count(system_prompt: str, user_content: str, model: str gpt-4o-mini): 調(diào)用模型并返回生成文本和 token 使用量 resp client.chat.completions.create( modelmodel, messages[ {role: system, content: system_prompt}, {role: user, content: user_content}, ], temperature0.3, ) output_text resp.choices[0].message.content return output_text, resp.usage def local_prompt_token_count(): 本地統(tǒng)計(jì)兩類(lèi) prompt 的輸入 token方便不調(diào)用 API 也能對(duì)比 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}, fcompletion{free_usage.completion_tokens}, ftotal{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}, fcompletion{con_usage.completion_tokens}, ftotal{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 腳本關(guān)鍵邏輯說(shuō)明腳本分為三部分本地計(jì)算 prompt 的 token 數(shù)。通過(guò) tiktoken 估算輸入側(cè)的差異。在這個(gè)例子里約束版 system prompt 會(huì)更長(zhǎng)一些這是因?yàn)樗嗽敿?xì)規(guī)則但這部分成本是一次性且可復(fù)用的。使用同一個(gè)開(kāi)發(fā)記錄分別調(diào)用兩次模型。一次“自由發(fā)揮”一次“敘事約束”。輸出文本本身打印出來(lái)可以直觀感受兩者差異。通過(guò) API 返回的usage字段精確獲得輸出 token 數(shù)并計(jì)算下降比例。這里有一個(gè)容易被忽略的細(xì)節(jié)如果你在系統(tǒng)提示詞中寫(xiě)了一套敘事約束它會(huì)被復(fù)用到后續(xù)所有調(diào)用中所以 prompt 本身多消耗的 token 是值得的。只要約束能讓每次輸出節(jié)省 200 token調(diào)用 10 次就節(jié)省了 2000 token遠(yuǎn)大于 prompt 增加的部分。5.4 運(yùn)行與驗(yàn)證運(yùn)行命令python narrative_constraint_demo.py如果一切正常你會(huì)看到兩類(lèi)輸出文本和 token 統(tǒng)計(jì)。判斷實(shí)驗(yàn)是否成功的標(biāo)準(zhǔn)兩類(lèi)版本都生成了周報(bào)內(nèi)容。約束版的輸出結(jié)構(gòu)嚴(yán)格符合 3 章列表要求。約束版輸出 token 明顯少于未約束版。約束版的正文仍然覆蓋了開(kāi)發(fā)記錄中的關(guān)鍵事實(shí)日志接入、超時(shí)取消、支付回調(diào)修復(fù)、QPS 提升、數(shù)據(jù)看板聯(lián)調(diào)。這最后一點(diǎn)最重要。Token 減少的代價(jià)不能是信息損失。約束后的輸出應(yīng)該更精煉而不是更殘缺。6. 運(yùn)行結(jié)果與效果驗(yàn)證以示例中的開(kāi)發(fā)記錄和模型表現(xiàn)來(lái)看典型結(jié)果大致如下模式輸出 token 范圍優(yōu)點(diǎn)風(fēng)險(xiǎn)未約束700 - 1100表達(dá)自然閱讀體驗(yàn)好存在大量過(guò)渡句和重復(fù)描述敘事約束150 - 250token 少結(jié)構(gòu)可預(yù)期便于程序解析需要人工確認(rèn)信息覆蓋度如果你運(yùn)行后的下降比例恰好是 70% 左右說(shuō)明任務(wù)冗余度較高如果只有 30%說(shuō)明這個(gè)任務(wù)本身已經(jīng)足夠緊湊比如輸入本身是高度結(jié)構(gòu)化數(shù)據(jù)。79% 這個(gè)數(shù)字之所以會(huì)被用來(lái)做標(biāo)題通常對(duì)應(yīng)的是最典型的“周報(bào)/紀(jì)要/文檔摘要”類(lèi)任務(wù)。不要把它當(dāng)作所有場(chǎng)景都能復(fù)現(xiàn)的結(jié)果。如何更嚴(yán)謹(jǐn)?shù)仳?yàn)證約束是否有效建議做一個(gè) 20 條樣本的小測(cè)試準(zhǔn)備 20 個(gè)不同的輸入文本。每條分別用自由模式和約束模式生成。記錄輸出 token。人工檢查每條輸出是否覆蓋關(guān)鍵信息點(diǎn)。如果平均下降比例在 40% 以上且 90% 的樣本沒(méi)有丟失關(guān)鍵信息說(shuō)明這套約束模板適合你的業(yè)務(wù)可以放到生產(chǎn)環(huán)境里復(fù)用。如果某些樣本丟失信息就要調(diào)整約束規(guī)則的粒度比如把“每項(xiàng)不超過(guò) 25 字”放寬到“不超過(guò) 40 字”。7. 常見(jiàn)問(wèn)題與排查方法在實(shí)際工程中敘事約束并不是加上就有效果。下面幾個(gè)問(wèn)題非常典型問(wèn)題現(xiàn)象可能原因排查方式解決方案模型輸出不符合指定結(jié)構(gòu)約束規(guī)則模糊或相互沖突檢查 system prompt是否出現(xiàn)“要簡(jiǎn)潔又要完整”這類(lèi)矛盾表述將規(guī)則拆成可執(zhí)行的序號(hào)條款并配一個(gè)輸出示例信息丟失關(guān)鍵點(diǎn)沒(méi)寫(xiě)出來(lái)約束過(guò)強(qiáng)列表項(xiàng)數(shù)量限制過(guò)嚴(yán)對(duì)比約束前后輸出的信息點(diǎn)覆蓋數(shù)量適當(dāng)放寬字?jǐn)?shù)上限或允許“超出部分單獨(dú)用小字補(bǔ)充”模型仍然輸出大段解釋約束只寫(xiě)了“不要輸出解釋”但沒(méi)有給出替代結(jié)構(gòu)檢查是否定義了“如果必須解釋?xiě)?yīng)放在哪個(gè)字段”增加一個(gè)comment字段把必須的解釋集中放在末尾本地 token 統(tǒng)計(jì)與 API 計(jì)費(fèi)不一致tiktoken encoding 選擇與模型不匹配使用模型對(duì)應(yīng)的 encoding以 API 返回 usage 為準(zhǔn)計(jì)費(fèi)與優(yōu)化決策以 API 返回?cái)?shù)據(jù)為準(zhǔn)本地統(tǒng)計(jì)只做估算用了約束后質(zhì)量下降temperature 設(shè)置過(guò)高輸出隨機(jī)性增加在約束場(chǎng)景下調(diào)低 temperature 到 0.2 - 0.4生產(chǎn)環(huán)境建議 temperature 固定不用默認(rèn)值結(jié)構(gòu)化輸出偶爾不是合法 JSON模型沒(méi)有穩(wěn)定遵循 JSON 格式開(kāi)啟 response_formatjson_object 等結(jié)構(gòu)化輸出能力同時(shí)做 JSON 解析失敗重試不要把格式正確性完全交給模型7.1 一個(gè)容易踩坑的案例有一種錯(cuò)誤做法是把敘事約束寫(xiě)在用戶消息里而不是系統(tǒng)提示詞里。當(dāng)約束出現(xiàn)在用戶消息中時(shí)模型可能把約束和業(yè)務(wù)輸入混在一起理解優(yōu)先級(jí)沒(méi)有 system prompt 高。生產(chǎn)環(huán)境建議把穩(wěn)定的敘事約束模板放在 system prompt 中把每次變化的文本放在 user message 中。這樣既保證約束穩(wěn)定生效又方便統(tǒng)一更新模板。8. 最佳實(shí)踐與工程建議敘事約束是一把雙刃劍。約束太強(qiáng)模型像在“填表格”句子生硬約束太弱token 節(jié)省不明顯。以下是長(zhǎng)期實(shí)踐下來(lái)比較有效的經(jīng)驗(yàn)。8.1 設(shè)計(jì)約束的五個(gè)原則原則一結(jié)構(gòu)優(yōu)先于措辭。先規(guī)定章節(jié)和列表再規(guī)定每項(xiàng)字?jǐn)?shù)不要顛倒。原則二給正例比給反例更有效。與其說(shuō)“不要寫(xiě)總結(jié)”不如直接說(shuō)“最后一個(gè)章節(jié)必須是下周計(jì)劃”。原則三控制規(guī)則數(shù)量。超過(guò) 5 條時(shí)模型容易顧此失彼建議合并同類(lèi)項(xiàng)。原則四每條規(guī)則都要可驗(yàn)證。比如“每項(xiàng)不超過(guò) 25 字”是可客觀判斷的“語(yǔ)言要流暢”不是。原則五預(yù)留一個(gè)自由字段。完全不放行會(huì)導(dǎo)致信息損失一個(gè)comment字段能避免模型把沒(méi)說(shuō)清楚的話強(qiáng)行塞進(jìn)別處。8.2 敘事約束與結(jié)構(gòu)化輸出的配合如果你的項(xiàng)目已經(jīng)使用了 structured output 或 function calling敘事約束依然有位置。它不是替代結(jié)構(gòu)化輸出而是專(zhuān)門(mén)針對(duì)“非結(jié)構(gòu)化生成內(nèi)容”的壓縮手段。當(dāng)模型必須返回一段可讀文本時(shí)結(jié)構(gòu)化輸出無(wú)法約束文本內(nèi)部的表達(dá)方式敘事約束會(huì)補(bǔ)上這個(gè)空缺。所以?xún)烧呤腔パa(bǔ)關(guān)系不是競(jìng)爭(zhēng)關(guān)系。8.3 生產(chǎn)環(huán)境部署建議在生產(chǎn)環(huán)境上token 優(yōu)化不能只靠“改了 prompt 就上線”。建議做三件事把約束模板作為配置項(xiàng)而不是硬編碼在代碼里。這樣調(diào)整字?jǐn)?shù)限制或者章節(jié)名時(shí)不用改代碼重新發(fā)布。對(duì)每次調(diào)用記錄prompt_tokens和completion_tokens形成消耗曲線。當(dāng)改版后 token 不降反升可以及時(shí)回溯。定期抽查 5% 的約束輸出確認(rèn)信息覆蓋度沒(méi)有悄悄下降。模型版本升級(jí)后行為可能變化同一套約束模板在新模型上不一定同樣好用。8.4 安全與合規(guī)提醒在 prompt 中加入約束時(shí)不要將業(yè)務(wù)敏感信息直接寫(xiě)在 system prompt 里。尤其是約束模板是要被復(fù)用的它可能被記錄在日志中也要被團(tuán)隊(duì)成員評(píng)審。敏感字段應(yīng)該通過(guò)變量注入到 user message 或?qū)iT(mén)的上下文字段中。另外如果你的約束模板變成了團(tuán)隊(duì)內(nèi)部的“標(biāo)準(zhǔn)做法”記得維護(hù)一份變更記錄。你新增一個(gè)字段可能影響下游解析邏輯需要同步通知調(diào)用方。9. 總結(jié)與后續(xù)學(xué)習(xí)方向敘事約束的核心價(jià)值不是讓你把所有 LLM 輸出都?jí)撼伞半妶?bào)體”而是給你一種可預(yù)期、可量化的 token 控制手段。Semantic Thermodynamics 這個(gè)方向表面上是借用了熱力學(xué)的概念本質(zhì)上是在提醒你一件事面對(duì) LLM約束不是創(chuàng)新的枷鎖它是信息密度的杠桿。一句“請(qǐng)簡(jiǎn)短回答”是模糊的意圖而一套“三章結(jié)構(gòu) 列表 字?jǐn)?shù)上限”的敘事約束才是真正能落到工程里的方案。建議你接下來(lái)做三件事用本文的腳本把你業(yè)務(wù)中最高頻的一個(gè)生成場(chǎng)景測(cè)一遍拿到真實(shí) token 下降數(shù)據(jù)。根據(jù)業(yè)務(wù)特點(diǎn)設(shè)計(jì)一套專(zhuān)屬約束模板先在小流量下驗(yàn)證信息覆蓋度。把約束模板配置化并接上 token 消耗監(jiān)控觀察長(zhǎng)期收益。如果你的任務(wù)本身就是高度結(jié)構(gòu)化的比如生成 JSON 或者調(diào)用工具參數(shù)敘事約束的收益會(huì)小一些。但如果你在做周報(bào)生成、會(huì)議摘要、Agent 多輪壓縮、文檔整理這類(lèi)“高冗余文本”任務(wù)這套方法很可能是目前成本收益比最高的優(yōu)化方式。