簡體中文
Openai的Tiktoken Go。
Tiktoken是一個快速的BPE令牌,可與OpenAI的型號一起使用。
這是原始tiktoken的港口。
go get github.com/pkoukk/tiktoken-goTiktoken-Go具有與原始Tiktoken庫相同的緩存機制。
您可以使用環境變量tiktoken_cache_dir設置緩存目錄。
設置此變量後,Tiktoken-go將使用此目錄來緩存令牌字典。
如果您不設置此環境變量,則每次首次初始化編碼時,Tiktoken-go都會下載字典。
如果您不想每次使用緩存或下載字典,則可以使用替代BPE加載程序。
只需致電tiktoken.SetBpeLoader然後致電tiktoken.GetEncoding或tiktoken.EncodingForModel 。
BpeLoader是一個接口,您可以通過實現此接口來實現自己的BPE加載程序。
離線BPE加載程序從嵌入文件加載BPE字典,如果您不想在運行時下載字典會有所幫助。
由於BPE詞典的大小,該裝載機在其他項目中。
如果您需要此加載程序:tiktoken_loader
package main
import (
"fmt"
"github.com/pkoukk/tiktoken-go"
)
func main () {
text := "Hello, world!"
encoding := "cl100k_base"
// if you don't want download dictionary at runtime, you can use offline loader
// tiktoken.SetBpeLoader(tiktoken_loader.NewOfflineLoader())
tke , err := tiktoken . GetEncoding ( encoding )
if err != nil {
err = fmt . Errorf ( "getEncoding: %v" , err )
return
}
// encode
token := tke . Encode ( text , nil , nil )
//tokens
fmt . Println (( token ))
// num_tokens
fmt . Println ( len ( token ))
} package main
import (
"fmt"
"github.com/pkoukk/tiktoken-go"
)
func main () {
text := "Hello, world!"
encoding := "gpt-3.5-turbo"
tkm , err := tiktoken . EncodingForModel ( encoding )
if err != nil {
err = fmt . Errorf ( "getEncoding: %v" , err )
return
}
// encode
token := tkm . Encode ( text , nil , nil )
// tokens
fmt . Println ( token )
// num_tokens
fmt . Println ( len ( token ))
}以下是用於計算傳遞給GPT-3.5-Turbo或GPT-4的消息的示例函數。
以下代碼是根據Wednesday, 28 June 2023 Openai-Cook Books示例編寫的。
請注意,該消息的令牌計算方法可能隨時更改,因此此代碼不一定在將來適用。
如果您需要準確的計算,請參閱官方文檔。
如果您發現此代碼不再適用,請隨時提交PR或問題。
package main
import (
"fmt"
"github.com/pkoukk/tiktoken-go"
"github.com/sashabaranov/go-openai"
)
// OpenAI Cookbook: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
func NumTokensFromMessages ( messages []openai. ChatCompletionMessage , model string ) ( numTokens int ) {
tkm , err := tiktoken . EncodingForModel ( model )
if err != nil {
err = fmt . Errorf ( "encoding for model: %v" , err )
log . Println ( err )
return
}
var tokensPerMessage , tokensPerName int
switch model {
case "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" :
tokensPerMessage = 3
tokensPerName = 1
case "gpt-3.5-turbo-0301" :
tokensPerMessage = 4 // every message follows <|start|>{role/name}n{content}<|end|>n
tokensPerName = - 1 // if there's a name, the role is omitted
default :
if strings . Contains ( model , "gpt-3.5-turbo" ) {
log . Println ( "warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613." )
return NumTokensFromMessages ( messages , "gpt-3.5-turbo-0613" )
} else if strings . Contains ( model , "gpt-4" ) {
log . Println ( "warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613." )
return NumTokensFromMessages ( messages , "gpt-4-0613" )
} else {
err = fmt . Errorf ( "num_tokens_from_messages() is not implemented for model %s. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens." , model )
log . Println ( err )
return
}
}
for _ , message := range messages {
numTokens += tokensPerMessage
numTokens += len ( tkm . Encode ( message . Content , nil , nil ))
numTokens += len ( tkm . Encode ( message . Role , nil , nil ))
numTokens += len ( tkm . Encode ( message . Name , nil , nil ))
if message . Name != "" {
numTokens += tokensPerName
}
}
numTokens += 3 // every reply is primed with <|start|>assistant<|message|>
return numTokens
}| 編碼名稱 | Openai型號 |
|---|---|
o200k_base | gpt-4o |
cl100k_base | gpt-4 , gpt-3.5-turbo , text-embedding-ada-002 , text-embedding-3-small , text-embedding-3-large |
p50k_base | codex型號, text-davinci-002 , text-davinci-003 |
r50k_base (或gpt2 ) | 像davinci這樣的GPT-3車型 |
| 模型名稱 | Openai型號 |
|---|---|
| GPT-4O-* | O200K_BASE |
| GPT-4-* | cl100k_base |
| gpt-3.5-turbo-* | cl100k_base |
| GPT-4O | O200K_BASE |
| GPT-4 | cl100k_base |
| GPT-3.5-Turbo | cl100k_base |
| text-davinci-003 | p50k_base |
| text-davinci-002 | p50k_base |
| text-davinci-001 | r50k_base |
| Text-Curie-001 | r50k_base |
| 文字bbbage-001 | r50k_base |
| Text-ADA-001 | r50k_base |
| 達文西 | r50k_base |
| 居里 | r50k_base |
| 巴巴奇 | r50k_base |
| 艾達 | r50k_base |
| 代碼davinci-002 | p50k_base |
| 代碼davinci-001 | p50k_base |
| Code-Cushman-002 | p50k_base |
| Code-Cushman-001 | p50k_base |
| Davinci-Codex | p50k_base |
| Cushman-Codex | p50k_base |
| text-davinci-edit-001 | p50k_edit |
| Code-Davinci-edit-001 | p50k_edit |
| 文本插入-ADA-002 | cl100k_base |
| text-embedding-3-small | cl100k_base |
| 文本插入3大 | cl100k_base |
| 文本相似性davinci-001 | r50k_base |
| 文本相似性-Curie-001 | r50k_base |
| 文本相似性babbage-001 | r50k_base |
| 文本相似性-ADA-001 | r50k_base |
| Text-Search-Search-Davinci-Doc-001 | r50k_base |
| 文本搜索-CURIE-DOC-001 | r50k_base |
| 文本搜索 - 寶貝-DOC-001 | r50k_base |
| Text-Search-SADA-DOC-001 | r50k_base |
| 代碼搜索寶貝代碼-001 | r50k_base |
| 代碼搜索-ADA-CODE-001 | r50k_base |
| GPT2 | GPT2 |
您可以在測試文件夾中運行測試
結果
結果
您可以在測試文件夾中運行基準測試
| 姓名 | 時間/OP | 作業系統 | 中央處理器 | 文字 | 時代 |
|---|---|---|---|---|---|
| tiktoken-go | 8795ns | MacOS 13.2 | 蘋果M1 | Udhr | 100000 |
| tiktoken | 8838ns | MacOS 13.2 | 蘋果M1 | Udhr | 100000 |
看起來表演幾乎是相同的。
也許區別是由於機器性能的差異。
也許我的基準方法不合適。
如果您有更好的基準方法或要添加基準結果,請隨時提交PR。
對於新的o200k_base編碼,它似乎比cl100k_base慢。 Tiktoken-Go在以下基準測試中的速度比Tiktoken稍慢。
| 姓名 | 編碼 | 時間/OP | 作業系統 | 中央處理器 | 文字 | 時代 |
|---|---|---|---|---|---|---|
| tiktoken-go | O200K_BASE | 108522 ns | Ubuntu 22.04 | AMD Ryzen 9 5900HS | Udhr | 100000 |
| tiktoken | O200K_BASE | 70198 ns | Ubuntu 22.04 | AMD Ryzen 9 5900HS | Udhr | 100000 |
| tiktoken-go | cl100k_base | 94502 ns | Ubuntu 22.04 | AMD Ryzen 9 5900HS | Udhr | 100000 |
| tiktoken | cl100k_base | 54642 ns | Ubuntu 22.04 | AMD Ryzen 9 5900HS | Udhr | 100000 |
麻省理工學院