LLM调用成本优化:从Token计费到Prompt瘦身与模型路由实践

发布时间:2026/10/14 11:19:17
LLM调用成本优化:从Token计费到Prompt瘦身与模型路由实践 1. 先把Token账单算明白再谈省钱很多人一听到“节约Token”就急着找Prompt压缩技巧但我觉得第一步不是想技巧而是先把计费逻辑摸清楚。Token就是模型处理文本的最小单位中文一个汉字可能对应1到2个Token英文则按词根切分。调用LLM时任何输入进来的系统提示、历史对话、用户问题以及模型吐出来的每一个字全部都要折算成Token按量计费。这个成本结构跟平时买东西不一样它是“你还没拿到结果就开始扣钱”的。哪怕模型一句话都没回复只要请求发出去输入的Token就已产生费用而且绝大多数平台对输出Token的单价要比输入更贵有些甚至是几倍的差距。也就是说光盯着“让回复变短”还不够输入那边才是大头尤其多轮对话场景里历史消息会反复累计。我接触过不少项目一开始觉得调用量不大结果月末账单出来直接傻眼。后来帮某团队做过一次成本盘点发现一个非常典型的浪费模式系统提示词写了上千字每轮都带上历史对话从来不裁剪聊到十几轮直接变成几万Token的上下文工具函数的说明书比代码本身还要长。这一套组合拳下来一次调用消耗的Token量几乎是业务原来预估的五倍以上。所以如果你问我节约Token从哪里开始我会先回答先拿出一天的真实日志统计每一类请求的平均输入Token、输出Token、单次成本。没有这个数据后面所有的优化都是拍脑袋。常用平台的控制台一般都能查token用量没有的话就自己埋点在请求前后分别记录usage字段并入库。等数据攒上几天哪些业务流程是吞金兽一眼就能看出来。有一个基本原则我建议刻在脑子里调用LLM之前先问自己三个问题——这个问题是否真的需要LLM参与哪些上下文模型必须要知道哪些只是我顺手塞进去的输出内容需要多精细能不能接受更短的回复这三个问题想清楚节流的思路会自然浮现出来。2. 输入侧先动手Prompt瘦身与结构化改造2.1 一句一句删把Prompt当成欠了债的文案Prompt占的是输入Token而且每调用一次就花一次比输出Token更容易失控。你可以做一个“减重练习”把现有Prompt逐句过一遍凡是不影响语义的字全部删掉。我见过很多Prompt开头写“你好你是一个智能助手你的任务是帮助用户解决各种问题你拥有以下能力……”这一串其实对模型理解任务几乎没有额外帮助属于典型的冗余。真正有意义的Prompt只需要包含三部分角色约束可选、任务说明、输入数据与输出格式。注意这里的“角色约束”也不是越长越好。你完全没必要给模型打造一个几百字的小传只需一两句话说明“你是客服助手回答要简洁、直接、使用简体中文”效果和长篇大论基本一致。另一类冗余是客套语。比如“请您根据以下内容进行回答非常感谢”这类话模型既不会因此更卖力也不会因此更友善删掉之后输出质量不会有任何变化。还有“如果可以的话”“如果你知道的话”这种模糊填充词纯粹是在给Token账单加码。我习惯做一个最小化测试先把Prompt砍掉50%用同样的测试集跑一遍看效果是否可接受如果效果还行再继续砍到30%-40%。实际测下来很多业务Prompt在压缩一半之后模型回答质量不降反升因为干扰信息少了注意力更集中。2.2 固定模板加变量插槽比临时拼字符串强得多有些团队让业务方通过接口直接传一段自由文本后台再拼上系统提示就发给模型看起来方便实际上埋了好几个坑。自由文本里很容易混入格式混乱的描述、重复信息甚至会让Prompt的公共部分无法复用。更好的做法是做一个固定的模板只有必要的位置留出变量插槽。举个例子我在某个客服项目里用的是这种模板prompt_template ( 你是{bot_role}。\n 用户提问{user_question}\n 已知订单状态{order_status}\n 历史处理结论{history_conclusion}\n 请直接输出处理建议不要复述问题控制在80字内。 )这样做的意义不只是省事。固定模板意味着每次请求的“公共前缀”是稳定的很多模型服务商对相同前缀的请求有自动缓存机制命中之后前面的Token费用会大幅降低甚至免费重算。如果你用字典动态拼接每次开头都不同缓存很难生效白白多花钱。另外模板中能不放的信息坚决不放。比如“当前系统时间”如果业务用不上就别加“用户所在地区”除非用于定制回答否则也别塞进去。总之原则就一句话只有对生成结果有影响的变量才值得随请求一起发出去。2.3 少样本示例要精挑能用一个就不用两个少样本提示few-shot确实能提升输出稳定性但代价是每个示例都会变成输入Token永远存在。很多人在Prompt里塞五六个示例生怕模型看不懂结果五六个示例就是大几百Token比任务本身还贵。这里有一个经验如果任务语义足够明确比如“把用户输入转成JSON格式”零示例就够了如果任务需要特定输出风格给一个典型示例即可只有当模型的输出经常走偏、且规则难以用文字描述时才给两个示例但每个示例要刻意选择边界情况让信息密度最大化。比如你想让模型学会“对用户情绪进行三级分类”与其给三个普通例子不如给一个“平静”“一个愤怒”“一个夹杂幽默的讽刺”让模型从两个例子中掌握更多边界信号。2.4 动词标准化让Prompt句式一致、减少歧义这个细节容易被忽略。同一个意图你这次写“请提取”下次写“帮我解析”再下次写“分析一下”模型会花费额外的“理解成本”表现在输出上就是偶尔多出来的一句反问或补全。最佳实践是针对固定任务使用固定祈使句提取、判断、生成、改写、翻译。让Prompt呈现出“指令对象约束”的统一格式模型每轮要处理的内容更少输出也更稳。3. 输出侧别浪费响应裁剪与输出约束3.1 max_tokens并不是设置得越大越好使用API时max_tokens是控制输出上限的参数但它不是“最好留很大防止截断”。只要你设置了较大的值模型就会“默认”你允许它写这么多于是很多模型会尽量把内容填充到这个容量的六七成你如果不设置服务商又可能按平台默认值放得特别宽。所以节省Token的第一步就是给每个任务设置合理的输出上限。比如一个“判断用户意图”的任务输出只需要一个词下单、咨询、投诉。那么max_tokens设10就够了模型再啰嗦也会在10个Token内被截断。一个“文案改写”的任务如果要求50字以内max_tokens设200已经非常富裕因为50字的中文最多占100多Token。注意一点max_tokens不是想设多小就多小。太小会导致内容被硬截断尤其生成JSON时很容易截出残缺结构下游解析直接报错。所以这个参数需要通过实际测试找到“安全余量”先设一个小值看是否满足业务再往下压直到接近极限。通常我会取预期输出Token数乘以1.5倍作为安全值既能防截断又不会给模型“长篇大论”的空间。3.2 用结构化输出管住格式模型就没机会说废话很多时候模型输出的“废话”根源在于你只给了文字要求没强制结构。现在的API基本都支持JSON模式或者结构化输出只要在请求参数中开启并给定一个JSON Schema模型就会严格按结构返回不会再出现“好的我来帮你分析一下第一……”这种自白段落。我在项目中更推荐直接给Schema的方案。比如要做信息抽取我先定义好字段{ type: object, properties: { customer_name: {type: string}, order_id: {type: string}, issue_type: {type: string, enum: [物流, 退换货, 发票, 其他]}, sentiment: {type: string, enum: [负面, 中性, 正面]} }, required: [customer_name, order_id, issue_type, sentiment] }模型输出就被约束成紧紧巴巴的一段JSON几乎零废话。这个方案唯一的代价是Schema本身也会占输入Token所以Schema里的字段注释能省则省字段名本身足够表意就行。3.3 重试越少省得越多遇到模型输出格式异常很多人的第一反应是重新生成一次代价直接翻倍。更划算的做法是“先解析、后重试”。比如要求JSON输出先用解析器看看是不是标准JSON如果只是多了个尾逗号或说明文字我可能直接用后处理修正而不是重新调用。如果确实需要重试也要用截断后的错误信息去引导而不是把上一轮完整输出原样丢回去。还有一个小技巧但凡希望输出稳定temperature不要拉太高。默认值或偏低的值能让模型输出更容易落在预期分布里减少因“创造力”产生的重复修正。控制输出质量其实是控制重试成本这才是最容易被忽略的省钱方式。4. 多轮会话中上下文就是隐形吞金兽4.1 历史消息是怎么一步步吃钱的先算一笔账。假设系统提示词固定500 Token用户每轮提问平均80 Token模型每轮回答平均300 Token。第一轮请求的总输入是“系统提示用户第一问”也就是580 Token左右输出约300 Token。但到了第十轮如果你把全部历史都带上输入会变成“系统提示前九个回合的所有内容和第十轮提问”也就是500加9乘380再加80约4000 Token这还只是输入一次。如果每个问题都要带着这些历史重新推理成本就是你看到的线性甚至更陡的增长。更隐蔽的是历史消息里包含了模型之前的输出。模型输出是按更贵的价格计费的你再把它塞回下一次请求当输入等于同一份内容付了两次钱。所以在多轮场景里历史消息不是“免费的记忆”而是“带利息的复利”。4.2 滑动窗口只保留真正有用的回合我建议第一档优化直接上滑动窗口只保留最近N轮对话。具体保留多少取决于业务。简单咨询场景保留3到5轮就足够复杂分析场景适当放宽但不要超过10轮。超出窗口的历史不再进入模型而是进入“摘要层”或干脆丢弃。代码实现不复杂每次构造消息列表时先截断def build_messages(system_prompt, history, max_rounds5): recent history[-max_rounds * 2:] # 每轮含一条user和一条assistant messages [{role: system, content: system_prompt}] messages.extend(recent) return messages如果业务真的需要长期记忆我建议把历史事件抽取成结构化的“状态摘要”而不是原样保存聊天记录。比如客服场景里把“用户订单号、问题类型、客户的诉求、当前处理状态”整理成一段200字以内的摘要和聊天原文相比Token占用往往能减少80%以上。4.3 让模型定期帮你压缩笔记“摘要式代偿”是我特别推荐的一种方式每聊完一段就另起一个“快速请求”让模型把这段对话压成一句结论再把结论作为下一轮历史。这个额外的压缩请求也会消耗Token但和保留全文相比基本是九牛一毛。压一次的成本换来后面几十轮的持续省钱。举个例子一段800 Token的对话原文压缩后可能只剩100 Token如果这段对话要被后续五个问题反复引用省下的Token就是700乘以五次也就是3500 Token。这样的小投入非常划算。实际执行时还可以把压缩请求的控制参数调低模型不需要追求文采只要准确转述关键事实即可。4.4 能用微服务状态替代的就别让模型记很多项目在架构上有一个误区本该由数据库记录的信息让模型以对话文本形式“记住”。比如用户填了一个金额系统不存数据库而是依赖模型从上一轮输出里提取。下一次使用时又把整段对话带上让模型再次提炼。这在原型阶段可以理解但正式上线就是双重烧钱。正确做法是业务状态全部落到结构化存储里模型只负责“理解与生成”不要让它承担“记忆”的职责。只有模型真正需要的少数关键字段才作为变量写进Prompt。这个改动省下的Token往往比任何Prompt技巧都多。5. 工具调用与函数定义别把说明书写得像论文5.1 函数描述是Token黑洞凡是让模型能够调用工具的API都需要把函数列表、参数定义、描述信息一起发给模型。很多人给每个函数写一长串说明还附带“历史背景、设计原因、注意事项”全部折算成输入Token。我这段时间专门看过几个项目的工具定义发现有些函数的description长达三四百字而真正影响模型决策的只有“什么条件下调用它”“参数怎么填”最多一百字就能说清。精简函数描述有一个方向从“解释这个函数是什么”改成“告诉模型什么时候用、怎么用”。模型不需要理解你的代码实现只需要知道触发条件和传参规则。越接近“决策说明书”描述越短效果反而越好。5.2 动态装工具不要一次全塞在复杂Agent场景里一次请求带上二十个工具定义Token随随便便就上2000。这其实很容易优化先根据用户问题做一轮预判只装与该任务相关的三到五个工具其余不放入工具列表。预判可以用规则匹配也可以用一个极小的分类模型成本远低于大模型调用。比如某客服系统有“查订单”“改地址”“申请退款”“转人工”“查物流”五个工具用户问题里带关键词“物流”那就只装载“查物流”工具。另外还预留一个“其他”兜底分类。这样工具描述总量从几百行压缩到几十行单次请求省下的Token非常可观。5.3 合并小函数精简返厂次数还有一个思路把细粒度的函数“攒”成合并接口。比如系统原来有“获取用户名”“获取订单号”“获取商品列表”三个独立函数每次调用前模型都要选一次选错又重试。合并成一个“获取订单上下文”函数一次性吐出所有信息虽然这一次输出可能会长一点但省去了整数次工具调用的开销总成本往往更低。合并函数还有附带好处模型少做几轮“决策与拼接”出错的概率下降重试也随之减少。只从Token角度看也是稳赚不赔。6. 模型按任务分层省钱的关键其实是模型路由6.1 小任务用轻量模型大任务才上旗舰模型不是所有请求都需要最强模型。一个“判断用户消息是咨询还是投诉”的任务用轻量模型就够了“根据用户描述生成一份包含退款金额和操作步骤的解决方案”才值得请出旗舰模型。任务分级之后成本结构会发生质的改变。我的建议是建一个简单的路由层按任务类型和输入长度分流def route_task(task_type, input_len): if task_type classification and input_len 500: return cheap-model if task_type extraction and input_len 1000: return mid-model return flagship-model这只是示意具体阈值要按模型性价比、延迟要求来调。但核心思路是成立的把高频、简单、输出短的请求统统扔给廉价模型把低频、复杂、输出长的请求留给强模型。很多平台的小模型成本只有旗舰模型的十分之一同样的业务量模型分层之后账单能降一个数量级。6.2 非LLM能解决的事别硬叫LLM有一类浪费最冤本来用正则、字典、字符串替换就能完成的活儿非要用Prompt调模型。比如从订单号中提取订单日期正则三行搞定判断用户输入是否匹配某个商品名称精确匹配加别名表即可统计一条消息里的数字个数更不该让模型出手。这些任务放到LLM上单一请求成本不算高但如果是日请求量几十万的高频场景纯属烧钱。养成一个习惯接到需求先问“有没有非模型方案”。规则方法维护成本高那就用轻量分类模型而不是大语言模型。总之LLM应该只处理真正需要语义理解、开放生成的任务机械性任务一律走传统代码路径。6.3 给路由层配一个“置信度回落”模型分层之后另一个问题是如何保证效果不降级。我会给轻量模型的输出做一个置信度判断不确定时回落给旗舰模型。比如分类任务如果轻量模型给出了概率很低的答案或者解析结果落在未知类别就自动升级到强模型。这个策略既照顾了成本又不牺牲关键场景的效果。7. 让缓存和RAG替你挡掉重复请求7.1 完全相同的请求直接复用上一次结果业务里存在大量“相同或相似问题反复进来”的情况比如同一个用户连续问三次“我的订单到哪了”不同用户问“怎么退货”。如果每次都发一次完整Prompt就是重复付三遍钱。最简单的方式是做一个请求级别缓存以“任务类型用户输入关键变量”作为Key查询结果直接返回给用户压根不触发模型调用。这样既能降本又能显著降低延迟对用户体验也是正向提升。需要做的只是设置一个合理的缓存失效时间避免过期信息被复用。比如订单状态五分钟内可能变化TTL设六十秒过期后重新查询。这种动态业务场景下缓存命中率会打折但仍然是划算的。7.2 语义缓存相似问题不重复生成请求级别缓存只对完全相同的问题有效。进一步可以上语义缓存先把用户输入向量化和已有请求池做相似度检索相似度超过阈值就复用历史答案用一套新的文案模板做微调其实也可以完全复用。这在客服FAQ类业务里非常有效可能命中率能到百分之三四十。唯一要留意的是语义缓存的“度”。如果两个问题字面不同但答案确实一致缓存就赚了如果字面相近但实际业务状态不同就要小心误复用。为此可以把“业务状态快照”一并纳入缓存键比如订单号、用户等级、当前阶段等避免张冠李戴。7.3 长文档别整本塞进Prompt很多人的RAG流程是“检索到一堆相关片段然后全部拼到Prompt里”。一个片段500字拼上8个片段就是4000字而且还包含了重复信息。正确的做法是对检索结果做重排序过滤掉重复或低相关片段每个Top切片控制在模型真正需要的范围内。另外RAG场景有个比较常见的坑明明只需要某文档的第二章节内容却把整个文档摘要都带上了。应该做切片级别的精细定位把“与当前答案直接相关”的内容作为输入其余一概不给模型看。7.4 留意平台的自动缓存机制现在不少模型平台支持对相同前缀的请求做自动缓存命中部分不再重复计费或价格大幅折扣。这要求你在系统设计时尽量保持“前缀稳定”比如把所有系统提示、固定指令放在消息队列前面把变化的部分放在后面。这样一来即使对话每轮不同稳定前缀也更容易命中缓存。与之配套的是尽量复用同一个Prompt模板不要每一轮动态重写系统提示。哪怕只是系统提示里有毫秒级时间戳都会打断缓存前缀让省钱机制完全失效。这些细节不做日志比对根本发现不了问题。8. 我真实踩过的Token坑与省钱清单8.1 最容易忽略的三类浪费第一类是调试时随手打印大段上下文排完bug没改回来结果线上服务一直把完整调试内容发送给模型。这个我踩过一次账单整整翻了一倍。建议给请求封装统一入口在入口处做“必填字段过滤”只放白名单变量进入Prompt。第二类是“为了安全加限制”比如系统提示里反复写“不要泄露隐私”“不要编造信息”“不要在回答中出现违法内容”每一条都占据Token而且重复出现并不会显著提升安全性。合规约束应当在产品层面通过参数与后置过滤实现Prompt里只保留必要的一条。第三类是日志系统本身。很多团队会把完整Prompt和完整输出原样打日志日志服务按量计费而且大数据平台还要对文本做清洗。这些成本不体现在API账单里但同样属于运营成本。日志应只记录Token计数、请求时长、命中缓存与否等元数据必要时才保留快照。8.2 Token计数要按真实tokenizer来算很多人拿中文字符数当Token数误差极大。同一个模型家族内也有不同分词规则最准确的办法是直接使用模型服务商提供的tokenizer包来做预计算。在设计Prompt模板时可以顺手写一个小脚本自动统计模板Token数提交到代码库之前顺手看一下变化省到就是赚到。8.3 上线前的Token压测比想象中重要我建议在项目准备上线前跑一套“黄金问题集”把每个问题的Prompt Tokens、Completion Tokens、总费用全部打印出来算一次单用户完整对话的平均成本再乘上预期DAU和平均轮数得到月预估账单。如果这个金额超过预期就在上线前回头调整Prompt、窗口和模型路由。等真上线再发现成本爆炸改起来就非常被动。8.4 一个省钱效果的对比实验我们在某个模拟项目X里做过一组对比效果非常直观。优化前的流程是完整系统提示加全量历史消息加全套工具定义一次普通问答平均消耗2600 Token。优化后精简系统提示到100字、对话历史只留最近三轮、工具按需动态装载、输出开JSON模式并设max_tokens同样的问答平均只消耗600 Token左右。业务效果没有明显下降单次成本降低约七成。这组数据说明一件事Token优化不是“抠唆”式的极限压缩而是把正确的信息放在正确的位置把无关信息挡在请求之外。做到这个程度成本和效果是可以兼得的。最后再分享一个小技巧定期把线上请求抽样出来做“Token审计”重点关注那些Token消耗量异常大的Top会话看看是哪一层的设计在吃钱。很多优化点不是一开始就能发现的只有持续盯数据、持续调整Token账单才会越来越贴近你的业务真实需求。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询