☰
Token优化实战:从提示词压缩到上下文管理的API成本控制指南
2026/10/13 3:38:13 网站建设 项目流程

我们每次调用大模型 API 时,真正在花钱的并不是“输入多少字”,而是“输入多少个 token”。很多开发者把 Token 当作一个抽象概念,直到账单翻倍、上下文窗口报错、长对话突然截断,才开始回头审视提示词里到底塞了多少无效内容。

Token 优化不是让模型更聪明的手段,而是让每次请求更便宜、更快、更不容易出错的手段。同一套业务逻辑,提示词写得省一点,成本可以下降 30% 到 50%;上下文管理做得好一点,长文档处理不再需要开新会话重来;批量任务设计合理一点,一天的调用量能压缩到原来的三分之一。

这篇文章围绕《token优化手册》的核心思路,把 Token 的计数方式、提示词压缩、上下文管理、成本估算、批量调用、问题排查和最佳实践完整串起来。你可以把它当作一份可执行的优化清单,不需要额外安装复杂框架,也不需要改业务代码结构,只调整提示词组织方式和调用策略,就能直接看到效果。

1. 核心能力速览:Token 优化到底管什么

Token 优化并不是某一款软件,而是一套覆盖“拆解、压缩、管理、监控”四个环节的方法集合。先看清楚它解决的问题范围,再决定从哪里入手。

能力项说明
优化对象提示词、上下文历史、检索结果、模型输出约束
核心目标降低单次请求 Token 占用量,提升上下文利用效率
适用模型OpenAI 系、Anthropic 系、Gemini、DeepSeek、本地开源模型等所有按 Token 计价的模型
前置条件能查看 Token 计数结果即可,不需要专用服务器或显卡
主要手段提示词压缩、结构化输出、滚动窗口、摘要压缩、检索增强、缓存复用
支持批量任务是,批量任务里 Token 复用和失败重试的收益更明显
接口能力可与 OpenAI 兼容接口配合,通常只需要改请求参数
直接收益降低成本、减少超时、降低截断率、提升响应稳定性
适合人群调用大模型 API 的开发者、提示词工程师、自动化脚本维护者、使用 AI 工具处理长文档的内容团队

本手册的重点不是概念科普,而是可落地的操作方式。下面每章都会从问题触发,然后给出具体的压缩或管理方案,最后提供验证方法。

2. 先理解 Token:计数方式、计费单位和窗口限制

2.1 Token 是语言模型的“最小识别单位”

Token 是语言模型处理文本时的最小离散单元。模型并不是逐字阅读你的提示词,而是先把文本切分成 Token 序列,再按序列预测输出。

英文文本中,一个 Token 通常对应 0.7 到 1 个单词。中文文本中,模型的分词差异较大,一般一个汉字约等于 1 到 2 个 Token,具体取决于使用的 Tokenizer。这也是为什么同样字数的提示词,中文请求的 Token 消耗通常比英文更高。

2.2 计费公式

几乎所有大模型平台的计费都是按总 Token 数计算:

单次请求费用 = 输入 Token 数 × 输入单价 + 输出 Token 数 × 输出单价

很多平台输入和输出的单价不一致,输出 Token 通常更贵。因此,优化输出长度往往比压缩输入提示词更省钱,但压缩输入能减少上下文重新处理的时间,两者需要同时考虑。

2.3 上下文窗口不是“内存越大越好”

上下文窗口是模型一次能容纳的最大 Token 量。例如 128K 窗口,意味着输入和输出总共不能超过 128K Token。一旦超过,请求会直接报错;没有报错时,模型也会优先记住前后部分,中段内容容易被忽略。

所以,常见的长文本问题并不是“模型记不住”,而是“你一次性塞进去的 Token 太多,超过了注意力能覆盖的范围”。Token 优化要解决的正是这种超载场景。

上下文窗口 = 系统提示 + 历史对话 + 检索内容 + 工具定义 + 本次用户输入 + 最大输出 Token

窗口是固定上限,减掉一个部分,其他部分才能有更多空间。

3. 环境准备与 Token 计量工具

优化 Token 之前,先建立一个能“看到 Token 数量”的环境。没有量化,就没有优化。

3.1 使用官方 Tokenizer 工具

常用方案:

平台工具说明
OpenAItiktokenPython 库,可精确计数
Anthropicclaude-tokenizerPython 或 Node 均可调用
Hugging Facetokenizers兼容多种开源模型的分词器
各家网页端Token 计数器页面适合快速测试,不适合脚本批量调用

以 Python 为例,安装 tiktoken:

pip install tiktoken

对应 OpenAI 模型的使用示例:

import tiktoken encoding = tiktoken.encoding_for_model("gpt-4o") text = "欢迎使用 Token 优化手册,这里是一段中文测试文本。" tokens = encoding.encode(text) print("token 数量:", len(tokens)) print("解码验证:", encoding.decode(tokens[:5]))

这里要注意,不同模型的 Tokenizer 并不通用,同一段文字在不同模型下的 Token 数量可能存在差异。统计时要以实际调用模型对应的 Tokenizer 为准。

3.2 在调用日志里记录 Token 用量

真实 API 响应中通常带有 Token 使用字段。把每次请求的 Token 数据写入日志,是成本分析的基础。

以 OpenAI 风格接口为例,把响应中的 usage 字段落盘:

import json response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "你好"}], ) usage = response.usage log_entry = { "prompt_tokens": usage.prompt_tokens, "completion_tokens": usage.completion_tokens, "total_tokens": usage.total_tokens, } print(json.dumps(log_entry, ensure_ascii=False))

日志里至少应该包含 prompt_tokens、completion_tokens、total_tokens 三项。后续做成本归因、请求耗时分析,都依赖这笔记录。

3.3 本地模型场景怎么观察 Token

如果使用本地部署的模型,比如 Ollama、vLLM 或 llama.cpp,可以先通过官方服务日志查看 token/s 和 prompt eval 速度。Token 消耗不直接影响真金白银,但会显著影响响应时间:输入 Token 越多,前置处理阶段越长,首字延迟就越高。

4. 提示词设计与压缩:用更少 Token 表达相同意图

提示词压缩是 Token 优化里见效最快的一环。多数用户的第一版提示词里,至少有 20% 到 40% 是重复、铺垫和无效限制。

4.1 减少“角色扮演式”前缀

很多提示词开头会写“你是一个优秀的人工智能助手,拥有丰富的知识储备,请帮我……”。这类描述不会显著提升模型效果,却占了系统提示的固定 Token。

更优写法是把角色限定压缩成功能关键词,例如:

旧写法(占 30 token): 你是一个优秀的人工智能助手,拥有丰富的知识储备,能够回答各种领域的问题, 并且回答总是详细完整。请帮我总结下面这段文字的核心观点: {文本} 新写法(占 8 token): 总结以下文本的核心观点: {文本}

第二种写法在效果上通常不弱于第一种,却省下了大量 Token。如果担心模型输出不够详细,应该限制输出长度,而不是在系统提示里反复强调“详细”。

4.2 精简 few-shot 示例

少样本示例(few-shot)是有效提升输出格式稳定性的手段,但也是 Token 消耗大户。一条示例可能包含问题、标准答案、格式说明,动辄几百 Token。

压缩原则:

  • 每个示例只保留能体现格式差异的最小片段。
  • 示例数量控制在 1 到 3 条,不要堆多条相似例子。
  • 能用 JSON Schema 描述的输出结构,优先用结构化输出,不用示例演示。

例如,要模型输出 JSON,可以只给一个关键约束:

{ "instruction": "只输出 JSON,不要输出任何其他文字。", "schema": { "type": "object", "properties": { "title": {"type": "string"}, "summary": {"type": "string"} } } }

结构化的 schema 比几条自然语言示例更省 Token,同时更适合程序解析。

4.3 固定模板与变量分离

在批量任务中,提示词模板应把固定部分和可变部分分开。固定部分提前合并,可变部分只保留本次任务真正需要的字段。不要在每条请求里重复粘贴大段公共说明。

template = "提取以下文档中的关键信息:\n处理要求:{rules}\n文档内容:{document}" payload = template.format( rules="只返回 json,不要解释。", document=document_content, )

这里需要注意的是,rules 如果对所有请求都一样,可以直接拼到系统提示里,只让每条请求携带 document。这样可以避免每条请求都重复传送相同的规则描述。

4.4 指示模型“不用复述问题”

很多模型会习惯性复述用户的问题,或者在回答开头重复一遍要求。这类输出会白白消耗输出 Token。在系统提示里加入一行“直接给出结果,不要复述问题”,往往能显著减少输出 Token。

验证方法:用同一批测试问题,分别使用压缩前和压缩后的提示词,统计 total_tokens 和输出质量,取 20 条左右的平均值。

5. 上下文窗口管理:长文档、多轮对话与摘要压缩

5.1 滚动窗口思路

对于多轮对话,把所有聊天历史全部发给模型,Token 消耗会随轮次线性增长。更稳妥的做法是只保留最近的 N 轮内容,更早的历史转换成摘要。

当前请求上下文 = 早期对话摘要 + 最近 10 轮完整对话 + 当前用户问题

摘要的生成可以由模型完成,也可以直接截断。注意,摘要本身也需要消耗 Token,如果摘要占比太高,效果反而不好。通常摘要长度控制在完整历史的 10% 到 20% 比较合理。

5.2 长文档分块与分层总结

处理长文档时,不要直接把整篇文档塞给模型。推荐的做法是“先分块、再分块总结、最后汇总”。

例如一份 50 页的 PDF:

  1. 按章节或固定长度切成 5 到 10 个片段。
  2. 每个片段单独调用模型,输出摘要和关键信息。
  3. 把所有摘要合并,再让模型基于摘要输出最终结论。

这种方法下,每次请求的 Token 不会超过窗口限制,同时每段内容都能获得足够的注意力权重。

5.3 历史消息的 Token 预算分配

建议把上下文窗口划分为多个预算区:

区域建议占比用途
系统提示与固定规则5% - 10%稳定指令、输出格式
历史摘要5% - 10%早期对话、已处理文档
检索内容30% - 50%当前任务真正需要的资料
最近对话20% - 30%用户最新意图和上下文
输出缓冲5% - 10%留给生成结果

如果某个区域超出预算,优先削减历史完整对话,而不是压缩检索内容。当前任务相关的核心资料保留优先级最高。

5.4 使用截断与压缩策略组合

实际工程中,可以采用“先截断、再摘要、最后全文”的降级策略:

  1. 如果原文 Token 总数低于窗口阈值的 50%,直接全文传入。
  2. 如果超过阈值,先做关键段落抽取,只传入与问题相关的段落。
  3. 如果抽取后仍然超限,先生成每段摘要,再把摘要传入模型。

这个策略能在尽量保留关键信息的前提下,把每次请求的 Token 控制到稳定区间。

6. Token 计数、成本估算与预算监控

6.1 建立成本计算公式

在业务代码里,可以封装一个简单的成本计算函数:

MODEL_PRICE = { "gpt-4o": {"input": 0.0000025, "output": 0.00001}, # 单位:美元 / token } def estimate_cost(prompt_tokens, completion_tokens, model): price = MODEL_PRICE[model] return prompt_tokens * price["input"] + completion_tokens * price["output"]

不要写死价格,因为模型价格会变动。更好的做法是把价格表放到配置文件中,定期更新。

6.2 为调用量设置预警

在调用 API 的公共入口处,对累计 Token 做统计并设置预警线。例如每 1000 次请求统计一次:

total_prompt_tokens = 0 total_completion_tokens = 0 BUDGET_WARNING = 100_000_000 # 例如累计达到 1 亿 token 时预警 def log_usage(prompt_tokens, completion_tokens): global total_prompt_tokens, total_completion_tokens total_prompt_tokens += prompt_tokens total_completion_tokens += completion_tokens if total_prompt_tokens + total_completion_tokens > BUDGET_WARNING: send_warning_email()

预警的意义是让你在账单爆炸前就有感知,而不是等到月账单出来后才后悔。

6.3 用抽样估算代替全量统计

如果调用量很大,无法逐条记录,可以按百分比抽样。例如记录每 100 条中的 1 条,估算整体 Token 消耗和成本。抽样统计在工程上更容易实现,误差通常在 5% 以内。

7. 批量调用与 API 请求层面的 Token 优化

7.1 合并同类请求

如果多个任务共用相同的系统提示和检索材料,可以把它们合并到一条请求中,要求模型一次输出多个结果。这样可以复用输入 Token。

例如,一次请求完成 10 条文本的分类,而不是调用 10 次:

texts = [text_1, text_2, ..., text_10] prompt = f""" 对以下每段文本进行分类,输出 JSON 数组,数组顺序与输入顺序一致: {json.dumps(texts, ensure_ascii=False)} """

注意,合并请求的输出长度会变长,如果输出超限,可以按每组 3 到 5 条文本分批处理。合并后的单次请求如果失败,重试成本也更高,因此需要额外关注稳定性。

7.2 缓存重复请求结果

对于相同或相似的输入,使用缓存可以完全避免重复计费。常见做法:

  • 以文本哈希值作为缓存键,命中缓存时直接返回历史结果。
  • 对检索增强型应用,缓存文档向量和文本摘要。
  • 对多轮对话应用,只对最近几轮做精确哈希,不要缓存过长历史。
import hashlib def request_with_cache(text, model, cache: dict): key = hashlib.sha256(text.encode("utf-8")).hexdigest() if key in cache: return cache[key] result = call_model(text, model) cache[key] = result return result

缓存不仅能降低 Token 成本,还能显著降低接口延迟。

7.3 批量失败重试要控制重复请求次数

批量任务里最容易出现的浪费是“失败后直接重新请求”。如果接口返回超时错误,但并不确定模型是否成功处理,重发会产生重复计费。建议:

  • 为每条请求生成唯一 request_id,服务端做幂等处理。
  • 重试时使用指数退避,间隔从 1 秒开始逐步递增。
  • 对同一批次任务记录已用 Token,失败超过 3 次就转人工检查。

7.4 考虑使用模型自带的缓存机制

部分平台提供提示词缓存或上下文缓存功能,例如相同的前缀内容在短期内多次重复时,缓存部分的计价会更低。如果调用场景中前缀高度一致,比如固定系统提示加固定知识库前缀,可以优先使用这类能力。具体缓存策略与价格,以各平台官方文档为准。

8. 常见问题与排查方法

Token 优化过程中,大部分问题集中在超限、截断和成本飙升。下面给出问题现象、可能原因和排查方案。

问题现象可能原因排查方式解决方案
请求报上下文长度超限输入加输出超过窗口上限检查 usage.total_tokens 与 max_tokens压缩历史、缩小检索范围、调低 max_tokens
输出被截断预留的 max_tokens 不够查看响应是否包含 finish_reason=length调大 max_tokens,或改用流式输出分批处理
Token 成本持续上涨历史对话无限累积且重复传入检查日志中 prompt_tokens 的变化趋势启用滚动窗口和摘要压缩
批量任务响应太慢单次请求输入 Token 过多观察首字延迟和总耗时合并或拆分请求,权衡输入复用
输出格式不稳定提示词中示例过多或格式约束混乱测试不同示例数量下的格式通过率使用结构化输出或精简示例
缓存命中率低缓存键包含无关变量统计缓存命中率数据归一化缓存键,移除时间戳等无关字段
提示词压缩后效果变差压缩掉了必要的约束条件对比相同任务压缩前后的输出质量保留与任务强相关的约束,去掉空泛修饰

排查时最有效的方法是先看 usage 日志,再分析失败请求的公共模式。常见的优化错误是把所有压缩手段同时套上,导致输出质量明显下降,然后又全部回滚。正确做法是每次只改一个变量,用同一批测试集做 A/B 对比。

8.1 上下文超限时的紧急处理

如果线上环境已经出现大量超限错误,先立刻降低 max_tokens。这一步能让部分请求先恢复。然后再压缩历史或检索内容。不要在生产环境直接换模型,换模型的 Tokenizer 差异可能引起更多格式问题。

8.2 截断问题不一定要靠扩大窗口

输出截断时,很多人的第一反应是“加 max_tokens”。但更省 Token 的做法是让模型输出更精简。例如:

  • 限制输出为 Markdown 列表,不要长段落。
  • 要求先输出结论,再按需展开。
  • 对于超长内容输出,改用流式输出并分段保存。

9. 为不同任务设计 Token 预算

不是所有任务都需要相同规模的上下文预算。把任务按复杂度分级,可以避免高成本模型处理简单任务。

9.1 轻量任务

典型:文本分类、关键词提取、情感判断、格式转换。这类任务上下文需求小,系统提示应该极短,输入直接是核心文本,输出结构固定。预算建议控制在 1000 到 3000 Token 以内。

9.2 中度任务

典型:文档摘要、内容改写、信息抽取。需要传入足够相关上下文,但不需要全文。预算建议控制在 8000 到 20000 Token,按文档大小动态调整。

9.3 重度任务

典型:多轮深度问答、复杂业务推理、长文档跨章节分析。需要合理使用摘要和分段检索,预算可能达到 30000 Token 以上。此时必须配置缓存和成本监控,不能裸调接口。

预算优先分配顺序: 当前问题相关检索 > 当前输入文本 > 最近对话 > 早期摘要 > 长尾上下文

10. 最佳实践与合规提醒

10.1 工程落地清单

  • 每次请求都在日志中记录 usage 字段。
  • 所有提示词模板参数化,禁止在代码里硬编码长文本。
  • 为每条提示词模板设置 Token 预估上限,超出时自动截断或告警。
  • 批量任务使用批次记录、唯一请求 ID 和指数退避重试。
  • 缓存键要稳定,定期清理过期缓存,避免内存无限增长。
  • 上线前用同一批测试样本对比提示词压缩前后的输出质量,保留质量达标且成本更低的版本。
  • 成本监控报表按天和按模型维度统计,设置周环比增长率预警。

10.2 数据与合规边界

Token 优化过程中,不可避免要把业务文本发送给模型。无论使用云端 API 还是本地模型,都应遵守以下原则:

  • 用户敏感信息、隐私数据、未公开业务信息,不得随意发送到第三方模型服务。
  • 涉及人脸、声音、版权素材等内容的场景,必须确认已获得授权,并评估传播范围。
  • 企业环境优先使用私有化部署或签署数据协议的 API 服务。
  • 内部测试数据使用脱敏样本,避免在日志中保留完整敏感内容。
  • 模型输出可能包含幻觉内容,关键业务场景需要人工复核,不能完全自动化放行。

Token 优化只是让工具更高效的工程技术,不能突破数据合规与内容安全的底线。

11. 总结与下一步

Token 优化手册解决的核心问题只有一个:让每一分 Token 预算都花在刀刃上。

值得最先动手验证的是提示词压缩。把自己最常用的提示词拿出来,删掉角色铺垫、压缩示例数量、限制输出格式,对比压缩前后的 Token 用量和输出质量。通常这一小步就能看到 20% 以上的成本下降。

最容易踩的坑是一次性改造过多。压缩提示词后输出质量下降,不代表方向错误,而是变量太多。建议保留旧版本提示词,建立小规模测试集,每次只改一个环节,量化记录。

后续可以继续扩展的方向包括:接入 RAG 后按检索相关度动态裁剪上下文、针对不同模型固定一套提示词模板规范、建立更细粒度的 Token 成本报表,以及在服务端实现多层缓存。Token 优化不是一次性的优化动作,而应该沉淀为团队或个人的提示词工程规范。好的规范会随着调用量增长,自动让成本曲线变得更平缓。

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

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

立即咨询