前言
在大型语言模型(LLM)的应用中,token数量的管理是一个核心挑战。无论是模型的输入限制、计算资源的分配,还是成本的控制,token计数都至关重要。然而,当调用超过预期范围时,我们该如何应对?本书以一段简单的Python代码为起点,探索token管理的实用方法,帮助开发者从临时方案走向系统化解决方案。
第一章:问题的起源——调用超预期
1.1 大模型的token限制
- LLM为何对token敏感?从输入上下文窗口到输出生成长度。
- 案例:调用API时意外超出限制的后果(错误、成本激增)。
- 引出问题:如何提前发现和管理超预期情况?
1.2 临时方案的诞生
- JSON结构:
"original_data"
作为输入,"generated_text"
作为输出。 - 代码简介:统计token的简单工具。
- 临时方案的优势与局限性。
第二章:代码解构——从临时到实用
2.1 核心功能分析
以下是代码,我将逐部分解释其在token管理中的作用:
import os
import json
import tiktoken
def calculate_token(text, model="deepseek-v3"):
"""计算文本的token数量"""
try:
encoding = tiktoken.encoding_for_model(model)
tokens = encoding.encode(text)
return len(tokens)
except KeyError:
print("模型编码未找到。使用默认编码。")
encoding = tiktoken.get_encoding("cl100k_base")
tokens = encoding.encode(text)
return len(tokens)
def calculate_total_tokens(output_dir):
"""计算输出目录中所有JSON文件的总输入和输出token数量"""
total_input_tokens = 0
total_output_tokens = 0
total_files = 0
for filename in os.listdir(output_dir):
if filename.endswith(".json"):
file_path = os.path.join(output_dir, filename)
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
input_tokens = calculate_token(data["original_data"])
output_tokens = calculate_token(data["generated_text"])
total_input_tokens += input_tokens
total_output_tokens += output_tokens
total_files += 1
print(f"文件: {filename}, 输入token: {input_tokens}, 输出token: {output_tokens}")
except Exception as e:
print(f"处理文件 {filename} 时出错: {e}")
print(f"\n总文件数: {total_files}")
print(f"总输入token数: {total_input_tokens}")
print(f"总输出token数: {total_output_tokens}")
output_dir = "generated_jsons"
calculate_total_tokens(output_dir)
calculate_token
:计算单段文本的token数,支持特定模型(如“deepseek-v3”),并提供备用编码。calculate_total_tokens
:扫描目录,统计所有JSON文件的输入和输出token总数。- JSON结构:临时设计的
"original_data"
和"generated_text"
字段,直观反映模型的输入输出。
2.2 代码的应用场景
- 调试:快速检查每次调用的token消耗。
- 成本估算:按token计费时,预估总费用。
- 优化提示:识别长输入或冗长输出,调整策略。
2.3 局限性与改进方向
- 临时性:JSON结构简单,但缺乏元数据(如模型参数、时间戳)。
- 单一性:仅支持固定字段,难以扩展。
- 性能:对大量文件处理效率低。
第三章:应对超预期——策略与实践
3.1 识别超预期情况
- 定义“预期范围”:输入token上限、输出token预算。
- 使用代码监控:实时统计token,设置阈值告警。
3.2 优化输入
- 文本压缩:去除冗余内容,精简
"original_data"
。 - 分段处理:将长输入拆分为多个调用。
- 示例代码:扩展
calculate_token
以支持分段。
3.3 控制输出
- 生成参数调整:限制
"generated_text"
长度(如设置max_tokens
)。 - 后处理:截断或总结超长输出。
- 示例代码:添加输出token阈值检查。
3.4 成本管理
- 计算token成本:结合API定价(如每千token $0.002)。
- 扩展代码:输出成本估算报告。
第四章:从临时到系统化
4.1 改进JSON结构
- 增强版JSON:
{ "input": { "text": "Hello, world!", "token_count": 4, "timestamp": "2025-03-12T10:00:00" }, "output": { "text": "Hello, world! How are you?", "token_count": 8, "model_params": {"max_tokens": 50} } }
- 优点:自描述性强,可追溯。
4.2 构建token管理系统
- 数据库存储:从JSON文件升级到SQLite或MongoDB。
- 实时监控:集成API调用,动态更新token统计。
- 可视化:用Matplotlib生成token使用图表。
4.3 示例实现
- 扩展代码:添加数据库支持、阈值告警和可视化。
import sqlite3
import matplotlib.pyplot as plt
def save_to_db(data, db_path="token_usage.db"):
conn = sqlite3.connect(db_path)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS usage
(filename TEXT, input_tokens INTEGER, output_tokens INTEGER)''')
for filename, input_t, output_t in data:
c.execute("INSERT INTO usage VALUES (?, ?, ?)", (filename, input_t, output_t))
conn.commit()
conn.close()
# 结合calculate_total_tokens,保存结果到数据库并绘图
第五章:未来展望
- 自动化token优化:AI驱动的输入输出调整。
- 跨模型兼容:支持更多模型的token化方案。
- 云端集成:将token管理部署为服务。
附录
- 代码完整版:包含所有扩展功能。
- 资源链接:
tiktoken
文档、LLM优化指南。
示例章节:第三章 - 应对超预期
3.1 识别超预期情况
当模型调用超出预期时,可能表现为:
- 输入超限:
"original_data"
超过模型上下文窗口(例如,GPT-3.5的4096 token)。 - 输出冗长:
"generated_text"
超出预算,增加成本。
使用现有代码,我们可以:
- 运行
calculate_total_tokens
,获取统计。 - 设置阈值,例如输入token > 3000 或输出token > 1000 时警告。
if total_input_tokens > 3000:
print("警告:输入token超出预期范围!")
3.2 优化输入
若"original_data"
过长,可尝试:
- 手动精简:删除不必要内容。
- 自动分段:
def split_text(text, max_tokens=2000):
encoding = tiktoken.get_encoding("cl100k_base")
tokens = encoding.encode(text)
if len(tokens) <= max_tokens:
return [text]
segments = []
for i in range(0, len(tokens), max_tokens):
segment = encoding.decode(tokens[i:i + max_tokens])
segments.append(segment)
return segments