static_embeddings 0.1.1 → 0.1.2
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/CHANGELOG.md +121 -0
- data/README.md +167 -276
- data/docs/ARCHITECTURE.md +56 -6
- data/docs/MODEL_AUDIT.md +21 -8
- data/docs/PERFORMANCE.md +104 -36
- data/ext/static_embeddings/extconf.rb +4 -0
- data/ext/static_embeddings/se_alloc_stats.c +244 -0
- data/ext/static_embeddings/se_f16.c +378 -0
- data/ext/static_embeddings/se_format.c +235 -148
- data/ext/static_embeddings/se_internal.h +159 -0
- data/ext/static_embeddings/se_tokenizer.c +144 -41
- data/ext/static_embeddings/se_topk.c +236 -0
- data/ext/static_embeddings/static_embeddings.c +225 -744
- data/lib/static_embeddings/format.rb +22 -11
- data/lib/static_embeddings/version.rb +1 -1
- data/tools/benchmark.rb +13 -4
- metadata +4 -1
|
@@ -70,6 +70,8 @@ module StaticEmbeddings
|
|
|
70
70
|
76 => :clean_text
|
|
71
71
|
}.freeze
|
|
72
72
|
|
|
73
|
+
VERIFY_CHUNK_BYTES = 1024 * 1024
|
|
74
|
+
|
|
73
75
|
module_function
|
|
74
76
|
|
|
75
77
|
def hash_bytes(str, seed = HASH_SEED)
|
|
@@ -120,14 +122,28 @@ module StaticEmbeddings
|
|
|
120
122
|
end
|
|
121
123
|
|
|
122
124
|
def verify(path)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
raise InvalidModelError, "file too small" if File.size(path) < HEADER_SIZE
|
|
126
|
+
|
|
127
|
+
File.open(path, "rb") do |io|
|
|
128
|
+
header = io.read(HEADER_SIZE)
|
|
129
|
+
raise InvalidModelError, "bad magic" unless header.byteslice(0, 8) == MAGIC.b
|
|
126
130
|
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
stored = header.byteslice(CHECKSUM_OFFSET, CHECKSUM_SIZE)
|
|
132
|
+
actual = streaming_checksum(io, header)
|
|
129
133
|
|
|
130
|
-
|
|
134
|
+
{ ok: stored == actual, expected: actual.unpack1("H*"), stored: stored.unpack1("H*") }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def streaming_checksum(io, header)
|
|
139
|
+
digest = Digest::SHA256.new
|
|
140
|
+
zeroed = header.dup
|
|
141
|
+
zeroed[CHECKSUM_OFFSET, CHECKSUM_SIZE] = "\0".b * CHECKSUM_SIZE
|
|
142
|
+
digest << zeroed
|
|
143
|
+
|
|
144
|
+
buffer = String.new(capacity: VERIFY_CHUNK_BYTES)
|
|
145
|
+
digest << buffer while io.read(VERIFY_CHUNK_BYTES, buffer)
|
|
146
|
+
digest.digest
|
|
131
147
|
end
|
|
132
148
|
|
|
133
149
|
def binary_string(capacity = nil)
|
|
@@ -280,10 +296,5 @@ module StaticEmbeddings
|
|
|
280
296
|
buffer[offset, 8] = [value & 0xFFFFFFFF, value >> 32].pack("V2")
|
|
281
297
|
end
|
|
282
298
|
|
|
283
|
-
def checksum_for_verify(data)
|
|
284
|
-
zeroed = data.dup
|
|
285
|
-
zeroed[CHECKSUM_OFFSET, CHECKSUM_SIZE] = "\0".b * CHECKSUM_SIZE
|
|
286
|
-
Digest::SHA256.digest(zeroed)
|
|
287
|
-
end
|
|
288
299
|
end
|
|
289
300
|
end
|
data/tools/benchmark.rb
CHANGED
|
@@ -12,8 +12,11 @@ CORPUS = (1..5_000).map do |i|
|
|
|
12
12
|
"локальный поиск по тексту номер #{i} hello world static embedding vector search"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
stats = CORPUS.map { |t| model.embed_with_stats(t) }
|
|
16
|
+
tokens = stats.sum { |s| s[:token_count] }
|
|
17
|
+
truncated = stats.count { |s| s[:truncated] }
|
|
18
|
+
logical_bytes = CORPUS.sum(&:bytesize)
|
|
19
|
+
processed_bytes = truncated.zero? ? logical_bytes : nil
|
|
17
20
|
|
|
18
21
|
def timed(label, iterations)
|
|
19
22
|
elapsed = Benchmark.realtime { iterations.times { yield } }
|
|
@@ -28,11 +31,17 @@ per_token_ns = (batch1 / tokens) * 1e9
|
|
|
28
31
|
per_token_per_100dim = per_token_ns / (model.dim / 100.0)
|
|
29
32
|
|
|
30
33
|
puts "model #{model.model_id} dim=#{model.dim} vocab=#{model.vocab_size}"
|
|
31
|
-
puts "corpus #{CORPUS.length} texts, #{tokens} tokens, #{
|
|
34
|
+
puts "corpus #{CORPUS.length} texts, #{tokens} tokens, #{logical_bytes} logical bytes"
|
|
35
|
+
puts "truncation #{truncated} of #{CORPUS.length} texts truncated at max_tokens=#{model.max_tokens}"
|
|
32
36
|
puts
|
|
33
37
|
puts "single embed #{((single / 2_000) * 1e6).round(1)} us/call"
|
|
34
38
|
puts "batch #{(CORPUS.length / batch1).round} texts/s, #{(tokens / batch1).round} tokens/s"
|
|
35
|
-
|
|
39
|
+
if processed_bytes
|
|
40
|
+
puts "tokenize only #{((tok_only / processed_bytes) * 1e9).round(1)} ns/processed byte"
|
|
41
|
+
else
|
|
42
|
+
puts "tokenize only #{(tok_only * 1e3).round(1)} ms total (no ns/byte: truncation makes"
|
|
43
|
+
puts " processed bytes smaller than the #{logical_bytes} logical bytes)"
|
|
44
|
+
end
|
|
36
45
|
puts
|
|
37
46
|
puts "normalised #{per_token_ns.round(1)} ns/token"
|
|
38
47
|
puts " #{per_token_per_100dim.round(1)} ns/token/100dim"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: static_embeddings
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Roman Haydarov
|
|
@@ -85,10 +85,13 @@ files:
|
|
|
85
85
|
- docs/PERFORMANCE.md
|
|
86
86
|
- exe/static_embeddings
|
|
87
87
|
- ext/static_embeddings/extconf.rb
|
|
88
|
+
- ext/static_embeddings/se_alloc_stats.c
|
|
88
89
|
- ext/static_embeddings/se_embed.c
|
|
90
|
+
- ext/static_embeddings/se_f16.c
|
|
89
91
|
- ext/static_embeddings/se_format.c
|
|
90
92
|
- ext/static_embeddings/se_internal.h
|
|
91
93
|
- ext/static_embeddings/se_tokenizer.c
|
|
94
|
+
- ext/static_embeddings/se_topk.c
|
|
92
95
|
- ext/static_embeddings/se_unicode.c
|
|
93
96
|
- ext/static_embeddings/static_embeddings.c
|
|
94
97
|
- lib/static_embeddings.rb
|