
Sharptoken是一個C#圖書館,用作Python Tiktoken庫的港口。它提供了使用基於GPT的編碼來編碼和解碼令牌的功能。該庫是為.NET 6,.NET 8和.NET標準2.0構建的,使其與廣泛的框架兼容。
重要的
SharpToken中的功能已添加到Microsoft.ML.Tokenizers中。 Microsoft.ML.Tokenizers是一個由.NET團隊開發的令牌庫,並將其展開,這是.NET中的引物開發的中心地點。通過使用Microsoft.ML.Tokenizers ,您應該看到比現有的令牌庫實現(包括SharpToken的性能改進。預計Microsoft.ML.Tokenizers的穩定版本與.NET 9.0版本(2024年11月)。可以在https://github.com/dotnet/machinelearning/blob/main/main/docs/code/microsoft-mlosoft-ml-tokenizers-migration-migration-guide.md上找到遷移的說明。
要安裝Sharptoken,請使用Nuget軟件包管理器:
Install-Package SharpToken或者,如果您喜歡使用.NET CLI:
dotnet add package SharpToken有關更多信息,請訪問Nuget軟件包頁面。
要在您的項目中使用Sharptoken,請首先導入庫:
using SharpToken ;接下來,通過指定所需的編碼或模型來創建gptencing的實例:
// Get encoding by encoding name
var encoding = GptEncoding . GetEncoding ( " cl100k_base " ) ;
// Get encoding by model name
var encoding = GptEncoding . GetEncodingForModel ( " gpt-4 " ) ;然後,您可以使用編碼方法來編碼一個字符串:
var encoded = encoding . Encode ( " Hello, world! " ) ; // Output: [9906, 11, 1917, 0]並使用解碼方法解碼編碼的令牌:
var decoded = encoding . Decode ( encoded ) ; // Output: "Hello, world!"Sharptoken還提供了高性能計數方法。在將其發送到LLM之前檢查提示尺寸或在Textsplitter/Chunker中將其用於抹布很有用。
var count = encoding . CountTokens ( " Hello, world! " ) ; // Output: 4 Sharptoken目前支持以下模型:
r50k_basep50k_basep50k_editcl100k_baseo200k_base在創建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 " ) ;除了指定直接模型名稱外,Sharptoken還根據特定前綴為映射模型名稱提供功能。這允許用戶根據模型的前綴檢索編碼。
這是當前受支持的前綴及其相應的編碼:
| 模型前綴 | 編碼 |
|---|---|
gpt-4o | o200k_base |
gpt-4- | cl100k_base |
gpt-3.5-turbo- | cl100k_base |
gpt-35-turbo | cl100k_base |
屬於這些前綴下的模型名稱的示例包括:
gpt-4o : gpt-4o , gpt-4o-2024-05-13 ,等等。gpt-4- : gpt-4-0314 , gpt-4-32k等。gpt-3.5-turbo- : gpt-3.5-turbo-0301 , gpt-3.5-turbo-0401 ,等等。gpt-35-turbo 。要根據模型名稱或其前綴檢索編碼名稱,您可以使用GetEncodingNameForModel方法:
string encodingName = Model . GetEncodingNameForModel ( " gpt-4-0314 " ) ; // This will return "cl100k_base"如果提供的模型名稱與任何直接模型名稱或前綴不匹配,則該方法將返回null 。
當您使用編碼方法編碼字符串時,返回的值是代表指定編碼中令牌的整數列表。這些令牌是表示輸入文本的緊湊方法,可以通過各種算法更有效地處理。
例如,編碼文本“ Hello World!”使用CL100K_BASE編碼可能會產生以下整數列表:
var encoded = cl100kBaseEncoding . Encode ( " Hello world! " ) ; // Output: [9906, 1917, 0]然後,您可以使用Decode方法將這些令牌化整數值轉換回原始文本:
var decoded = cl100kBaseEncoding . Decode ( encoded ) ; // Output: "Hello world!"使用Sharptoken,您可以在不同的編碼之間無縫切換,以找到最適合您需求的編碼。只需記住,對Encode和Decode方法都使用相同的編碼以確保結果。
Sharptoken允許您在編碼文本時指定允許的特殊令牌的自定義集。為此,請傳遞包含允許的特殊令牌作為參數的主題集,以將其傳遞給編碼方法:
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 ) ;同樣,您可以在編碼文本時指定自定義的特殊令牌。傳遞一個HashSet<string>其中包含不允許的特殊令牌作為編碼方法的參數:
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 ) ;在此示例中,拋出了一個ArgumentException ,因為輸入文本包含不允許的特殊令牌
Sharptoken在testplans.txt文件中包含一組測試用例,以確保其與Python Tiktoken庫的兼容性。這些測試用例驗證了Sharptoken的功能和行為,為開發人員提供了可靠的參考。運行單元測試並驗證測試用例有助於保持C#Sharptoken庫與原始Python實現之間的一致性。
Sharptoken是最快的庫,分配最低!
[ 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
| 方法 | 工作 | 運行時 | 意思是 | 錯誤 | stddev | 中位數 | Gen0 | Gen1 | 分配 |
|---|---|---|---|---|---|---|---|---|---|
| mltokenizers | .NET 8.0 | .NET 8.0 | 60.55毫秒 | 1.143 ms | 1.123 ms | 60.45毫秒 | 1000.0000 | - | 13.12 MB |
| mltokenizers | .NET 6.0 | .NET 6.0 | 95.75毫秒 | 1.374 ms | 1.147 ms | 95.54毫秒 | 10500.0000 | - | 126.19 MB |
| mltokenizers | .NET框架4.7.1 | .NET框架4.7.1 | 291.77毫秒 | 5.811 ms | 11.195毫秒 | 291.64 ms | 21000.0000 | - | 127.33 MB |
| Sharptoken | .NET 8.0 | .NET 8.0 | 87.78毫秒 | 1.700毫秒 | 1.590毫秒 | 87.34 ms | 1000.0000 | - | 22.13 MB |
| Sharptoken | .NET 6.0 | .NET 6.0 | 128.84毫秒 | 1.718毫秒 | 1.607毫秒 | 128.17毫秒 | 16250.0000 | 500.0000 | 196.31 MB |
| Sharptoken | .NET框架4.7.1 | .NET框架4.7.1 | 356.21 ms | 6.843 ms | 10.854 ms | 355.09毫秒 | 34000.0000 | 1000.0000 | 204.39 MB |
| tokenizerlib | .NET 8.0 | .NET 8.0 | 109.26毫秒 | 2.082 ms | 4.482毫秒 | 107.90毫秒 | 18200.0000 | 600.0000 | 217.82 MB |
| tokenizerlib | .NET 6.0 | .NET 6.0 | 126.16 ms | 2.959毫秒 | 8.630毫秒 | 122.34 ms | 18000.0000 | 500.0000 | 217.82 MB |
| tokenizerlib | .NET框架4.7.1 | .NET框架4.7.1 | 374.71 ms | 7.374毫秒 | 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毫秒 | 8.797毫秒 | 174.98毫秒 | 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毫秒 | 26000.0000 | 666.6667 | 313.26 MB |
| tiktokensharp | .NET框架4.7.1 | .NET框架4.7.1 | 488.22毫秒 | 9.696毫秒 | 15.931 MS | 487.17毫秒 | 63000.0000 | 1000.0000 | 378.31 MB |
Sharptoken在Net8.0上進行了超出性能。它使用現代的多重CPU指令,幾乎沒有堆分配。
所有核心方法均已在大型和小輸入文本上進行了測試。
輸入:
SmallText :453 B(文本/平原)LargeText :51 kb(文本/html)方法:
Encode :文字到令牌Decode :文字的令牌CountTokens : high performance API to count tokens of text 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
| 方法 | 意思是 | 錯誤 | stddev | 比率 | 比率 | 分配 | 同種比率 |
|---|---|---|---|---|---|---|---|
| .NET 8.0 | |||||||
| Encode_smallText | 22.649美國 | 0.4244美國 | 0.4359 US | 0.28 | 0.01 | 696 b | 0.02 |
| encode_largetext | 美國4,542.505 | 87.7988美國 | 104.5182美國 | 0.24 | 0.01 | 155547 b | 0.03 |
| DECODE_SMALLTEXT | 1.623我們 | 0.0324美國 | 0.0373 US | 0.44 | 0.02 | 2320 b | 0.98 |
| decode_largetext | 454.570美國 | 6.8980美國 | 6.4524美國 | 0.80 | 0.02 | 286979 b | 1.00 |
| counttokens_smallText | 22.008美國 | 0.1165美國 | 0.0909 US | 0.28 | 0.00 | 184 b | 0.005 |
| counttokens_largetext | 美國4,231.353 | 14.5157美國 | 11.3329美國 | 0.23 | 0.00 | 195 b | 0.000 |
| .NET 6.0 | |||||||
| Encode_smallText | 36.370美國 | 0.7178 US | 1.0962美國 | 0.45 | 0.02 | 37344 b | 0.91 |
| encode_largetext | 11,213.070美國 | 219.6291美國 | 269.7243美國 | 0.59 | 0.02 | 5062574 b | 0.91 |
| DECODE_SMALLTEXT | 2.588美國 | 0.0394美國 | 0.0350美國 | 0.70 | 0.02 | 2320 b | 0.98 |
| decode_largetext | 489.467美國 | 8.9195美國 | 8.3433美國 | 0.86 | 0.02 | 286985 b | 1.00 |
| counttokens_smallText | 34.758美國 | 0.2027美國 | 0.1896美國 | 0.45 | 0.01 | 36832 b | 0.907 |
| counttokens_largetext | 11,252.083美國 | 215.8912美國 | 212.0340美國 | 0.61 | 0.01 | 4907169 b | 0.907 |
| .NET框架4.7.1 | |||||||
| Encode_smallText | 79.947美國 | 1.5621美國 | 3.0097美國 | 1.00 | 0.00 | 41138 b | 1.00 |
| encode_largetext | 18,961.252美國 | 253.1816美國 | 236.8262美國 | 1.00 | 0.00 | 5567685 b | 1.00 |
| DECODE_SMALLTEXT | 3.723美國 | 0.0728 US | 0.0997美國 | 1.00 | 0.00 | 2375 b | 1.00 |
| decode_largetext | 570.787美國 | 11.0356美國 | 11.8080美國 | 1.00 | 0.00 | 287496 b | 1.00 |
| counttokens_smallText | 77.521美國 | 1.0802美國 | 0.9020美國 | 1.00 | 0.00 | 40616 b | 1.000 |
| counttokens_largetext | 18,485.392美國 | 313.5834美國 | 277.9836美國 | 1.00 | 0.00 | 5413237 b | 1.000 |
如果您遇到任何問題或提出改進的建議,請隨時打開問題或在項目存儲庫上提交拉動請求。
希望您發現Sharptoken對您的項目有用,並歡迎您可能獲得的任何反饋。