Skip to content

Commit 26d8dcc

Browse files
committed
Initial commit
0 parents  commit 26d8dcc

16 files changed

Lines changed: 1679 additions & 0 deletions

File tree

.formatter.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Used by "mix format"
2+
[
3+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
4+
]

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
pull_request:
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Elixir
18+
uses: erlef/setup-beam@v1
19+
with:
20+
elixir-version: 1.18.4
21+
otp-version: 27.0
22+
23+
- name: Install dependencies
24+
run: |
25+
mix deps.get
26+
mix deps.compile
27+
28+
- name: Check formatting
29+
run: mix format --check-formatted
30+
31+
- name: Run tests
32+
run: mix test --exclude oracle
33+
34+
- name: Run dialyzer
35+
run: mix dialyzer

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where third-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# If the VM crashes, it generates a dump, let's ignore it too.
14+
erl_crash.dump
15+
16+
# Also ignore archive artifacts (built via "mix archive.build").
17+
*.ez
18+
19+
# Ignore package tarball (built via "mix hex.build").
20+
tiktoken_ex-*.tar
21+
22+
# Temporary files, for example, from tests.
23+
/tmp/
24+
25+
# Downloaded Kimi tokenizer oracle files (HF artifacts, venv, etc.)
26+
/oracle/kimi/
27+
/oracle/.venv/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 North-Shore-AI
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<div align="center">
2+
<img src="assets/tiktoken_ex.svg" width="400" alt="TiktokenEx Logo" />
3+
</div>
4+
5+
# TiktokenEx
6+
7+
**Pure Elixir TikToken-style byte-level BPE tokenizer (Kimi K2 compatible).**
8+
9+
[![CI](https://github.com/North-Shore-AI/tiktoken_ex/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/North-Shore-AI/tiktoken_ex/actions/workflows/ci.yml)
10+
[![Hex.pm](https://img.shields.io/hexpm/v/tiktoken_ex.svg)](https://hex.pm/packages/tiktoken_ex)
11+
[![Docs](https://img.shields.io/badge/docs-hexdocs.pm-blue.svg)](https://hexdocs.pm/tiktoken_ex)
12+
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
13+
14+
TiktokenEx is a small, dependency-light implementation of the core TikToken
15+
idea:
16+
17+
- Split text with a Unicode-aware regex (`pat_str`)
18+
- Encode pieces with byte-pair encoding (BPE) using `mergeable_ranks`
19+
- Optionally recognize special tokens (e.g. `<|im_end|>`)
20+
21+
It’s focused on matching the behavior of MoonshotAI’s **Kimi K2** tokenizers
22+
that ship a `tiktoken.model` file and a TikToken-compatible `pat_str`.
23+
24+
## Installation
25+
26+
Add `tiktoken_ex` to your dependencies:
27+
28+
```elixir
29+
def deps do
30+
[
31+
{:tiktoken_ex, "~> 0.1.0"}
32+
]
33+
end
34+
```
35+
36+
## Usage
37+
38+
### Build an encoding directly
39+
40+
```elixir
41+
alias TiktokenEx.Encoding
42+
43+
mergeable_ranks = %{
44+
"He" => 0,
45+
"ll" => 1,
46+
"llo" => 2,
47+
"H" => 10,
48+
"e" => 11,
49+
"l" => 12,
50+
"o" => 13
51+
}
52+
53+
{:ok, enc} = Encoding.new(pat_str: ".+", mergeable_ranks: mergeable_ranks)
54+
55+
{:ok, ids} = Encoding.encode(enc, "Hello")
56+
{:ok, text} = Encoding.decode(enc, ids)
57+
```
58+
59+
### Load a Kimi K2 encoding from local HuggingFace artifacts
60+
61+
Kimi provides:
62+
63+
- `tiktoken.model` (mergeable ranks)
64+
- `tokenizer_config.json` (special tokens, etc)
65+
66+
```elixir
67+
alias TiktokenEx.{Encoding, Kimi}
68+
69+
{:ok, enc} =
70+
Kimi.from_hf_files(
71+
tiktoken_model_path: "/path/to/tiktoken.model",
72+
tokenizer_config_path: "/path/to/tokenizer_config.json"
73+
)
74+
75+
{:ok, ids} = Encoding.encode(enc, "Say hi")
76+
{:ok, decoded} = Encoding.decode(enc, ids)
77+
```
78+
79+
### Special tokens
80+
81+
Special tokens are recognized by default. To treat them as plain text:
82+
83+
```elixir
84+
{:ok, ids} = TiktokenEx.Encoding.encode(enc, "<|im_end|>", allow_special_tokens: false)
85+
```
86+
87+
### Regex compatibility note
88+
89+
Kimi’s upstream `pat_str` uses character-class intersections (`&&`), which are
90+
not supported by Erlang’s PCRE engine. `TiktokenEx.Kimi.pat_str/0` provides a
91+
PCRE-compatible translation.
92+
93+
## Development
94+
95+
- Run tests: `mix test`
96+
- Run oracle parity tests (downloads HF artifacts): `mix test --include oracle`
97+
- Run dialyzer: `mix dialyzer`
98+
99+
## License
100+
101+
MIT © 2025 North-Shore-AI

assets/tiktoken_ex.svg

Lines changed: 156 additions & 0 deletions
Loading

lib/tiktoken_ex.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
defmodule TiktokenEx do
2+
@moduledoc """
3+
Pure-Elixir implementation of TikToken-style byte-level BPE encoding.
4+
5+
This project targets the subset needed to match MoonshotAI Kimi tokenizers
6+
that ship a `tiktoken.model` file and a TikToken-compatible `pat_str`.
7+
"""
8+
end

0 commit comments

Comments
 (0)