sentencepiece clib AI

SentencePiece tokenizer. Subword tokenization, encode/decode, BPE/Unigram, LLM-compatible.

ppm install sentencepiece

Overview

SentencePiece is Google's language-independent subword tokenizer. Used by LLaMA, Gemma, T5, ALBERT, and most production LLMs. Implements BPE and Unigram language model tokenization. A .model file (distributed with each LLM) is required — it defines the vocabulary.

CLib package — model file required

Ubuntu/Debian: sudo apt install libsentencepiece-dev
Model files ship with each LLM (e.g. tokenizer.model in LLaMA weights)

Encode & Decode

uses sentencepiece;

{ load tokenizer model }
var sp := LoadModel('/models/llama/tokenizer.model');

{ encode text to token IDs }
var ids := Encode(sp, 'Hello, world! How are you?');
var i: Integer;
for i := 0 to Length(ids) - 1 do
  Write(ids[i], ' ');   { 1 15043 29892 3186 29991 1128 526 366 29973 }
WriteLn;

{ decode back to text }
var text := Decode(sp, ids);
WriteLn(text);   { Hello, world! How are you? }

FreeModel(sp);

Pieces (Subword Tokens)

uses sentencepiece;

var sp := LoadModel('/models/tokenizer.model');

{ get token strings instead of IDs }
var pieces := EncodeAsPieces(sp, 'tokenization is powerful');
var i: Integer;
for i := 0 to Length(pieces) - 1 do
  Write('[', pieces[i], '] ');
{ [_token] [ization] [_is] [_power] [ful] }
WriteLn;

{ full result: IDs + pieces + byte offsets }
var result := EncodeEx(sp, 'Hello world');
for i := 0 to Length(result.Ids) - 1 do
  WriteLn(result.Ids[i], #9, result.Pieces[i], #9, 'offset:', result.Offsets[i]);

Special Tokens (BOS / EOS)

uses sentencepiece;

var sp     := LoadModel('/models/tokenizer.model');
var info   := GetModelInfo(sp);

WriteLn('Vocab size: ', info.VocabSize);
WriteLn('BOS id:     ', info.BOSId);
WriteLn('EOS id:     ', info.EOSId);

{ encode with BOS + EOS (required by many LLMs for prompts) }
var ids := EncodeWithSpecial(sp, 'Hello!', True, True);
{ [1, 15043, 29991, 2]  — 1=BOS, 2=EOS }

{ check if an ID is a special/control token }
WriteLn(IsControl(sp, info.BOSId));   { True }
WriteLn(IsControl(sp, 15043));        { False }

Token Counting & Budget

uses sentencepiece;

var sp := LoadModel('/models/tokenizer.model');

{ count tokens without materializing them — very fast }
var n := CountTokens(sp, longText);
WriteLn('Token count: ', n);

{ check if text fits within a limit (e.g. 4096 for LLaMA context) }
if FitsInBudget(sp, longText, 4096) then
  WriteLn('Fits in context window')
else begin
  { truncate to max tokens }
  var truncated := TruncateToTokens(sp, longText, 4000);
  WriteLn('Truncated to: ', CountTokens(sp, truncated), ' tokens');
end;

Vocabulary Lookup

uses sentencepiece;

var sp := LoadModel('/models/tokenizer.model');

{ ID to piece }
WriteLn(IdToPiece(sp, 15043));   { Hello }
WriteLn(GetPiece(sp, 1));        { <s>  (BOS) }

{ piece to ID }
var id := PieceToId(sp, 'world');
WriteLn(id);   { 3186 }

{ unknown pieces return -1 }
WriteLn(PieceToId(sp, 'xyzzyblorp'));   { -1 }

WriteLn('Vocab size: ', GetVocabSize(sp));

Batch Encoding

uses sentencepiece;

var sp := LoadModel('/models/tokenizer.model');

var texts: array of string;
SetLength(texts, 3);
texts[0] := 'The quick brown fox';
texts[1] := 'jumps over the lazy dog';
texts[2] := 'Hello world';

{ encode all at once — returns space-separated IDs per line }
var batch := EncodeBatch(sp, texts);
var i: Integer;
for i := 0 to Length(batch) - 1 do
  WriteLn('Line ', i, ': ', batch[i]);

Package Info

Version1.0.0
Typeclib
CategoryAI
Authorgustavo
AlgorithmsBPE, Unigram

API

  • LoadModel(path)
  • LoadModelBytes(data)
  • FreeModel(m)
  • Encode(m,text)
  • EncodeAsPieces(m,text)
  • EncodeEx(m,text)
  • EncodeWithSpecial(m,t,bos,eos)
  • EncodeBatch(m,texts)
  • Decode(m,ids)
  • IdToPiece(m,id)
  • DecodePieces(m,pieces)
  • GetVocabSize(m)
  • GetPiece(m,id)
  • PieceToId(m,piece)
  • IsControl(m,id)
  • IsUnknown(m,id)
  • CountTokens(m,text)
  • FitsInBudget(m,text,max)
  • TruncateToTokens(m,text,max)
  • GetModelInfo(m)
Used by

LLaMA 1/2/3, Gemma, T5, ALBERT, mT5, XLNet, and most Google/Meta LLMs. The .model file ships with model weights.