Open-source project
sugarme/tokenizer avatar
sugarme/tokenizer

sugarme/tokenizer: HuggingFace Tokenizers Ported to Pure Go

NLP tokenizers written in Go language

334 stars68 forksGoApache-2.0

At a glance

What is it?
A pure Go implementation of the tokenizer pipeline that can load HuggingFace tokenizer.json files and encode text with offsets. It is aimed at Go services that want to avoid a Python sidecar, and its main constraint is that it is a reimplementation, not the reference library.
Who is it for?
Adopt sugarme/tokenizer when your inference stack is already Go and you need WordPiece, BPE or word-level encoding from an existing HuggingFace tokenizer.json without a Python process. Do not adopt it if your pipeline depends on tokenizer behaviours this port does not implement, or if you need the reference Rust implementation's exact parity guarantees.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 112 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap sugarme/tokenizer fills for Go services

Most NLP inference in production starts with a Python process, because that is where HuggingFace Tokenizers lives. If the model itself runs in Go, the tokenizer becomes the awkward part: you either shell out to Python, run a separate service, or reimplement the tokenizer yourself and get the edge cases wrong. sugarme/tokenizer exists to remove that boundary. The README describes it as a pure Go package to facilitate applying NLP models in Go, and it is explicit that it is heavily inspired by and based on HuggingFace Tokenizers. The audience is narrow and identifiable: Go engineers who already have a model runtime in Go (the project positions itself alongside sugarme/transformer and sugarme/gotch) and who want text encoding to happen in the same process and the same language. If your inference is in Python, this library offers you nothing.

Four sub-packages and three tokenizer models

The architecture is a pipeline, and the README names its stages directly. The package is built in modules located in sub-packages: Normalizer, Pretokenizer, Tokenizer, and Post-processing. Text enters at the normalizer, is split by the pretokenizer, mapped to ids by the tokenizer model, and then adjusted by post-processing (which is where special tokens and attention-mask style padding conventions typically get applied). Three model types are implemented, and the README marks all three as done in its checklist: word level, WordPiece, and Byte Pair Encoding. That is the same decomposition HuggingFace Tokenizers uses, which is why a tokenizer.json file maps onto it at all. The practical consequence is that the library is configuration-driven rather than hardcoded to BERT: the behaviour you get depends on what the loaded file specifies for each stage.

Loading a pretrained tokenizer.json and encoding a sentence

The README gives one worked example, and it is worth reading closely because it shows both the API shape and the caching behaviour. You call tokenizer.CachedPath with a model name and the filename tokenizer.json to download and cache the file, then pretrained.FromFile to build the tokenizer. The README notes that any model with tokenizer.json available can be used, and names tiiuae/falcon-7b as an example alongside the bert-base-uncased case in the code. Encoding is a single call, tk.EncodeSingle(sentence), which returns a result carrying Tokens and Offsets. The documented output for the sentence in the example is the WordPiece split of "Gophers" into "go", "##pher", "##s", and offsets as byte ranges into the original string, for example [4 6] for "go" and [29 35] for "[MASK]". Those offsets are the part that matters for anything downstream of classification: span extraction, highlighting, and alignment back to source text all depend on them being correct. The README also states that all models can be loaded from files manually if you do not want the pretrained helper, with pkg.go.dev as the reference for that path.

Training new models versus loading existing ones

The README claims the library can be used for both training new models from scratch and fine-tuning existing models, and points to the example directory for detail. That is a broader claim than the basic example demonstrates. The example only covers the load-and-encode path, and the getting started section defers entirely to pkg.go.dev for APIs rather than walking through a training loop. So the honest reading is: the encode path is documented with a concrete input and output, and the training path is asserted with a pointer to examples you would have to read in the repository. If training a tokenizer from scratch in Go is your reason for looking at this project, treat the example directory as the thing to evaluate, not the README prose.

Where this port is the wrong tool

This is a reimplementation of another project's format and semantics, and that is the central risk. HuggingFace Tokenizers is the reference; sugarme/tokenizer is a Go package that is inspired by and based on it. Nothing in the supplied material makes a parity claim, and no conformance suite or comparison against the reference outputs is described. The failure mode is quiet: a normalizer rule, a pre-tokenizer regex, or a post-processor template that the Go implementation handles differently from the reference produces different token ids, and a model fed those ids returns plausible-looking but wrong output. There is no error to catch. A second limitation is documentation depth. The README's getting started section is one line pointing at pkg.go.dev, and the only complete code sample is the encode example. Configuration keys for the four pipeline stages are not enumerated in the README at all, so you are reading generated API docs and the source to learn what a given tokenizer.json field maps to. Finally, this is a single-maintainer project under the sugarme namespace with a v0.x version history, which is a reasonable thing to weigh when it sits on the critical path of a serving stack.

The alternative: keep the tokenizer in Python

The realistic alternative is not another Go tokenizer, it is not moving the tokenizer at all. HuggingFace Tokenizers, the Rust implementation with Python bindings, is the thing this project is based on, and it is the reference for the tokenizer.json format. The difference in approach is not performance, it is who owns correctness. With the Python binding you get the reference implementation's behaviour by definition, including every normalizer and post-processor variant, and your risk shifts to process management: a sidecar service, a subprocess call, or an IPC boundary between your Go inference and your Python encoding. sugarme/tokenizer trades that operational boundary for a reimplementation you have to validate yourself. Neither choice is free. If your tokenizer configuration is plain WordPiece with no exotic normalizer, the Go route is small and self-contained. If your tokenizer.json uses something the port does not cover, the Python sidecar is the lower-risk answer and the extra hop is the price.

Licence and upgrade cost

The project is Apache-2.0 licensed, and the README states this plainly. Apache-2.0 includes an explicit patent grant and requires that you preserve notices and state changes, which matters if you vendor the code or modify it. That is the licence text, not advice on your situation; if you are redistributing a modified copy, have someone qualified read the terms. On upgrade cost, the material shows one release, v0.3.0, dated 2025-09-18, with the repository's last push in May 2026. A v0.x version number means the API carries no stability promise, so pinning a specific tag in go.mod is the practical posture rather than tracking master. The deeper upgrade risk is not the Go API, it is the tokenizer.json files you feed it: a model you pull from HuggingFace may use pipeline configuration added after this port was written, and that will surface as a parse error or, worse, as silently different tokens. Re-running your own encode fixtures against any new tag is the check that catches it.

Editorial conclusion

Adopt sugarme/tokenizer when your inference stack is already Go and you need WordPiece, BPE or word-level encoding from an existing HuggingFace tokenizer.json without a Python process. Do not adopt it if your pipeline depends on tokenizer behaviours this port does not implement, or if you need the reference Rust implementation's exact parity guarantees. Before committing, verify three things against your own model: that pretrained.CachedPath resolves and caches your specific tokenizer.json, that EncodeSingle returns the tokens and offsets your downstream model expects, and that the normalizer and post-processor configuration in your file is one this library actually parses.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. sugarme/tokenizer on GitHub
Community notes

Community notes