首页 › LLM大语言模型 › 大模型技术工程 › 上下文工程 › 上下文窗口与Token完全指南:LLM分词原理、计数方法与成本优化策略

上下文窗口与Token完全指南:LLM分词原理、计数方法与成本优化策略

核心摘要​

Token是大语言模型处理文本的基本单位,上下文窗口决定了模型一次能处理的最大Token数量。本指南详细介绍Token化过程、主流分词算法(BPE、WordPiece、SentencePiece)、各模型上下文窗口对比、长上下文技术(RoPE、ALiBi),以及Token计数和成本优化的实用策略。​

​

​

引言​

当你使用ChatGPT、Claude或其他大语言模型时,是否好奇过:为什么有时候对话会被截断?为什么中文和英文的"长度"计算不一样?为什么API调用费用难以预估?​

这些问题的答案都与两个核心概念相关:Token和上下文窗口(Context Window)。理解它们不仅能帮助你更高效地使用AI工具,还能显著降低API调用成本。​

在本指南中,你将学到:​

•

Token的定义和Token化过程​

•

BPE、WordPiece、SentencePiece等分词算法的原理​

•

什么是上下文窗口及其重要性​

•

主流大模型的上下文窗口大小对比​

•

长上下文技术:RoPE、ALiBi、Sliding Window​

•

如何计算Token数量和估算成本​

•

优化上下文使用的实用策略​

​

​

什么是Token​

Token是大语言模型处理文本的最小单位。在模型眼中,文本不是字符或单词的序列,而是Token的序列。​

​

飞书文档 - 图片

​

Token与字符、单词的区别​

​

#evbhMWeLMlAc text { white-space: pre; }#evbhMWeLMlAc .fb0 { stroke: var(--N900-FG, 0.15); }#evbhMWeLMlAc .fb0 {stroke: rgba(31,35,41, 0.15)}#evbhMWeLMlAc .fx0 { stroke-miterlimit: 10; }#evbhMWeLMlAc .fx0 {stroke-miterlimit: 10}#evbhMWeLMlAc .fa1 { fill: rgb(187, 191, 196); }#evbhMWeLMlAc .fa1 {fill: rgb(187, 191, 196)}#evbhMWeLMlAc .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#evbhMWeLMlAc .fx1 {font-style: normal}#evbhMWeLMlAc .fx2 { text-anchor: middle; }#evbhMWeLMlAc .fx2 {text-anchor: middle}#evbhMWeLMlAc .fx3 { dominant-baseline: central; }#evbhMWeLMlAc .fx3 {dominant-baseline: central}#evbhMWeLMlAc .fx4 { stroke: none; }#evbhMWeLMlAc .fx4 {stroke: none}#evbhMWeLMlAc .fc0 { fill: var(--text-caption); }#evbhMWeLMlAc .fc0 {fill: #646a73}#evbhMWeLMlAc .fa2 { fill: var(--text-link-disabled); }#evbhMWeLMlAc .fa2 {fill: rgb(187, 191, 196)}#evbhMWeLMlAc .fa3 { fill: rgb(31, 35, 41); }#evbhMWeLMlAc .fa3 {fill: rgb(31, 35, 41)}#evbhMWeLMlAc .fx5 { font: 400 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#evbhMWeLMlAc .fx5 {font-style: normal}#evbhMWeLMlAc .fx6 { text-anchor: start; }#evbhMWeLMlAc .fx6 {text-anchor: start}#evbhMWeLMlAc .fx7 { dominant-baseline: alphabetic; }#evbhMWeLMlAc .fx7 {dominant-baseline: alphabetic}#evbhMWeLMlAc .fc1 { fill: rgb(255, 255, 255); }#evbhMWeLMlAc .fc1 {fill: rgb(255, 255, 255)}#evbhMWeLMlAc .fc2 { fill: rgb(51, 51, 51); }#evbhMWeLMlAc .fc2 {fill: rgb(51, 51, 51)}#evbhMWeLMlAc .fb1 { fill: var(--N900-FG, 0.15); }#evbhMWeLMlAc .fb1 {fill: rgba(31,35,41, 0.15)}#evbhMWeLMlAc .fb2 { fill: rgb(225, 228, 232); }#evbhMWeLMlAc .fb2 {fill: rgb(225, 228, 232)}#evbhMWeLMlAc .fa4 { fill: var(--bg-body); }#evbhMWeLMlAc .fa4 {fill: #fff}ABC1234概念定义示例字符单词Token最小的文本单位由空格分隔的文本模型处理的基本单位H, e, l, l, oHello, worldHello, wor, ld

​

Token的粒度介于字符和单词之间。常见单词通常是一个Token,而罕见词或长词会被拆分成多个Token。​

为什么使用Token而非单词​

词汇表大小可控:英语有数十万单词,而Token词汇表通常只有3-5万​

处理未知词:任何文本都能被分解为已知Token的组合​

跨语言支持:同一分词器可以处理多种语言​

子词共享:相关词汇共享子词Token,如"run"、"running"、"runner"​

​

​

Token化过程详解​

Token化(Tokenization)是将原始文本转换为Token序列的过程。​

​

代码块​

Python

import tiktoken​

​

enc = tiktoken.encoding_for_model("gpt-4")​

​

text = "Hello, world! 你好,世界!"​

tokens = enc.encode(text)​

​

print(f"原始文本: {text}")​

print(f"Token数量: {len(tokens)}")​

print(f"Token ID: {tokens}")​

print(f"解码后: {[enc.decode([t]) for t in tokens]}")​

​

输出示例:​

​

代码块​

Plain Text

原始文本: Hello, world! 你好,世界!​

Token数量: 11​

Token ID: [9906, 11, 1917, 0, 220, 57668, 53901, 3922, 244, 98220, 6447]​

解码后: ['Hello', ',', ' world', '!', ' ', '你好', ',', '世', '界', '!']​

​

不同语言的Token效率​

中文和英文的Token效率差异显著:​

​

代码块​

Python

​

一般来说,英文约4个字符对应1个Token,而中文约1.5-2个字符对应1个Token。​

​

​

主流分词算法​

BPE(Byte Pair Encoding)​

BPE是GPT系列模型使用的分词算法,通过迭代合并最频繁的字符对来构建词汇表。​

​

​

​

代码块​

Python

def simple_bpe_demo():​

"""简化的BPE演示"""​

corpus = ["low", "lower", "newest", "widest"]​

​

​

BPE的优点:​

•

平衡了字符级和单词级分词的优缺点​

•

能有效处理未知词​

•

词汇表大小可控​

WordPiece​

WordPiece是BERT使用的分词算法,与BPE类似但使用不同的合并策略。​

​

代码块​

Python

from transformers import BertTokenizer​

​

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')​

​

text = "unbelievable"​

tokens = tokenizer.tokenize(text)​

print(f"WordPiece分词: {tokens}")​

​

WordPiece使用##前缀标记非首字符的子词Token。​

SentencePiece​

SentencePiece是一种语言无关的分词工具,将文本视为Unicode字符序列处理。​

​

代码块​

Python

​

SentencePiece的特点:​

•

不依赖预分词(如空格分割)​

•

支持BPE和Unigram两种算法​

•

广泛用于多语言模型​

​

​

什么是上下文窗口​

上下文窗口(Context Window)是大语言模型一次能处理的最大Token数量。它决定了模型能"看到"多少信息。​

​

​

上下文窗口的组成​

上下文窗口包含所有输入和输出Token:​

系统提示(System Prompt):定义模型行为的指令​

对话历史:之前的对话轮次​

用户输入:当前的问题或请求​

模型输出:模型生成的回复​

为什么上下文窗口很重要​

​

​

​

​

主流模型上下文窗口对比​

​

​

​

​

​

上下文窗口vs实际可用长度​

需要注意的是,标称的上下文窗口大小并不等于实际可用长度:​

​

代码块​

Python

def calculate_available_context(total_window, system_prompt_tokens, ​

history_tokens, max_output_tokens):​

"""计算实际可用的输入Token数"""​

available = total_window - system_prompt_tokens - history_tokens - max_output_tokens​

return max(0, available)​

​

total = 128000​

system = 500​

history = 10000​

​

​

​

长上下文技术​

随着对长上下文需求的增加,研究者开发了多种技术来扩展模型的上下文处理能力。​

RoPE(旋转位置编码)​

RoPE通过旋转矩阵编码位置信息,支持位置外推。​

​

代码块​

Python

​

RoPE的优势:​

•

相对位置信息自然编码​

•

支持长度外推​

•

计算效率高​

ALiBi(Attention with Linear Biases)​

ALiBi通过在注意力分数中添加线性偏置来编码位置信息。​

​

代码块​

Python

def alibi_bias(seq_len, num_heads):​

​

Sliding Window Attention​

滑动窗口注意力限制每个Token只关注固定范围内的Token,降低计算复杂度。​

​

​

​

​

Token计数与成本估算​

准确计算Token数量对于成本控制至关重要。​

使用tiktoken计算Token​

​

代码块​

Python

import tiktoken​

​

def count_tokens(text, model="gpt-4"):​

"""​

​

Token计数工具类​

​

代码块​

Python

class TokenCounter:​

"""Token计数和成本估算工具"""def __init__(self, model="gpt-4"):​

self.model = model​

try:​

self.encoding = tiktoken.encoding_for_model(model)​

except KeyError:​

self.encoding = tiktoken.get_encoding("cl100k_base")​

​

def count(self, text):​

"""计算Token数量"""return len(self.encoding.encode(text))​

​

def count_messages(self, messages):​

"""计算对话消息的Token数量"""​

total = 0for message in messages:​

total += 4for key, value in message.items():​

total += self.count(value)​

if key == "name":​

total += -1​

​

​

​

优化上下文使用的策略​

精简系统提示​

​

代码块​

Python

verbose_prompt = """​

你是一个非常有帮助的AI助手。你的任务是帮助用户解答各种问题。​

你应该始终保持友好、专业的态度。当用户提问时,你需要仔细分析问题,​

然后给出详细、准确的回答。如果你不确定答案,请诚实地告诉用户。​

"""​

​

concise_prompt = """​

你是专业的AI助手。提供准确、简洁的回答。不确定时如实说明。​

​

对话历史管理​

​

代码块​

Python

def manage_conversation_history(messages, max_tokens, counter):​

"""​

管理对话历史,保持在Token限制内​

策略:保留系统消息和最近的对话​

"""​

system_messages = [m for m in messages if m.get("role") == "system"]​

other_messages = [m for m in messages if m.get("role") != "system"]​

​

system_tokens = counter.count_messages(system_messages)​

available_tokens = max_tokens - system_tokens​

​

​

文档分块策略​

​

代码块​

Python

def smart_chunk_document(text, max_chunk_tokens=1000, overlap_tokens=100):​

"""​

智能文档分块:在句子边界处分割​

"""import re​

​

counter = TokenCounter()​

sentences = re.split(r'(?<=[。!?.!?])\s*', text)​

​

使用摘要压缩历史​

​

代码块​

Python

def compress_history_with_summary(messages, summarizer_fn, threshold_tokens=2000):​

"""​

当历史过长时,使用摘要压缩早期对话​

"""​

counter = TokenCounter()​

total_tokens = counter.count_messages(messages)​

​

if total_tokens <= threshold_tokens:​

return messages​

​

system_msgs = [m for m in messages if m["role"] == "system"]​

other_msgs = [m for m in messages if m["role"] != "system"]​

​

split_point = len(other_msgs) // 2​

old_msgs = other_msgs[:split_point]​

recent_msgs = other_msgs[split_point:]​

​

​

​

总结​

理解Token和上下文窗口是高效使用大语言模型的基础:​

Token是LLM的基本单位:不同于字符或单词,Token由分词算法决定​

分词算法各有特点:BPE、WordPiece、SentencePiece适用于不同场景​

上下文窗口限制总Token数:包括输入、输出和对话历史​

长上下文技术不断发展:RoPE、ALiBi等技术扩展了模型能力​

成本优化需要精确计数:使用tiktoken等工具准确估算​

多种策略可优化使用:精简提示、管理历史、智能分块​

掌握这些知识,你就能更好地控制API成本,设计更高效的AI应用。​

​

​

常见问题​

为什么中文消耗的Token比英文多?​

这与分词算法的训练数据有关。GPT等模型主要在英文语料上训练,英文常见词通常是单个Token,而中文字符往往需要多个Token表示。例如,"人工智能"可能需要3-4个Token,而"AI"只需要1个Token。使用针对中文优化的模型(如Qwen)可以提高中文Token效率。​

上下文窗口越大越好吗?​

不一定。更大的上下文窗口意味着:1)更高的API成本(按Token计费);2)更长的响应时间;3)可能的注意力分散(模型可能难以聚焦关键信息)。应根据实际需求选择合适大小的上下文窗口,并使用检索增强生成(RAG)等技术优化信息利用。​

如何估算一段文本的Token数量?​

最准确的方法是使用对应模型的分词器。对于OpenAI模型,使用tiktoken库;对于其他模型,使用相应的tokenizer。粗略估算时,英文约4个字符=1个Token,中文约1.5-2个字符=1个Token。在线工具如OpenAI的Tokenizer也可以快速计算。​

对话历史会消耗上下文窗口吗?​

是的,每轮对话的输入和输出都会累积在上下文中。这就是为什么长对话可能导致早期内容被截断。建议实现对话历史管理策略:保留最近的对话、使用摘要压缩历史、或在适当时候重置上下文。​

不同模型的Token是否通用?​

不通用。不同模型使用不同的分词器,同一文本在不同模型中的Token数量可能不同。例如,GPT-4使用cl100k_base编码,而BERT使用WordPiece。在切换模型时需要重新计算Token数量和成本。​