NLP(五十四)tiktoken的使用
??tiktoken是OpenAI于近期開源的Python第三方模塊,該模塊主要實現(xiàn)了tokenizer的BPE(Byte pair encoding)算法,并對運行性能做了極大的優(yōu)化。本文將介紹tiktoken模塊的使用。
tiktoken簡介
??BPE(Byte pair encoding)算法是NLP中常見的tokenizer方式,關于其介紹和實現(xiàn)原理,讀者可參考深入理解NLP Subword算法:BPE、WordPiece、ULM。
??tiktoken已開源至Github,訪問網(wǎng)址為:https://github.com/openai/tiktoken,tiktoken會比其它開源的tokenizer庫運行快3-6倍,以下是它與hugging face的tokenizer庫的性能比較:
不同線程數(shù)下tiktoken與hugging face的性能比較以上結果是使用GPT-2 tokenizer在1G文本上進行的性能測試,使用的
GPT2TokenizerFast來源于tokenizers==0.13.2, transformers==4.24.0 , tiktoken==0.2.0。簡單使用
??tiktoken的Encodings(編碼方式)用于展示文本是如何被轉化為token的。不同的模型使用不同類型的編碼方式。tiktoken支持如下三種OpenAI模型的編碼方式:
| 編碼方式 | 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 |
可以通過如下代碼來獲取模型的編碼方式:
#?-*-?coding:?utf-8?-*-
import?tiktoken
#?get?encoding?name
print(tiktoken.encoding_for_model('gpt-3.5-turbo'))
輸出結果為:
注意,p50k_base與r50k_base基本類似,在非代碼應用中,它們通常會給出相同的token。
??cl100k_base中的100k代碼該編碼方式中的詞匯表數(shù)量大約為100k,詞匯表文件為cl100k_base_vocab.json,下載網(wǎng)址為:https://raw.githubusercontent.com/weikang-wang/ChatGPT-Vocabulary/main/cl100k_base_vocab.json,詞匯數(shù)量為100256,如此龐大的詞匯數(shù)量使得OpenAI模型在多種語言上都有不俗的表現(xiàn)。
編碼與解碼
??編碼(encode)是指將文本映射為token的數(shù)字列表,解碼(decode)是指將token的數(shù)字列表轉化為文本。參看以下的Python代碼實現(xiàn):
#?-*-?coding:?utf-8?-*-
import?tiktoken
#?simple?test
enc?=?tiktoken.get_encoding("cl100k_base")
print(enc.encode("hello?world")?==?[15339,?1917])
print(enc.decode([15339,?1917])?==?"hello?world")
print(enc.encode("hello?<|endoftext|>",?allowed_special="all")?==?[15339,?220,?100257])
#?encode
tokens?=?enc.encode("tiktoken?is?great!")
print(tokens)
print(len(tokens))
#?decode
print(enc.decode([83,?1609,?5963,?374,?2294,?0]))
#?chinese?encode
tokens?=?enc.encode("大模型是什么?")
print(tokens)
print(len(tokens))
#?chinese?decode
print(enc.decode([27384,?54872,?25287,?21043,?6271,?222,?82696,?11571]))
輸出結果如下:
True
True
True
[83,?1609,?5963,?374,?2294,?0]
6
tiktoken?is?great!
[27384,?54872,?25287,?21043,?6271,?222,?82696,?11571]
8
大模型是什么?
計算token數(shù)量
??OpenAI模型中token數(shù)量較為關鍵,畢竟,OpenAI接口調用的收費方式是按照token數(shù)量來的。關于OpenAI接口調用的收費方式,可以參考網(wǎng)站:https://openai.com/pricing。
??下面是用tiktoken來計算token數(shù)量的Python代碼:
#?-*-?coding:?utf-8?-*-
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
print(num_tokens_from_string('tiktoken?is?great!',?'cl100k_base'))
print(num_tokens_from_string('大模型是什么?',?'cl100k_base'))
輸出結果為:
6
8
??在hugging face網(wǎng)站上,已經(jīng)有人實現(xiàn)了tiktoken的token數(shù)量計算,訪問網(wǎng)站為:https://huggingface.co/spaces/JacobLinCool/tiktoken-calculator ,頁面如下:
tiktoken的token數(shù)量計算??在對話補全(chat completion)場景中計算token數(shù)量,以模型
gpt-3.5-turbo為例,實現(xiàn)Python代碼如下:
#?-*-?coding:?utf-8?-*-
import?tiktoken
import?openai
def?num_tokens_from_messages(messages):
????#?Returns?the?number?of?tokens?used?by?a?list?of?messages.
????encoding?=?tiktoken.encoding_for_model("gpt-3.5-turbo")
????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
????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
example_messages?=?[
????{
????????"role":?"system",
????????"content":?"You?are?a?helpful,?pattern-following?assistant?that?translates?corporate?jargon?into?plain?English.",
????},
????{
????????"role":?"system",
????????"name":?"example_user",
????????"content":?"New?synergies?will?help?drive?top-line?growth.",
????},
????{
????????"role":?"system",
????????"name":?"example_assistant",
????????"content":?"Things?working?well?together?will?increase?revenue.",
????},
????{
????????"role":?"system",
????????"name":?"example_user",
????????"content":?"Let's?circle?back?when?we?have?more?bandwidth?to?touch?base?on?opportunities?for?increased?leverage.",
????},
????{
????????"role":?"system",
????????"name":?"example_assistant",
????????"content":?"Let's?talk?later?when?we're?less?busy?about?how?to?do?better.",
????},
????{
????????"role":?"user",
????????"content":?"This?late?pivot?means?we?don't?have?time?to?boil?the?ocean?for?the?client?deliverable.",
????},
]
#?example?token?count?from?the?function?defined?above
print(f"{num_tokens_from_messages(example_messages)}?prompt?tokens?counted?by?num_tokens_from_messages().")
#?example?token?count?from?the?OpenAI?API
openai.api_key?=?""
response?=?openai.ChatCompletion.create(
????model="gpt-3.5-turbo",
????messages=example_messages,
????temperature=0,
????max_tokens=1
)
print(f'{response["usage"]["prompt_tokens"]}?prompt?tokens?counted?by?the?OpenAI?API.')
輸出結果如下:
127?prompt?tokens?counted?by?num_tokens_from_messages().
127?prompt?tokens?counted?by?the?OpenAI?API.
可見,在num_tokens_from_messages中,對于輸入messages中的每條message,token數(shù)量先加上4,然后對字典中的value值進行token數(shù)量統(tǒng)計,如果此時對應的key為name,則token數(shù)量減1,因為要忽略role字段的token數(shù)量。在模型gpt-3.5-turbo中,num_tokens_from_messages函數(shù)與OpenAI對話補全中的token數(shù)量計算方式是一致的。
總結
??本文介紹了tiktoken模型和它的簡單使用,以及token數(shù)量計算方式。
參考文獻
-
深入理解NLP Subword算法:BPE、WordPiece、ULM: https://zhuanlan.zhihu.com/p/86965595
-
tiktoken的Github網(wǎng)址:https://github.com/openai/tiktoken
-
tiktoken-calculator: https://huggingface.co/spaces/JacobLinCool/tiktoken-calculator
-
How_to_count_tokens_with_tiktoken.ipynb: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
