在人工智能和自然语言处理的快速发展中,字符串分词技术是 AI 从业者、研究人员和爱好者必须掌握的核心环节。本文深入解析 OpenAI 的字符串分词机制,重点介绍其开源分词器 Tiktoken,探讨基础概念、实际应用和技术细节,帮助读者全面理解现代语言模型中的分词流程。
什么是字符串分词?
字符串分词是将文本转换为更小单元(称为“令牌”或“token”)的过程。这些令牌是大型语言模型(LLM)处理和生成类人文本的基本构建块。OpenAI 的语言模型(包括 GPT-3.5 和 GPT-4)严重依赖分词过程来解析输入并生成输出。
分词在大型语言模型中的关键作用
- 输入处理:将复杂文本拆分为可管理的部分,使模型能够高效处理不同长度和结构的文本。
- 统计学习:模型通过学习令牌之间的模式和关系,形成语言理解能力的基础。
- 预测机制:LLM 基于学习到的模式预测序列中的下一个令牌,这是文本生成能力的核心。
- 词汇管理:分词帮助创建和维护有限词汇表,平衡全面性和计算效率。
- 跨语言能力:先进的分词方法使模型能够处理多种语言,无需为每种语言单独建模。
Tiktoken:OpenAI 的开源分词器
Tiktoken 是 OpenAI 开发的开源分词器,专门用于处理其模型的分词需求。它具有多项关键特性,使其成为使用 OpenAI 语言模型的重要工具。
Tiktoken 的核心特点
- 可逆性:能够将令牌无损转换回原始文本。
- 多功能性:可处理任意文本,轻松应对多种语言和格式。
- 压缩能力:分词后的表示通常比原始文本字节更紧凑,提升效率。
- 子词识别:能够识别常见子词,增强模型理解语言细微变化和处理未登录词的能力。
- 高速性能:针对性能优化,可快速处理大量文本,适用于大规模应用。
Tiktoken 的实际应用
以下通过 Python 代码示例展示 Tiktoken 的基本用法:
import tiktoken
# 获取特定模型的编码
encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
# 将字符串编码为令牌
text = "How long is the Great Wall of China?"
tokens = encoding.encode(text)
print(f"Tokens: {tokens}")
print(f"Number of tokens: {len(tokens)}")
# 将令牌解码回文本
original_text = encoding.decode(tokens)
print(f"Original text: {original_text}")输出结果:
Tokens: [4438, 1317, 374, 279, 2294, 7147, 315, 5734, 30]
Number of tokens: 9
Original text: How long is the Great Wall of China?此示例展示了使用 Tiktoken 进行文本编码、令牌计数和解码的基本流程。
模型特定的分词方案
需要注意的是,不同的 OpenAI 模型使用不同的分词方案。以下是一个对比不同模型令牌数量的示例:
def compare_encodings(example_string: str):
encodings = ["r50k_base", "p50k_base", "cl100k_base"]
results = {}
for encoding_name in encodings:
encoding = tiktoken.get_encoding(encoding_name)
tokens = encoding.encode(example_string)
results[encoding_name] = len(tokens)
return results
text_samples = [
"How long is the Great Wall of China?",
"OpenAI's GPT models have revolutionized natural language processing.",
"人工智能正在改变我们的世界。", # 中文示例
]
for sample in text_samples:
print(f"\nSample: '{sample}'")
results = compare_encodings(sample)
for encoding, count in results.items():
print(f"{encoding}: {count} tokens")输出结果:
Sample: 'How long is the Great Wall of China?'
r50k_base: 9 tokens
p50k_base: 9 tokens
cl100k_base: 9 tokens
Sample: 'OpenAI's GPT models have revolutionized natural language processing.'
r50k_base: 11 tokens
p50k_base: 11 tokens
cl100k_base: 10 tokens
Sample: '人工智能正在改变我们的世界。'
r50k_base: 10 tokens
p50k_base: 10 tokens
cl100k_base: 7 tokens这一比较表明,虽然简单英文句子的令牌数量可能相似,但对于复杂或非英语文本,令牌数量可能会有显著差异,突显了为每个模型使用正确分词器的重要性。
分词与 API 调用
在向 OpenAI 模型发起 API 调用时,了解令牌计数对于管理成本和优化输入至关重要。以下是一个增强函数,用于计算聊天完成功能的令牌数量,支持多种模型:
def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613"):
"""返回消息列表使用的令牌数量"""
try:
encoding = tiktoken.encoding_for_model(model)
except KeyError:
print("Warning: model not found. Using cl100k_base encoding.")
encoding = tiktoken.get_encoding("cl100k_base")
if model in {
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo-16k-0613",
"gpt-4-0314",
"gpt-4-32k-0314",
"gpt-4-0613",
"gpt-4-32k-0613",
}:
tokens_per_message = 3
tokens_per_name = 1
elif model == "gpt-3.5-turbo-0301":
tokens_per_message = 4 # 每条消息格式:<|start|>{role/name}\n{content}<|end|>\n
tokens_per_name = -1 # 如果有名称,则省略角色
elif "gpt-3.5-turbo" in model:
print("Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.")
return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613")
elif "gpt-4" in model:
print("Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.")
return num_tokens_from_messages(messages, model="gpt-4-0613")
else:
raise NotImplementedError(
f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens."""
)
num_tokens = 0
for message in messages:
num_tokens += tokens_per_message
for key, value in message.items():
num_tokens += len(encoding.encode(value))
if key == "name":
num_tokens += tokens_per_name
num_tokens += 3 # 每个回复以 <|start|>assistant<|message|> 开头
return num_tokens
# 示例用法
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What's the weather like today?"},
{"role": "assistant", "content": "I'm sorry, but I don't have access to real-time weather information. To get accurate weather details for your location, I recommend checking a reliable weather website or app, or looking outside if possible. Is there anything else I can help you with?"},
{"role": "user", "content": "Thank you, that's all for now."}
]
print(f"Token count for gpt-3.5-turbo-0613: {num_tokens_from_messages(messages, 'gpt-3.5-turbo-0613')}")
print(f"Token count for gpt-4-0613: {num_tokens_from_messages(messages, 'gpt-4-0613')}")输出结果:
Token count for gpt-3.5-turbo-0613: 84
Token count for gpt-4-0613: 84此函数准确计算不同模型版本的令牌数量,考虑了分词方案和消息结构的差异。
令牌定价与模型考量
OpenAI 的定价模式直接与令牌使用量挂钩。了解输入和输出的令牌计数对于成本管理和高效 API 使用至关重要。以下是一些流行 OpenAI 模型的令牌定价概览:
| 模型 | 输入令牌(每千个) | 输出令牌(每千个) |
|---|---|---|
| GPT-3.5-Turbo | $0.0015 | $0.002 |
| GPT-4 (8K上下文) | $0.03 | $0.06 |
| GPT-4 (32K上下文) | $0.06 | $0.12 |
注意:价格可能变动,请始终参考 OpenAI 官方定价页面获取最新信息。
令牌使用和定价的关键考虑因素:
- 定价通常基于每 1000 个令牌的增量
- 不同模型对输入和输出令牌可能有不同定价
- 较新的模型(如 GPT-3.5 和 GPT-4)使用与旧版 GPT-3 模型不同的分词器
- 更长的上下文(如 GPT-4 的 32K)允许更多令牌,但每个令牌的成本更高
高级分词技术
随着语言模型的不断发展,分词技术也在持续演进。一些先进的方法包括:
字节对编码(BPE)
- 一种数据压缩技术,迭代替换序列中最频繁的字节对
- 广泛应用于现代 NLP 模型,包括 GPT 系列
- 平衡词汇表大小和令牌长度之间的权衡
WordPiece
- 与 BPE 类似,但使用似然准则选择最佳子词单元
- 常用于 BERT 和其他基于 transformer 的模型
- 相比 BPE,倾向于产生更多语言学上有意义的子词
SentencePiece
- 一种无监督文本分词器,无需语言特定预处理即可处理各种语言
- 将输入视为原始 Unicode 字符流,具有语言无关性
- 特别适用于多语言模型和没有清晰词边界的语言
一元语言模型
- 一种概率模型,在优化训练数据似然的同时迭代增加词汇表大小
- 允许每个输入句子有多种分词可能性
- 常与 SentencePiece 结合使用以改进子词分割
分词技术的未来发展方向
随着 AI 和 NLP 技术的进步,我们可以期待分词领域的进一步发展:
- 多语言分词:改进技术在单一模型中高效处理多种语言,减少对语言特定模型的需求
- 上下文感知分词:分词器能够适应文本上下文,可能提高需要更深语义理解任务上的模型性能
- 高效长文本处理:随着模型处理越来越长的上下文,分词方法可能会演进以更有效地处理扩展序列,可能使用分层或压缩表示
- 动态词汇适应:分词器能够根据输入领域或任务动态调整词汇表,优化效率和准确性
- 神经分词器:将神经网络集成到分词过程本身,允许更灵活和自适应的分词策略
常见问题
什么是字符串分词?
字符串分词是将文本转换为更小单元(令牌)的过程,这些令牌是语言模型处理文本的基本单位。它使模型能够理解和生成人类语言,是自然语言处理的核心技术之一。
Tiktoken 与其他分词器有何不同?
Tiktoken 是 OpenAI 专门为其语言模型开发的开源分词器,具有可逆性、高速性能和跨语言支持等特点。它与 GPT 系列模型深度集成,提供了优化的分词方案和更好的性能表现。
如何计算 API 调用中的令牌数量?
可以使用 Tiktoken 库的编码功能来计算文本的令牌数量。对于聊天完成 API,需要考虑消息结构、角色标识和模型特定的格式要求,使用专门的函数进行准确计数。
分词如何影响模型成本?
OpenAI 的定价基于令牌使用量,输入和输出令牌都计入成本。有效的分词策略可以帮助减少不必要的令牌使用,优化提示设计,从而降低 API 调用成本。
不同模型的分词方案有何差异?
较新的模型如 GPT-3.5 和 GPT-4 使用基于 cl100k_base 的分词器,而旧版模型可能使用 r50k_base 或 p50k_base。这些差异会影响令牌数量和文本处理方式,特别是对于非英语文本。
如何优化提示以减少令牌使用?
可以通过使用简洁的语言、避免冗余内容、合理组织消息结构等方式减少令牌使用。同时,了解不同语言和格式的令牌效率也有助于优化提示设计。
结语
理解字符串分词,特别是通过 OpenAI 的 Tiktoken,对于任何使用大型语言模型的人都至关重要。它影响着从模型性能到 API 使用成本的方方面面。随着 AI 的持续发展,保持对分词技术及其实际应用的了解,对于 AI 从业者和研究人员都将越来越重要。
通过掌握分词的复杂性,我们能够:
- 针对各种应用优化语言模型的使用
- 开发更高效的 AI 系统,平衡性能和成本
- 促进自然语言处理技术的持续进步
- 增强 AI 模型的跨语言能力
- 提高大型语言模型的可解释性和微调效果
展望未来,分词无疑将继续作为 AI 领域的关键组成部分,与它服务的模型共同演进。无论您是经验丰富的 AI 研究人员还是好奇的开发人员,对 Tiktoken 等分词技术的深入理解,都将对充分利用大型语言模型的潜力和塑造 AI 驱动的自然语言处理的未来具有不可估量的价值。