最簡單的 token 計算,當然是之前介紹的 Tokenizer。
把你想計算的文字,直接複製貼上,網頁就告訴你結果。
不過,實際應用上,當然還是呼叫程式計算。
OpenAi 官方教學
官方教學有一些額外資訊,感興趣的朋友請參考(Jupyter Notebook 格式):
How to count tokens with tiktoken?
tiktoken
為了避免看到帳單時嚇一跳,用程式預先計算,將花費控制在可接受的範圍。
BPE (Byte Pair Encoding)
tiktoken 使用 BPE 演算法。
-
1994年,首先公開發表於 Philip Gage 的 C Users Journal 著作。
-
2015年,開始被應用在 natural language processing (NLP) 中的 tokenization。
BPN 演算法,主要是把重覆出現的字串,用另新的字串代替,依此類推。例如:
-
原始字串
aaabdaaabac
-
第一次壓縮 Z = aa
aaabdaaabac 會成為ZabdZabac
Z=aa -
第二次壓縮 Y=ab
ZabdZabac 會成為ZYdZYac
Y=ab
Z=aa -
第三次壓縮 X=ZY
ZYdZYac 會成為XdXac
X=ZY
Y=ab
Z=aa
到無法再壓縮時,就算壓縮完成。
要解壓時,把上述程式倒過來即可。
我們看看 OpenAI 在 github 中,如何描述 BPE:
-
可逆且無損壓縮,因此可以將標記轉換回原始文件。
-
適用於任意文件,甚至是不在標記器訓練數據中的文件。
-
壓縮文件:令牌序列(token sequence)比原始文件短。實際上,每個令牌(token)平均對應大約 4 個 bytes。
-
它試圖讓模型看到常見的子詞(subwords)。
例如,“ing"是英語中的常見子詞,因此 BPE 編碼通常會將"encoding"拆分為"encod"和"ing"等標記(而不是"enc"和"oding”)。
因為模型隨後會在不同的上下文中一次又一次地看到"ing"標記,所以它有助於模型概括和更好地理解語法。
編碼方式
tiktoken 有三種編碼方式,不同 model 對應的 encoding 如下表:
Encoding name | OpenAI models |
---|---|
cl100k_base |
gpt-4 , gpt-3.5-turbo , text-embedding-ada-002 |
p50k_base |
Codex models, text-davinci-002 , text-davinci-003 |
r50k_base (or gpt2 ) |
GPT-3 models like davinci |
GPT-4 和 GPT-3.X 的比較,這篇這的蠻詳細:
實際應用
就是把 OpenAI 的 num_tokens_from_messages
直接拿來用即可。
以下計算 token 函式來自 OpenAI github - How to count tokens with tiktoken
更新日期:2023年5月6日
def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301"):
"""Returns the number of tokens used by a list of messages."""
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 == "gpt-3.5-turbo":
print("Warning: gpt-3.5-turbo may change over time. Returning num tokens assuming gpt-3.5-turbo-0301.")
return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301")
elif model == "gpt-4":
print("Warning: gpt-4 may change over time. Returning num tokens assuming gpt-4-0314.")
return num_tokens_from_messages(messages, model="gpt-4-0314")
elif model == "gpt-3.5-turbo-0301":
tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n
tokens_per_name = -1 # if there's a name, the role is omitted
elif model == "gpt-4-0314":
tokens_per_message = 3
tokens_per_name = 1
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 # every reply is primed with <|start|>assistant<|message|>
return num_tokens
不過我們實際使用時,不需要(也不應該)自己把上面這段 code 複製到自己的程式中,因為 OpenAI 可能會不定期版本更新。使用的方法如下:
import tiktoken
def num_tokens_from_string(string: str, encoding_name: str) -> int:
"""Returns the number of tokens in a text string."""
encoding = tiktoken.get_encoding(encoding_name)
num_tokens = len(encoding.encode(string))
return num_tokens
num_tokens_from_string("tiktoken is great!", "cl100k_base")
以上示範程式來自 OpenAI 官網 - How can I tell how many tokens a string has before I embed it?
補充:你可以從 前面表格(tiktoken 的編碼方式) 中左側的「Encoding name」或右側的「OpenAI models」選擇編碼方式:
encoding = tiktoken.get_encoding(“cl100k_base”)
encoding = tiktoken.encoding_for_model(“gpt-4”)
延伸閱讀
- 找資料的過程中,看到一段說明,提及 tiktoken 的
_educational
能提供更視覺化的演算法理解。原文找不到了,這裡是 github 中的程式碼:
- 關於 Token Count,這裡有另一堂共學課程的參考: 1️⃣ Section 10. 文字嵌入(Text Embedding)