Spaces:
Running on Zero
Running on Zero
Download bpe.lua from jeorgexyz/lua-agent-lab: direct link, hf CLI and curl.
- Browser
- Download file 3.22 kB
-
https://huggingface.co/spaces/jeorgexyz/lua-agent-lab/resolve/main/bpe.lua
- Command line
-
hf download hf://spaces/jeorgexyz/lua-agent-lab/bpe.lua
-
curl -L -o bpe.lua https://huggingface.co/spaces/jeorgexyz/lua-agent-lab/resolve/main/bpe.lua
3.22 kB
| -- bpe.lua - Load lua-llama's BPE tokenizer without loading a model. | |
| -- | |
| -- Exact token counts need the real tokenizer, and the real tokenizer is a | |
| -- 433KB file. But repo 1's Tokenizer.new(path, vocab_size) takes the vocab | |
| -- size as an argument, and the only place the rest of this repo had one was | |
| -- model.config.vocab_size -- so counting tokens meant loading a 60MB | |
| -- checkpoint and waiting ~17s for it. | |
| -- | |
| -- That coupling is incidental: tokenizer.bin describes its own length, you | |
| -- just have to walk it. This scans the file to derive the entry count, then | |
| -- hands that to repo 1's loader. The replay and http backends get exact | |
| -- counts with no model at all. | |
| -- | |
| -- Format (llama2.c): | |
| -- int32 max_token_length | |
| -- repeated: float32 score, int32 len, len bytes | |
| local bpe = {} | |
| -- Walk the file and count entries. ~433KB and a few thousand reads, so it | |
| -- costs milliseconds -- against 17s and 60MB for the checkpoint it replaces. | |
| function bpe.count_entries(path) | |
| local fh, err = io.open(path, "rb") | |
| if not fh then return nil, tostring(err) end | |
| local header = fh:read(4) | |
| if not header or #header ~= 4 then | |
| fh:close() | |
| return nil, "truncated header" | |
| end | |
| local n = 0 | |
| while true do | |
| local score = fh:read(4) | |
| if not score or #score < 4 then break end | |
| local len_bytes = fh:read(4) | |
| if not len_bytes or #len_bytes < 4 then | |
| fh:close() | |
| return nil, string.format("truncated length field at entry %d", n) | |
| end | |
| local len = string.unpack("<i4", len_bytes) | |
| if len < 0 or len > 1024 then | |
| fh:close() | |
| return nil, string.format("implausible token length %d at entry %d", len, n) | |
| end | |
| local tok = fh:read(len) | |
| if not tok or #tok ~= len then | |
| fh:close() | |
| return nil, string.format("truncated token body at entry %d", n) | |
| end | |
| n = n + 1 | |
| end | |
| fh:close() | |
| if n == 0 then return nil, "no tokens found" end | |
| return n | |
| end | |
| -- Returns tokenizer, vocab_size or nil, err. | |
| -- llama_path is where repo 1 lives, needed because its tokenizer module | |
| -- requires('utils') by bare name. | |
| function bpe.load(path, llama_path) | |
| local n, err = bpe.count_entries(path) | |
| if not n then return nil, err end | |
| local root = llama_path or "../lua_llama" | |
| package.path = root .. "/?.lua;" .. package.path | |
| local ok, Tokenizer = pcall(require, "tokenizer") | |
| if not ok then return nil, "cannot load lua-llama's tokenizer.lua: " .. tostring(Tokenizer) end | |
| -- Repo 1's loader prints as it goes; useful in its CLI, noise here. | |
| local real_print = print | |
| _G.print = function() end | |
| local loaded, tok = pcall(Tokenizer.new, path, n) | |
| _G.print = real_print | |
| if not loaded then return nil, tostring(tok) end | |
| return tok, n | |
| end | |
| -- The stand-in when no tokenizer file is available: roughly four characters | |
| -- per token. Good enough to exercise the eviction policies, and never | |
| -- reported as exact. | |
| function bpe.approximate() | |
| return { encode = function(_, s) | |
| local out = {} | |
| for k = 1, math.max(1, math.ceil(#s / 4)) do out[k] = k end | |
| return out | |
| end } | |
| end | |
| return bpe | |