简体中文
Tiktoken de OpenAi en Go.
Tiktoken es un tokenizador BPE rápido para su uso con los modelos de OpenAi.
Este es un puerto del Tiktoken original.
go get github.com/pkoukk/tiktoken-goTiktoken-go tiene el mismo mecanismo de caché que la Biblioteca Tiktoken original.
Puede establecer el directorio de caché utilizando la variable de entorno TIKToken_cache_DIR.
Una vez que se establezca esta variable, Tiktoken-go usará este directorio para almacenar en caché el diccionario de token.
Si no establece esta variable de entorno, Tiktoken-go descargará el diccionario cada vez que inicialice una codificación por primera vez.
Si no desea usar caché o descargar el diccionario cada vez, puede usar el cargador BPE alternativo.
Simplemente llame tiktoken.SetBpeLoader antes de llamar tiktoken.GetEncoding o tiktoken.EncodingForModel .
BpeLoader es una interfaz, puede implementar su propio cargador BPE implementando esta interfaz.
El cargador BPE fuera de línea carga el diccionario BPE de los archivos de incrustación, ayuda si no desea descargar el diccionario en tiempo de ejecución.
Debido al tamaño del diccionario BPE, este cargador está en otro proyecto.
Incluya si necesita este cargador: 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 ))
}A continuación se muestra una función de ejemplo para contar tokens para los mensajes pasados a GPT-3.5-TURBO o GPT-4.
El siguiente código fue escrito en base a ejemplos de Openai-Cookbook el Wednesday, 28 June 2023 .
Tenga en cuenta que el método de cálculo del token para el mensaje puede cambiar en cualquier momento, por lo que este código no necesariamente será aplicable en el futuro.
Si necesita un cálculo preciso, consulte la documentación oficial.
Si encuentra que este código ya no es aplicable, no dude en enviar un PR o un problema.
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
}| Nombre de codificación | 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 (o gpt2 ) | Modelos GPT-3 como davinci |
| Nombre del 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 |
| texto-Davinci-003 | P50K_BASE |
| texto-Davinci-002 | P50K_BASE |
| texto-Davinci-001 | r50k_base |
| Texto curie-001 | r50k_base |
| texto-babbage-001 | r50k_base |
| texto-ADA-001 | r50k_base |
| davinci | r50k_base |
| curie | r50k_base |
| babbage | r50k_base |
| ADA | r50k_base |
| código-Davinci-002 | P50K_BASE |
| código-Davinci-001 | P50K_BASE |
| código-cushman-002 | P50K_BASE |
| Code-Cushman-001 | P50K_BASE |
| davinci-code | P50K_BASE |
| Cushman-Codex | P50K_BASE |
| texto-Davinci-edit-001 | P50K_Edit |
| Code-Davinci Edit-001 | P50K_Edit |
| Texto incrustado-ADA-002 | CL100K_BASE |
| Texto incrustado-3-Small | CL100K_BASE |
| texto incrustado-3-larga | CL100K_BASE |
| texto-similitud-Davinci-001 | r50k_base |
| texto-similitud-curie-001 | r50k_base |
| texto-similitud-babbage-001 | r50k_base |
| TEXT-SIMILIDAD-ADA-001 | r50k_base |
| Text Search-Davinci-Doc-001 | r50k_base |
| Text-Search-curie-DOC-001 | r50k_base |
| Text Search-Babbage-Doc-001 | r50k_base |
| Text-Search-AAD-DOC-001 | r50k_base |
| Código de búsqueda-babbage-código-001 | r50k_base |
| Código-Search-ADA-Code-001 | r50k_base |
| GPT2 | GPT2 |
Puede ejecutar la prueba de prueba en la carpeta de prueba
resultado
resultado
Puede ejecutar Benchmark en la carpeta de prueba
| nombre | Tiempo/OP | sistema operativo | UPC | texto | veces |
|---|---|---|---|---|---|
| tiktoken-go | 8795ns | MacOS 13.2 | Apple M1 | Udhr | 100000 |
| tiktoken | 8838ns | MacOS 13.2 | Apple M1 | Udhr | 100000 |
Parece que el rendimiento es casi el mismo.
Tal vez la diferencia se deba a la diferencia en el rendimiento de la máquina.
O tal vez mi método de referencia no es apropiado.
Si tiene un mejor método de referencia o si desea agregar su resultado de referencia, no dude en enviar un PR.
Para una nueva codificación o200k_base , parece más lento que cl100k_base . Tiktoken-go es un poco más lento que Tiktoken en el siguiente punto de referencia.
| nombre | codificación | Tiempo/OP | sistema operativo | UPC | texto | veces |
|---|---|---|---|---|---|---|
| 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