
Sharptoken adalah perpustakaan C# yang berfungsi sebagai port dari Perpustakaan Python Tiktoken. Ini menyediakan fungsionalitas untuk pengkodean dan decoding token menggunakan pengkodean berbasis GPT. Perpustakaan ini dibangun untuk .NET 6, .NET 8 dan .NET Standar 2.0, membuatnya kompatibel dengan berbagai kerangka kerja.
Penting
Fungsionalitas di SharpToken telah ditambahkan ke Microsoft.ML.Tokenizers . Microsoft.ML.Tokenizers adalah perpustakaan tokenizer yang dikembangkan oleh tim .net dan ke depan, tempat utama untuk pengembangan tokenizer di .net. Dengan menggunakan Microsoft.ML.Tokenizers , Anda akan melihat peningkatan kinerja dibandingkan implementasi perpustakaan tokenizer yang ada, termasuk SharpToken . Rilis Microsoft.ML.Tokenizers yang stabil diharapkan bersama rilis .NET 9.0 (November 2024). Instruksi untuk migrasi dapat ditemukan di https://github.com/dotnet/machinelearning/blob/main/docs/code/microsoft-token-tokenizers-migration-guide.md.
Untuk menginstal Sharptoken, gunakan Nuget Package Manager:
Install-Package SharpTokenAtau, jika Anda lebih suka menggunakan .NET CLI:
dotnet add package SharpTokenUntuk informasi lebih lanjut, kunjungi halaman Paket Nuget.
Untuk menggunakan Sharptoken dalam proyek Anda, pertama impor perpustakaan:
using SharpToken ;Selanjutnya, buat instance gtEncoding dengan menentukan pengkodean atau model yang diinginkan:
// Get encoding by encoding name
var encoding = GptEncoding . GetEncoding ( " cl100k_base " ) ;
// Get encoding by model name
var encoding = GptEncoding . GetEncodingForModel ( " gpt-4 " ) ;Anda kemudian dapat menggunakan metode Encode untuk menyandikan string:
var encoded = encoding . Encode ( " Hello, world! " ) ; // Output: [9906, 11, 1917, 0]Dan gunakan metode decode untuk memecahkan kode token yang dikodekan:
var decoded = encoding . Decode ( encoded ) ; // Output: "Hello, world!"Sharptoken juga menyediakan metode penghitungan kinerja tinggi. Adalah berguna untuk memeriksa ukuran cepat sebelum mengirimkannya ke LLM atau menggunakannya di TextSplitter/Chunker untuk Rag.
var count = encoding . CountTokens ( " Hello, world! " ) ; // Output: 4 Sharptoken saat ini mendukung model -model berikut:
r50k_basep50k_basep50k_editcl100k_baseo200k_baseAnda dapat menggunakan salah satu model ini saat membuat instance gptEncoding:
var r50kBaseEncoding = GptEncoding . GetEncoding ( " r50k_base " ) ;
var p50kBaseEncoding = GptEncoding . GetEncoding ( " p50k_base " ) ;
var p50kEditEncoding = GptEncoding . GetEncoding ( " p50k_edit " ) ;
var cl100kBaseEncoding = GptEncoding . GetEncoding ( " cl100k_base " ) ;
var o200kBaseEncoding = GptEncoding . GetEncoding ( " o200k_base " ) ;Selain menentukan nama model langsung, Sharptoken juga menyediakan fungsionalitas untuk memetakan nama model berdasarkan awalan tertentu. Ini memungkinkan pengguna untuk mengambil pengkodean berdasarkan awalan model.
Berikut adalah awalan yang didukung saat ini dan penyandiannya yang sesuai:
| Awalan model | Pengkodean |
|---|---|
gpt-4o | o200k_base |
gpt-4- | cl100k_base |
gpt-3.5-turbo- | cl100k_base |
gpt-35-turbo | cl100k_base |
Contoh nama model yang termasuk dalam awalan ini meliputi:
gpt-4o : gpt-4o , gpt-4o-2024-05-13 , dll.gpt-4- : gpt-4-0314 , gpt-4-32k , dll.gpt-3.5-turbo- : gpt-3.5-turbo-0301 , gpt-3.5-turbo-0401 , dll.gpt-35-turbo . Untuk mengambil nama pengkodean berdasarkan nama model atau awalannya, Anda dapat menggunakan metode GetEncodingNameForModel :
string encodingName = Model . GetEncodingNameForModel ( " gpt-4-0314 " ) ; // This will return "cl100k_base" Jika nama model yang disediakan tidak cocok dengan nama atau awalan model langsung, metode ini akan mengembalikan null .
Saat Anda mengkode string menggunakan metode Encode, nilai yang dikembalikan adalah daftar bilangan bulat yang mewakili token dalam pengkodean yang ditentukan. Token ini adalah cara kompak untuk mewakili teks input dan dapat diproses lebih efisien dengan berbagai algoritma.
Misalnya, menyandikan teks "Hello World!" Menggunakan pengkodean CL100K_BASE dapat menghasilkan daftar bilangan bulat berikut:
var encoded = cl100kBaseEncoding . Encode ( " Hello world! " ) ; // Output: [9906, 1917, 0] Anda kemudian dapat menggunakan metode Decode untuk mengonversi nilai integer tokenisasi ini kembali ke teks asli:
var decoded = cl100kBaseEncoding . Decode ( encoded ) ; // Output: "Hello world!" Dengan Sharptoken, Anda dapat beralih dengan mulus antara berbagai penyandian untuk menemukan yang paling sesuai dengan kebutuhan Anda. Ingatlah untuk menggunakan pengkodean yang sama untuk metode Encode dan Decode untuk memastikan hasil yang akurat.
Sharptoken memungkinkan Anda untuk menentukan set khusus token khusus yang diizinkan saat mengkode teks. Untuk melakukan ini, lulus hashset yang berisi token khusus yang diizinkan sebagai parameter dari metode Encode:
const string encodingName = " cl100k_base " ;
const string inputText = " Some Text <|endofprompt|> " ;
var allowedSpecialTokens = new HashSet < string > { " <|endofprompt|> " } ;
var encoding = GptEncoding . GetEncoding ( encodingName ) ;
var encoded = encoding . Encode ( inputText , allowedSpecialTokens ) ;
var expectedEncoded = new List < int > { 8538 , 2991 , 220 , 100276 } ;
Assert . Equal ( expectedEncoded , encoded ) ; Demikian pula, Anda dapat menentukan set kustom token khusus yang tidak diizinkan saat mengkode teks. Lulus HashSet<string> yang berisi token khusus yang tidak diizinkan sebagai parameter ke metode encode:
const string encodingName = " cl100k_base " ;
const string inputText = " Some Text " ;
var encoding = GptEncoding . GetEncoding ( encodingName ) ;
void TestAction ( )
{
encoding . Encode ( inputText , disallowedSpecial : new HashSet < string > { " Some " } ) ;
}
Assert . Throws < ArgumentException > ( TestAction ) ; Dalam contoh ini, ArgumentException dilemparkan karena teks input berisi token khusus yang tidak diizinkan
Sharptoken mencakup satu set kasus uji di file testplans.txt untuk memastikan kompatibilitasnya dengan pustaka Python Tiktoken. Kasus -kasus uji ini memvalidasi fungsionalitas dan perilaku Sharptoken, memberikan referensi yang dapat diandalkan untuk pengembang. Menjalankan tes unit dan memverifikasi kasus uji membantu mempertahankan konsistensi antara perpustakaan C# Sharptoken dan implementasi Python asli.
Sharptoken adalah perpustakaan tercepat dengan alokasi terendah!
[ SimpleJob ( RuntimeMoniker . Net60 ) ]
[ SimpleJob ( RuntimeMoniker . Net80 ) ]
[ SimpleJob ( RuntimeMoniker . Net471 ) ]
[ RPlotExporter ]
[ MemoryDiagnoser ]
public class CompareBenchmark
{
private GptEncoding _sharpToken ;
private TikToken _tikToken ;
private ITokenizer _tokenizer ;
private Tokenizer _mlTokenizer ;
private string _kLongText ;
[ GlobalSetup ]
public async Task Setup ( )
{
_sharpToken = GptEncoding . GetEncoding ( " cl100k_base " ) ;
_tikToken = await TikToken . GetEncodingAsync ( " cl100k_base " ) . ConfigureAwait ( false ) ;
_tokenizer = await TokenizerBuilder . CreateByModelNameAsync ( " gpt-4 " ) . ConfigureAwait ( false ) ;
_kLongText = " King Lear, one of Shakespeare's darkest and most savage plays, tells the story of the foolish and Job-like Lear, who divides his kingdom, as he does his affections, according to vanity and whim. Lear’s failure as a father engulfs himself and his world in turmoil and tragedy. " ;
}
[ Benchmark ]
public int SharpToken ( )
{
var sum = 0 ;
for ( var i = 0 ; i < 10000 ; i ++ )
{
var encoded = _sharpToken . Encode ( _kLongText ) ;
var decoded = _sharpToken . Decode ( encoded ) ;
sum += decoded . Length ;
}
return sum ;
}
[ Benchmark ]
public int TiktokenSharp ( )
{
var sum = 0 ;
for ( var i = 0 ; i < 10000 ; i ++ )
{
var encoded = _tikToken . Encode ( _kLongText ) ;
var decoded = _tikToken . Decode ( encoded ) ;
sum += decoded . Length ;
}
return sum ;
}
[ Benchmark ]
public int TokenizerLib ( )
{
var sum = 0 ;
for ( var i = 0 ; i < 10000 ; i ++ )
{
var encoded = _tokenizer . Encode ( _kLongText ) ;
var decoded = _tokenizer . Decode ( encoded . ToArray ( ) ) ;
sum += decoded . Length ;
}
return sum ;
}
[ Benchmark ]
public int MLTokenizers ( )
{
var sum = 0 ;
for ( var i = 0 ; i < 10000 ; i ++ )
{
var encoded = _mlTokenizer . EncodeToIds ( _kLongText ) ;
var decoded = _mlTokenizer . Decode ( encoded ) ;
sum += decoded . Length ;
}
return sum ;
}
} BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, Windows 11 (10.0.22631.3296)
11th Gen Intel Core i9-11950H 2.60GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.100-preview.2.24157.14
[Host] : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2
.NET 6.0 : .NET 6.0.28 (6.0.2824.12007), X64 RyuJIT AVX2
.NET 8.0 : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2
.NET Framework 4.7.1 : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256
| Metode | Pekerjaan | Runtime | Berarti | Kesalahan | Stddev | Median | Gen0 | Gen1 | Dialokasikan |
|---|---|---|---|---|---|---|---|---|---|
| MlTokenizers | .NET 8.0 | .NET 8.0 | 60,55 ms | 1.143 ms | 1.123 ms | 60,45 ms | 1000.0000 | - | 13.12 MB |
| MlTokenizers | .NET 6.0 | .NET 6.0 | 95,75 ms | 1.374 ms | 1.147 ms | 95,54 ms | 10500.0000 | - | 126.19 MB |
| MlTokenizers | .NET Framework 4.7.1 | .NET Framework 4.7.1 | 291.77 ms | 5.811 ms | 11.195 ms | 291.64 ms | 21000.0000 | - | 127.33 MB |
| Sharptoken | .NET 8.0 | .NET 8.0 | 87,78 ms | 1,700 ms | 1,590 ms | 87,34 ms | 1000.0000 | - | 22.13 MB |
| Sharptoken | .NET 6.0 | .NET 6.0 | 128.84 ms | 1,718 ms | 1.607 ms | 128.17 ms | 16250.0000 | 500.0000 | 196.31 MB |
| Sharptoken | .NET Framework 4.7.1 | .NET Framework 4.7.1 | 356.21 ms | 6.843 ms | 10.854 ms | 355.09 ms | 34000.0000 | 1000.0000 | 204.39 MB |
| Tokenizerlib | .NET 8.0 | .NET 8.0 | 109.26 ms | 2.082 ms | 4.482 ms | 107,90 ms | 18200.0000 | 600.0000 | 217.82 MB |
| Tokenizerlib | .NET 6.0 | .NET 6.0 | 126.16 ms | 2.959 ms | 8.630 ms | 122,34 ms | 18000.0000 | 500.0000 | 217.82 MB |
| Tokenizerlib | .NET Framework 4.7.1 | .NET Framework 4.7.1 | 374.71 ms | 7.374 ms | 16.794 ms | 370.12 ms | 40000.0000 | 1000.0000 | 243.79 MB |
| Tiktokensharp | .NET 8.0 | .NET 8.0 | 177.34 ms | 3,506 ms | 8.797 ms | 174,98 ms | 28000.0000 | 1000.0000 | 338.98 MB |
| Tiktokensharp | .NET 6.0 | .NET 6.0 | 196.17 MS | 3,912 ms | 8.422 ms | 195.52 ms | 26000.0000 | 666.6667 | 313.26 MB |
| Tiktokensharp | .NET Framework 4.7.1 | .NET Framework 4.7.1 | 488.22 ms | 9.696 ms | 15.931 ms | 487.17 ms | 63000.0000 | 1000.0000 | 378.31 MB |
Sharptoken sangat dioptimalkan pada Net8.0. Ini menggunakan instruksi CPU multibyte modern dan hampir tidak ada alokasi tumpukan.
Semua metode inti telah diuji pada teks input besar dan kecil.
Input:
SmallText : 453 B (teks/polos)LargeText : 51 kb (teks/html)Metode:
Encode : Teks ke tokenDecode : Token ke SMSCountTokens : API Kinerja Tinggi untuk Menghitung Token Teks BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3296/23H2/2023Update/SunValley3)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK 8.0.200
[Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
.NET 6.0 : .NET 6.0.16 (6.0.1623.17311), X64 RyuJIT AVX2
.NET 8.0 : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
.NET Framework 4.7.1 : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256
| Metode | Berarti | Kesalahan | Stddev | Perbandingan | RasioSd | Dialokasikan | Rasio Alloc |
|---|---|---|---|---|---|---|---|
| .NET 8.0 | |||||||
| Encode_smalltext | 22.649 AS | 0.4244 AS | 0.4359 AS | 0.28 | 0,01 | 696 b | 0,02 |
| Encode_largetext | 4.542.505 AS | 87.7988 AS | 104.5182 US | 0.24 | 0,01 | 155547 b | 0,03 |
| Decode_smalltext | 1.623 AS | 0.0324 AS | 0,0373 AS | 0.44 | 0,02 | 2320 b | 0.98 |
| Decode_largetext | 454.570 AS | 6.8980 AS | 6.4524 AS | 0.80 | 0,02 | 286979 b | 1.00 |
| Counttokens_smalltext | 22.008 AS | 0.1165 AS | 0,0909 AS | 0.28 | 0,00 | 184 b | 0,005 |
| Counttokens_largetext | 4.231.353 AS | 14.5157 US | 11.3329 AS | 0.23 | 0,00 | 195 b | 0,000 |
| .NET 6.0 | |||||||
| Encode_smalltext | 36.370 AS | 0.7178 AS | 1.0962 AS | 0.45 | 0,02 | 37344 b | 0.91 |
| Encode_largetext | 11.213.070 AS | 219.6291 AS | 269.7243 AS | 0,59 | 0,02 | 5062574 b | 0.91 |
| Decode_smalltext | 2.588 AS | 0,0394 AS | 0,0350 AS | 0,70 | 0,02 | 2320 b | 0.98 |
| Decode_largetext | 489.467 AS | 8.9195 AS | 8.3433 AS | 0.86 | 0,02 | 286985 b | 1.00 |
| Counttokens_smalltext | 34.758 AS | 0.2027 AS | 0.1896 AS | 0.45 | 0,01 | 36832 b | 0.907 |
| Counttokens_largetext | 11.252.083 AS | 215.8912 AS | 212.0340 AS | 0.61 | 0,01 | 4907169 b | 0.907 |
| .NET Framework 4.7.1 | |||||||
| Encode_smalltext | 79.947 AS | 1.5621 AS | 3.0097 AS | 1.00 | 0,00 | 41138 b | 1.00 |
| Encode_largetext | 18.961.252 US | 253.1816 AS | 236.8262 US | 1.00 | 0,00 | 5567685 b | 1.00 |
| Decode_smalltext | 3.723 AS | 0.0728 AS | 0.0997 AS | 1.00 | 0,00 | 2375 b | 1.00 |
| Decode_largetext | 570.787 US | 11.0356 AS | 11.8080 AS | 1.00 | 0,00 | 287496 b | 1.00 |
| Counttokens_smalltext | 77.521 AS | 1.0802 AS | 0.9020 AS | 1.00 | 0,00 | 40616 b | 1.000 |
| Counttokens_largetext | 18.485.392 AS | 313.5834 AS | 277.9836 AS | 1.00 | 0,00 | 5413237 b | 1.000 |
Jika Anda menghadapi masalah atau memiliki saran untuk perbaikan, jangan ragu untuk membuka masalah atau mengirimkan permintaan tarik pada repositori proyek.
Semoga Anda menganggap Sharptoken bermanfaat untuk proyek Anda dan menyambut umpan balik apa pun yang mungkin Anda miliki.