你是否曾经想知道一个文本字符串包含多少个标记?标记在GPT模型中是很重要的,因为它们决定了文本的长度和模型处理的成本。本教程将向你介绍如何使用OpenAI的开源工具tiktoken来轻松计算文本中的标记数。
引子
在开始之前,让我们来谈谈为什么需要计算标记数。标记是文本的最小单位,可以是一个字符,也可以是一个单词。GPT模型处理文本时以标记为基本单位,因此知道一个文本字符串包含多少标记对于以下两个方面非常重要:
-
文本长度限制:有时,你可能需要将文本输入到一个模型中,但模型对文本长度有限制。如果你的文本超过了模型的最大标记数限制,你需要截断或缩短它,以确保模型可以正确处理。
-
计算成本:使用OpenAI的API调用GPT模型是需要付费的,而费用是按照标记数计算的。因此,了解文本中有多少标记可以帮助你估算API调用的成本。
使用不同的编码
在使用tiktoken之前,你需要了解文本是如何被转换成标记的。不同的模型使用不同的编码方式。tiktoken支持三种OpenAI模型使用的编码:
cl100k_base
:用于gpt-4、gpt-3.5-turbo、text-embedding-ada-002等模型。p50k_base
:用于Codex模型、text-davinci-002、text-davinci-003等模型。r50k_base
(或称为gpt2):用于GPT-3模型,如davinci。
你可以使用以下方式获取特定模型的编码:
import tiktoken
# 获取gpt-3.5-turbo模型的编码
encoding = tiktoken.encoding_for_model('gpt-3.5-turbo')
请注意,p50k_base
与r50k_base
在非代码应用中有很大的重叠,在这种情况下,它们通常会产生相同的标记。
使用tiktoken计算标记数
现在,让我们看看如何使用tiktoken计算文本中的标记数。首先,你需要安装tiktoken库:
pip install --upgrade tiktoken
安装完成后,你可以按照以下方式计算标记数:
import tiktoken
def num_tokens_from_string(string: str, encoding_name: str) -> int:
"""返回文本字符串中的标记数。"""
encoding = tiktoken.get_encoding(encoding_name)
num_tokens = len(encoding.encode(string))
return num_tokens
# 示例:计算标记数
text = "tiktoken is great!"
encoding_name = "cl100k_base"
num_tokens = num_tokens_from_string(text, encoding_name)
print(f"文本中的标记数:{num_tokens}")
上述代码将输出文本中的标记数。在这个示例中,文本 "tiktoken is great!" 有6个标记。
将标记转换为文本
如果你想将标记转换回文本,你可以使用以下方法:
import tiktoken
def tokens_to_text(tokens, encoding_name: str) -> str:
"""将标记列表转换为文本字符串。"""
encoding = tiktoken.get_encoding(encoding_name)
text = encoding.decode(tokens)
return text
# 示例:将标记转换为文本
tokens = [83, 1609, 5963, 374, 2294, 0]
encoding_name = "cl100k_base"
text = tokens_to_text(tokens, encoding_name)
print(f"标记转换为文本:{text}")
在上面的示例中,标记列表 [83, 1609, 5963, 374, 2294, 0]
被转换回了文本 "tiktoken is great!"。
比较不同的编码
不同的编码方式可能在如何分割单词、处理空格以及处理非英文字符方面有所不同。使用上述方法,我们可以比较不同编码在几个示例文本上的表现:
import tiktoken
def compare_encodings(example_string: str) -> None:
"""比较三种字符串编码的表现。"""
# 打印示例字符串
print(f'\n示例字符串: "{example_string}"')
# 对于每种编码,打印标记数、标记整数和标记字节
for encoding_name in ["r50k_base", "p50k_base", "cl100k_base"]:
encoding = tiktoken.get_encoding(encoding_name)
token_integers = encoding.encode(example_string)
num_tokens = len(token_integers)
token_bytes = [encoding.decode_single_token_bytes(token) for token in token_integers]
print()
print(f"{encoding_name}: {num_tokens} 个标记")
print(f"标记整数: {token_integers}")
print(f"标记字节: {token_bytes}")
# 示例:比较编码
compare_encodings("antidisestablishmentarianism")
compare_encodings("2 + 2 = 4")
compare_encodings("お誕生日おめでとう")
通过上述代码,你可以比较不同编码在示例文本上的表现。这将有助于你选择最适合你的应用程序的编码方式。
在聊天完成API调用中计算标记数
对于ChatGPT模型,如gpt-3.5-turbo和gpt-4,它们使用的标记方式与旧的完成模型相同,但由于它们的消息格式,更难计算会话中将使用多少标记。
以下是一个用于计算传递给gpt-3.5-turbo或gpt-
4的消息中标记数的示例Python代码:
import tiktoken
def num_tokens_in_chat(messages: list, encoding_name: str) -> int:
"""计算聊天消息中的标记数。"""
encoding = tiktoken.get_encoding(encoding_name)
total_tokens = 0
for message in messages:
role = message["role"]
content = message["content"]
if role == "system":
# 系统消息不包含标记
continue
elif role == "user" or role == "assistant":
# 用户和助手消息包含标记
tokens = encoding.encode(content)
total_tokens += len(tokens)
return total_tokens
# 示例:计算聊天消息中的标记数
chat_messages = [
{"role": "user", "content": "tell me a joke"},
{"role": "assistant", "content": "why did the chicken cross the road"},
{"role": "user", "content": "I don't know, why did the chicken cross the road"},
]
encoding_name = "cl100k_base"
num_tokens = num_tokens_in_chat(chat_messages, encoding_name)
print(f"聊天消息中的标记数:{num_tokens}")
在上面的示例中,我们计算了一个包含用户和助手消息的聊天中的标记数。你可以根据自己的聊天数据和所选的编码来计算标记数。
这就是如何使用tiktoken计算文本中的标记数,无论是用于一般文本处理还是用于聊天API调用,这个工具都可以帮助你更好地管理标记。希望这个教程对你有所帮助!如果你有任何问题或需要进一步的协助,请随时提问。