gigatoken 0.1.0-aarch64-linux → 0.2.0-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +54 -11
- data/lib/gigatoken/3.3/gigatoken_rb.so +0 -0
- data/lib/gigatoken/3.4/gigatoken_rb.so +0 -0
- data/lib/gigatoken/4.0/gigatoken_rb.so +0 -0
- data/lib/gigatoken/cli/bench.rb +4 -3
- data/lib/gigatoken/cli/support.rb +7 -4
- data/lib/gigatoken/cli/validate.rb +4 -3
- data/lib/gigatoken/encodings/PROVENANCE.md +110 -0
- data/lib/gigatoken/encodings/cl100k_base.tiktoken +100256 -0
- data/lib/gigatoken/encodings/o200k_base.tiktoken +199998 -0
- data/lib/gigatoken/encodings/r50k_base.tiktoken +50256 -0
- data/lib/gigatoken/encodings.rb +103 -0
- data/lib/gigatoken/tokenizer.rb +48 -11
- data/lib/gigatoken/version.rb +1 -1
- data/lib/gigatoken.rb +15 -0
- metadata +8 -2
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gigatoken
|
|
4
|
+
# The tiktoken encodings gigatoken vendors ranks for, and the pieces a
|
|
5
|
+
# .tiktoken file doesn't carry: its pretokenizer scheme and special-token
|
|
6
|
+
# table (see Tokenizer.from_tiktoken and lib/gigatoken/encodings/
|
|
7
|
+
# PROVENANCE.md, the source of truth this is transcribed from).
|
|
8
|
+
module Encodings
|
|
9
|
+
DATA_DIR = File.expand_path("encodings", __dir__)
|
|
10
|
+
private_constant :DATA_DIR
|
|
11
|
+
|
|
12
|
+
# The non-contiguous head of openai_public.py's o200k_harmony()
|
|
13
|
+
# special-token table, transcribed verbatim (see PROVENANCE.md): its ten
|
|
14
|
+
# named control tokens, plus the six reserved slots sitting in the gaps
|
|
15
|
+
# between them (200000, 200001, 200004, 200009, 200010, 200011). The
|
|
16
|
+
# reserved range only goes contiguous at 200013.
|
|
17
|
+
HARMONY_HEAD_TOKENS = {
|
|
18
|
+
"<|startoftext|>" => 199998,
|
|
19
|
+
"<|endoftext|>" => 199999,
|
|
20
|
+
"<|reserved_200000|>" => 200000,
|
|
21
|
+
"<|reserved_200001|>" => 200001,
|
|
22
|
+
"<|return|>" => 200002,
|
|
23
|
+
"<|constrain|>" => 200003,
|
|
24
|
+
"<|reserved_200004|>" => 200004,
|
|
25
|
+
"<|channel|>" => 200005,
|
|
26
|
+
"<|start|>" => 200006,
|
|
27
|
+
"<|end|>" => 200007,
|
|
28
|
+
"<|message|>" => 200008,
|
|
29
|
+
"<|reserved_200009|>" => 200009,
|
|
30
|
+
"<|reserved_200010|>" => 200010,
|
|
31
|
+
"<|reserved_200011|>" => 200011,
|
|
32
|
+
"<|call|>" => 200012,
|
|
33
|
+
"<|endofprompt|>" => 200018
|
|
34
|
+
}.freeze
|
|
35
|
+
private_constant :HARMONY_HEAD_TOKENS
|
|
36
|
+
|
|
37
|
+
# The contiguous tail of that reserved range: 200013..201087. With the
|
|
38
|
+
# head above, 1091 entries total — 10 named, 1081 reserved (see
|
|
39
|
+
# PROVENANCE.md).
|
|
40
|
+
HARMONY_RESERVED_TAIL = (200013..201087).to_h { |id| ["<|reserved_#{id}|>", id] }.freeze
|
|
41
|
+
private_constant :HARMONY_RESERVED_TAIL
|
|
42
|
+
|
|
43
|
+
REGISTRY = {
|
|
44
|
+
"r50k_base" => {
|
|
45
|
+
rank_file: File.join(DATA_DIR, "r50k_base.tiktoken"),
|
|
46
|
+
pretokenizer: "gpt2",
|
|
47
|
+
special_tokens: {"<|endoftext|>" => 50256}
|
|
48
|
+
},
|
|
49
|
+
"cl100k_base" => {
|
|
50
|
+
rank_file: File.join(DATA_DIR, "cl100k_base.tiktoken"),
|
|
51
|
+
pretokenizer: "gpt4",
|
|
52
|
+
special_tokens: {
|
|
53
|
+
"<|endoftext|>" => 100257,
|
|
54
|
+
"<|fim_prefix|>" => 100258,
|
|
55
|
+
"<|fim_middle|>" => 100259,
|
|
56
|
+
"<|fim_suffix|>" => 100260,
|
|
57
|
+
"<|endofprompt|>" => 100276
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"o200k_base" => {
|
|
61
|
+
rank_file: File.join(DATA_DIR, "o200k_base.tiktoken"),
|
|
62
|
+
pretokenizer: "o200k",
|
|
63
|
+
special_tokens: {"<|endoftext|>" => 199999, "<|endofprompt|>" => 200018}
|
|
64
|
+
},
|
|
65
|
+
"o200k_harmony" => {
|
|
66
|
+
rank_file: File.join(DATA_DIR, "o200k_base.tiktoken"),
|
|
67
|
+
pretokenizer: "o200k",
|
|
68
|
+
special_tokens: HARMONY_HEAD_TOKENS.merge(HARMONY_RESERVED_TAIL).freeze
|
|
69
|
+
}
|
|
70
|
+
}.freeze
|
|
71
|
+
private_constant :REGISTRY
|
|
72
|
+
|
|
73
|
+
# The packaged encoding names — the single source error messages naming
|
|
74
|
+
# what's available are built from (the same discipline
|
|
75
|
+
# Native.pretokenizer_names / PretokenizerType::NAMES applies to
|
|
76
|
+
# pretokenizer scheme names).
|
|
77
|
+
NAMES = REGISTRY.keys.freeze
|
|
78
|
+
|
|
79
|
+
# Encodings known by name but deliberately not packaged, keyed to the
|
|
80
|
+
# reason a caller asking for one by name deserves to hear.
|
|
81
|
+
UNPACKABLE_REASONS = {
|
|
82
|
+
"p50k_base" => "its ranks are not dense (50256 is left free for <|endoftext|>), " \
|
|
83
|
+
"and the rank loader rejects non-dense ranks",
|
|
84
|
+
"p50k_edit" => "it loads the same p50k_base.tiktoken ranks, which are not dense " \
|
|
85
|
+
"(50256 is left free for <|endoftext|>), and the rank loader rejects non-dense ranks"
|
|
86
|
+
}.freeze
|
|
87
|
+
private_constant :UNPACKABLE_REASONS
|
|
88
|
+
|
|
89
|
+
class << self
|
|
90
|
+
# The {rank_file:, pretokenizer:, special_tokens:} registered for a
|
|
91
|
+
# packaged encoding name, or nil.
|
|
92
|
+
def [](name)
|
|
93
|
+
REGISTRY[name]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Why `name` can't be packaged, or nil when there's no reason on
|
|
97
|
+
# record (it's either packaged, or simply not one gigatoken knows of).
|
|
98
|
+
def unpackable_reason(name)
|
|
99
|
+
UNPACKABLE_REASONS[name]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
data/lib/gigatoken/tokenizer.rb
CHANGED
|
@@ -7,9 +7,6 @@ module Gigatoken
|
|
|
7
7
|
# over a native `Gigatoken::Native::BPETokenizer` or
|
|
8
8
|
# `Gigatoken::Native::SentencePieceTokenizer`.
|
|
9
9
|
class Tokenizer
|
|
10
|
-
TIKTOKEN_ENDOFTEXT = "<|endoftext|>"
|
|
11
|
-
private_constant :TIKTOKEN_ENDOFTEXT
|
|
12
|
-
|
|
13
10
|
FILE_SOURCE_CLASSES = [Native::TextFileSource, Native::JsonlFileSource, Native::ParquetFileSource].freeze
|
|
14
11
|
private_constant :FILE_SOURCE_CLASSES
|
|
15
12
|
|
|
@@ -27,10 +24,27 @@ module Gigatoken
|
|
|
27
24
|
from_json(File.binread(path))
|
|
28
25
|
end
|
|
29
26
|
|
|
30
|
-
# Load from a .tiktoken mergeable-ranks file.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
# Load from a .tiktoken mergeable-ranks file. The file carries neither a
|
|
28
|
+
# pretokenization scheme nor special tokens — nothing is guessed here,
|
|
29
|
+
# so `pretokenizer:` is required: one of the schemes gigatoken ships
|
|
30
|
+
# (see Native.pretokenizer_names, e.g. "gpt2"/"r50k", "gpt4"/"cl100k",
|
|
31
|
+
# "o200k", "qwen2", "qwen35", "olmo3", "deepseek_v3", "nemotron", "kimi").
|
|
32
|
+
# `special_tokens:` maps token content to id (none by default).
|
|
33
|
+
def self.from_tiktoken(path, pretokenizer:, special_tokens: {})
|
|
34
|
+
native = Native::BPETokenizer.from_tiktoken(path.to_s, pretokenizer, special_tokens)
|
|
35
|
+
new(native, special_tokens: special_tokens)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Load one of the tiktoken encodings gigatoken vendors ranks for, by
|
|
39
|
+
# name — see Gigatoken::Encodings::NAMES — entirely from the vendored
|
|
40
|
+
# files: no network, no writable cache.
|
|
41
|
+
def self.from_encoding(name)
|
|
42
|
+
encoding = Encodings[name]
|
|
43
|
+
return from_tiktoken(encoding[:rank_file], pretokenizer: encoding[:pretokenizer], special_tokens: encoding[:special_tokens]) if encoding
|
|
44
|
+
|
|
45
|
+
reason = Encodings.unpackable_reason(name)
|
|
46
|
+
detail = reason ? " — #{reason}" : ""
|
|
47
|
+
raise Error, "#{name.inspect}: not a packaged encoding#{detail} (packaged encodings: #{Encodings::NAMES.join(", ")})"
|
|
34
48
|
end
|
|
35
49
|
|
|
36
50
|
# Load tokenizer.json from HuggingFace Hub repo `repo_id` at `revision`
|
|
@@ -41,12 +55,29 @@ module Gigatoken
|
|
|
41
55
|
|
|
42
56
|
# Load from any of the supported source shapes: an existing file or
|
|
43
57
|
# directory path (a tokenizer.json, or a directory containing one), a
|
|
44
|
-
# .tiktoken vocabulary file,
|
|
45
|
-
# "
|
|
46
|
-
|
|
58
|
+
# .tiktoken vocabulary file, a packaged encoding name (see
|
|
59
|
+
# Gigatoken::Encodings::NAMES, e.g. "cl100k_base"), or a HuggingFace Hub
|
|
60
|
+
# repo id like "openai-community/gpt2". A .tiktoken file carries no
|
|
61
|
+
# pretokenizer scheme of its own, so one must be named explicitly via
|
|
62
|
+
# `pretokenizer:` — nothing here is guessed. Packaged encoding names are
|
|
63
|
+
# checked before the Hub-repo-id shape: a bare name like "o200k_base" is
|
|
64
|
+
# also shaped like a legacy repo id, and must resolve locally rather
|
|
65
|
+
# than reach the network. Names the registry knows but doesn't package
|
|
66
|
+
# (see Encodings.unpackable_reason, e.g. "p50k_base") are intercepted
|
|
67
|
+
# here too, raising the same explanation from_encoding gives rather than
|
|
68
|
+
# reaching the Hub — but only those; an unrecognized bare name like
|
|
69
|
+
# "gpt2" still dispatches to the Hub.
|
|
70
|
+
def self.load(source, pretokenizer: nil, special_tokens: {}, revision: "main", hub: Hub.new)
|
|
47
71
|
source = source.to_s
|
|
48
|
-
|
|
72
|
+
if source.end_with?(".tiktoken")
|
|
73
|
+
unless pretokenizer
|
|
74
|
+
raise Error, "#{source.inspect}: a .tiktoken file carries no pretokenizer scheme of its own — " \
|
|
75
|
+
"pass pretokenizer: (one of #{Native.pretokenizer_names.join(", ")})"
|
|
76
|
+
end
|
|
77
|
+
return from_tiktoken(source, pretokenizer: pretokenizer, special_tokens: special_tokens)
|
|
78
|
+
end
|
|
49
79
|
return from_file(source) if File.exist?(source)
|
|
80
|
+
return from_encoding(source) if Encodings::NAMES.include?(source) || Encodings.unpackable_reason(source)
|
|
50
81
|
return from_hub(source, revision: revision, hub: hub) if Hub.looks_like_repo_id?(source)
|
|
51
82
|
|
|
52
83
|
raise Error, "#{source.inspect}: no such file or directory, not a .tiktoken path, and doesn't look like a HuggingFace Hub repo id"
|
|
@@ -112,6 +143,12 @@ module Gigatoken
|
|
|
112
143
|
@native.merges
|
|
113
144
|
end
|
|
114
145
|
|
|
146
|
+
# Cached pretoken/unit entries on this tokenizer's single-document
|
|
147
|
+
# encode path — see Gigatoken.max_cache_bytes.
|
|
148
|
+
def cache_entries
|
|
149
|
+
@native.cache_entries
|
|
150
|
+
end
|
|
151
|
+
|
|
115
152
|
attr_reader :special_tokens
|
|
116
153
|
end
|
|
117
154
|
end
|
data/lib/gigatoken/version.rb
CHANGED
data/lib/gigatoken.rb
CHANGED
|
@@ -7,6 +7,20 @@ module Gigatoken
|
|
|
7
7
|
# extension — never a raw Rust panic across the Ruby boundary.
|
|
8
8
|
class Error < StandardError; end
|
|
9
9
|
|
|
10
|
+
class << self
|
|
11
|
+
# The process-global encode-cache budget in bytes per worker (a parallel
|
|
12
|
+
# batch encode may use up to workers x budget), applied to tokenizers of
|
|
13
|
+
# either backend constructed *afterward* — changing it never affects an
|
|
14
|
+
# already-built Tokenizer. nil means unbounded. Default: 512 MiB.
|
|
15
|
+
def max_cache_bytes
|
|
16
|
+
Native.get_max_cache_bytes
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def max_cache_bytes=(bytes)
|
|
20
|
+
Native.set_max_cache_bytes(bytes)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
10
24
|
NATIVE_EXTENSIONS = %w[.bundle .so .rb].freeze
|
|
11
25
|
|
|
12
26
|
# Precompiled native gems ship per-ABI subdirs (`gigatoken/4.0/...`),
|
|
@@ -26,4 +40,5 @@ require native
|
|
|
26
40
|
|
|
27
41
|
require_relative "gigatoken/hub"
|
|
28
42
|
require_relative "gigatoken/packed_result"
|
|
43
|
+
require_relative "gigatoken/encodings"
|
|
29
44
|
require_relative "gigatoken/tokenizer"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gigatoken
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Jacobs
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async
|
|
@@ -72,6 +72,11 @@ files:
|
|
|
72
72
|
- lib/gigatoken/cli/bench.rb
|
|
73
73
|
- lib/gigatoken/cli/support.rb
|
|
74
74
|
- lib/gigatoken/cli/validate.rb
|
|
75
|
+
- lib/gigatoken/encodings.rb
|
|
76
|
+
- lib/gigatoken/encodings/PROVENANCE.md
|
|
77
|
+
- lib/gigatoken/encodings/cl100k_base.tiktoken
|
|
78
|
+
- lib/gigatoken/encodings/o200k_base.tiktoken
|
|
79
|
+
- lib/gigatoken/encodings/r50k_base.tiktoken
|
|
75
80
|
- lib/gigatoken/hub.rb
|
|
76
81
|
- lib/gigatoken/packed_result.rb
|
|
77
82
|
- lib/gigatoken/tokenizer.rb
|
|
@@ -82,6 +87,7 @@ licenses:
|
|
|
82
87
|
- MIT
|
|
83
88
|
metadata:
|
|
84
89
|
bug_tracker_uri: https://github.com/jetpks/gigatoken-rb/issues
|
|
90
|
+
changelog_uri: https://github.com/jetpks/gigatoken-rb/blob/main/CHANGELOG.md
|
|
85
91
|
homepage_uri: https://github.com/jetpks/gigatoken-rb
|
|
86
92
|
source_code_uri: https://github.com/jetpks/gigatoken-rb
|
|
87
93
|
post_install_message:
|