简体中文
O Openai do Tiktoken em Go.
Tiktoken é um tokeniser BPE rápido para uso com os modelos do Openai.
Este é um porto do Tiktoken original.
go get github.com/pkoukk/tiktoken-goTiktoken-Go tem o mesmo mecanismo de cache que a biblioteca original de Tiktoken.
Você pode definir o diretório de cache usando a variável de ambiente tiktoken_cache_dir.
Depois que essa variável estiver definida, o TikToken-Go usará este diretório para armazenar em cache o dicionário de token.
Se você não definir essa variável de ambiente, o TikToken-Go baixará o dicionário cada vez que você inicializará uma codificação pela primeira vez.
Se você não quiser usar o cache ou baixar o dicionário a cada vez, pode usar o Loader Alternativo BPE.
Basta ligar tiktoken.SetBpeLoader antes de ligar para tiktoken.GetEncoding ou tiktoken.EncodingForModel .
BpeLoader é uma interface, você pode implementar seu próprio carregador BPE implementando essa interface.
O carregador BPE offline carrega o dicionário BPE de arquivos incorporados, ajuda se você não deseja baixar o dicionário em tempo de execução.
Devido ao tamanho do dicionário BPE, esse carregador está em outro projeto.
Inclua se você precisar deste carregador: 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 ))
}Abaixo está uma função de exemplo para contar tokens para mensagens passadas para GPT-3.5-turbo ou GPT-4.
O código a seguir foi escrito com base nos exemplos de Openai-Cookbook na Wednesday, 28 June 2023 .
Observe que o método de cálculo do token para a mensagem pode alterar a qualquer momento; portanto, esse código pode não ser necessariamente aplicável no futuro.
Se você precisar de cálculo preciso, consulte a documentação oficial.
Se você achar que este código não é mais aplicável, sinta -se à vontade para enviar um PR ou emissão.
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
}| Nome da codificação | Modelos 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 | Modelos Codex, text-davinci-002 , text-davinci-003 |
r50k_base (ou gpt2 ) | Modelos GPT-3 como davinci |
| Nome do modelo | Modelos 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 |
| Curie-textie-001 | r50k_base |
| Text-Babbage-001 | r50k_base |
| Text-Ada-001 | r50k_base |
| DaVinci | r50k_base |
| Curie | r50k_base |
| Babbage | r50k_base |
| Ada | r50k_base |
| Code-Davinci-002 | p50k_base |
| Code-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 |
| Encadeamento de texto-Ada-002 | CL100K_BASE |
| Text-embebedding-3-small | CL100K_BASE |
| Text-3-Large | CL100K_BASE |
| TEXT-MIMILARIDADE-DAVINCI-001 | r50k_base |
| TEXT-MIMilaridade-Curie-001 | r50k_base |
| TEXT-MIMilaridade-Babbage-001 | r50k_base |
| TEXT-MIMilaridade-Ada-001 | r50k_base |
| Texto-pesquisa-davinci-doc-001 | r50k_base |
| Texto-pesquisa-curie-Doc-001 | r50k_base |
| Texto-pesquisa-Babbage-Doc-001 | r50k_base |
| Texto-pesquisa-Ada-Doc-001 | r50k_base |
| Código-pesquisa-Babbage-Code-001 | r50k_base |
| Code-search-ADA-Code-001 | r50k_base |
| GPT2 | GPT2 |
Você pode executar o teste na pasta de teste
resultado
resultado
você pode executar benchmark na pasta de teste
| nome | tempo/op | OS | CPU | texto | vezes |
|---|---|---|---|---|---|
| Tiktoken-go | 8795ns | MacOS 13.2 | Apple M1 | Udhr | 100000 |
| Tiktoken | 8838ns | MacOS 13.2 | Apple M1 | Udhr | 100000 |
Parece que o desempenho é quase o mesmo.
Talvez a diferença se deva à diferença no desempenho da máquina.
Ou talvez meu método de referência não seja apropriado.
Se você tiver melhor método de referência ou se deseja adicionar seu resultado de referência, sinta -se à vontade para enviar um PR.
Para a nova codificação o200k_base , parece mais lenta que cl100k_base . O Tiktoken-Go é um pouco mais lento que o Tiktoken na referência a seguir.
| nome | codificação | tempo/op | OS | CPU | texto | vezes |
|---|---|---|---|---|---|---|
| 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 |
Mit