
Sharptoken은 Python Tiktoken 라이브러리의 포트 역할을하는 C# 라이브러리입니다. GPT 기반 인코딩을 사용하여 토큰 인코딩 및 디코딩 기능을 제공합니다. 이 라이브러리는 .NET 6, .NET 8 및 .NET Standard 2.0 용으로 구축되어 광범위한 프레임 워크와 호환됩니다.
중요한
SharpToken 의 기능은 Microsoft.ML.Tokenizers 에 추가되었습니다. Microsoft.ML.Tokenizers 는 .NET 팀에서 개발하고 있으며 .NET의 토큰 화제 개발의 중심점 인 .NET 팀이 개발하고 있습니다. Microsoft.ML.Tokenizers 사용하면 SharpToken 포함한 기존 토큰 화기 라이브러리 구현보다 성능이 향상됩니다. .NET 9.0 릴리스 (2024 년 11 월)와 함께 Microsoft.ML.Tokenizers 의 안정적인 출시가 예상됩니다. 마이그레이션 지침은 https://github.com/dotnet/machinelearning/blob/main/docs/code/microsoft-ml-tokenizers-migration-guide.md에서 찾을 수 있습니다.
Sharptoken을 설치하려면 Nuget 패키지 관리자를 사용하십시오.
Install-Package SharpToken또는 .NET CLI를 선호하는 경우 :
dotnet add package SharpToken자세한 내용은 Nuget 패키지 페이지를 방문하십시오.
프로젝트에서 Sharptoken을 사용하려면 먼저 라이브러리를 가져 오십시오.
using SharpToken ;다음으로 원하는 인코딩 또는 모델을 지정하여 gptencoding 인스턴스를 만듭니다.
// 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으로 보내기 전에 프롬프트 크기를 확인하거나 Rag의 TextSplitter/Chunker에서 사용하는 것이 유용합니다.
var count = encoding . CountTokens ( " Hello, world! " ) ; // Output: 4 Sharptoken은 현재 다음 모델을 지원합니다.
r50k_basep50k_basep50k_editcl100k_baseo200k_basegptencoding 인스턴스를 만들 때 이러한 모델을 사용할 수 있습니다.
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 반환합니다.
Encode 메소드를 사용하여 문자열을 인코딩하면 리턴 된 값은 지정된 인코딩에서 토큰을 나타내는 정수 목록입니다. 이 토큰은 입력 텍스트를 나타내는 소형 방법이며 다양한 알고리즘으로보다 효율적으로 처리 할 수 있습니다.
예를 들어, "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을 사용하면 텍스트를 인코딩 할 때 허용되는 특수 토큰의 사용자 정의 세트를 지정할 수 있습니다. 이렇게하려면 허용 특수 토큰이 포함 된 해시 세트를 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 ) ; 마찬가지로 텍스트를 인코딩 할 때 허용하지 않는 특수 토큰의 사용자 정의 세트를 지정할 수 있습니다. 허용되지 않은 특수 토큰을 포함하는 HashSet<string> 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 ) ; 이 예에서는 입력 텍스트에 허용되지 않은 특수 토큰이 포함되어 있기 때문에 ArgumentException 발생합니다.
Sharptoken에는 Python Tiktoken 라이브러리와의 호환성을 보장하기 위해 TestPlans.txt 파일에 일련의 테스트 사례가 포함되어 있습니다. 이러한 테스트 사례는 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.55ms | 1.143 MS | 1.123 MS | 60.45ms | 1000.0000 | - | 13.12 MB |
| mltokenizers | .NET 6.0 | .NET 6.0 | 95.75ms | 1.374ms | 1.147ms | 95.54ms | 10500.0000 | - | 126.19 MB |
| mltokenizers | .NET 프레임 워크 4.7.1 | .NET 프레임 워크 4.7.1 | 291.77 ms | 5.811ms | 11.195 ms | 291.64 ms | 21000.0000 | - | 127.33 MB |
| Sharptoken | .NET 8.0 | .NET 8.0 | 87.78ms | 1.700ms | 1.590ms | 87.34ms | 1000.0000 | - | 22.13 MB |
| Sharptoken | .NET 6.0 | .NET 6.0 | 128.84 ms | 1.718ms | 1.607ms | 128.17ms | 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.09ms | 34000.0000 | 1000.0000 | 204.39 MB |
| Tokenizerlib | .NET 8.0 | .NET 8.0 | 109.26ms | 2.082ms | 4.482ms | 107.90ms | 18200.0000 | 600.0000 | 217.82 MB |
| Tokenizerlib | .NET 6.0 | .NET 6.0 | 126.16 ms | 2.959ms | 8.630ms | 122.34 ms | 18000.0000 | 500.0000 | 217.82 MB |
| Tokenizerlib | .NET 프레임 워크 4.7.1 | .NET 프레임 워크 4.7.1 | 374.71 ms | 7.374 ms | 16.794 ms | 370.12ms | 40000.0000 | 1000.0000 | 243.79 MB |
| Tiktokensharp | .NET 8.0 | .NET 8.0 | 177.34 ms | 3.506ms | 8.797ms | 174.98 ms | 28000.0000 | 1000.0000 | 338.98 MB |
| Tiktokensharp | .NET 6.0 | .NET 6.0 | 196.17 MS | 3.912ms | 8.422ms | 195.52ms | 26000.0000 | 666.6667 | 313.26 MB |
| Tiktokensharp | .NET 프레임 워크 4.7.1 | .NET 프레임 워크 4.7.1 | 488.22 ms | 9.696 ms | 15.931 ms | 487.17 ms | 63000.0000 | 1000.0000 | 378.31 MB |
Sharptoken은 Net8.0에서 최적화 된 성능을 발표합니다. 현대적인 멀티 바이트 CPU 명령어를 사용하고 힙 할당이 거의 없습니다.
모든 핵심 방법은 크고 작은 입력 텍스트에서 테스트되었습니다.
입력 :
SmallText : 453 B (텍스트/일반)LargeText : 51 KB (텍스트/html)행동 양식:
Encode : 토큰으로 텍스트Decode : 텍스트 토큰CountTokens : 텍스트 토큰을 계산하는 고성능 API 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 우리 | 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 우리 | 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 미국 | 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 우리 | 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 | US 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 우리 | 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을 발견하고 피드백을 환영합니다.