token-align 0.1.0

Maps overlapping tokens and character positions between tokenized texts
Documentation
  • Coverage
  • 100%
    11 out of 11 items documented3 out of 8 items with examples
  • Size
  • Source code size: 302.1 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.5 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 2s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • hey-jj/token-align
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hey-jj

token-align

token-align maps overlaps between two token sequences that represent the same text. It also maps Unicode scalar positions between two strings. The library supports no_std programs with an allocator and has no runtime dependencies.

The default comparison form removes common subword markers, ignores fixed vocabulary control tokens, applies Unicode 17.0.0 compatibility decomposition, and uses simple lowercase mappings. A custom normalizer can replace those rules.

Token alignment

use token_align::get_alignments;

let words = ["untouchable"];
let pieces = ["un", "##touch", "##able"];
let (word_to_piece, piece_to_word) = get_alignments(&words, &pieces);

assert_eq!(word_to_piece, vec![vec![0, 1, 2]]);
assert_eq!(piece_to_word, vec![vec![0], vec![0], vec![0]]);

Each outer index names an input token. Its inner list contains the overlapping indices on the other side. A token without a matched character has an empty list.

Character mapping

use token_align::get_charmap;

let (left, right) = get_charmap("Å", "A");
assert_eq!(left, vec![vec![0]]);
assert_eq!(right, vec![vec![0]]);

Character indices count Unicode scalar values.

Custom comparison forms

Implement Normalizer or pass a closure to get_alignments_with. The output string is reusable scratch space and is empty at the start of each call.

use token_align::get_alignments_with;

let strip_suffix = |token: &str, out: &mut String| {
    out.push_str(token.strip_suffix("@@").unwrap_or(token));
};

let whole = ["hashtag"];
let pieces = ["hash@@", "tag"];
let (whole_to_piece, _) = get_alignments_with(&whole, &pieces, &strip_suffix);
assert_eq!(whole_to_piece, vec![vec![0, 1]]);

Exact copies tokens without case conversion, marker removal, or Unicode decomposition.

Complexity

Equal normalized unit streams use linear time. Different streams use a linear-space Myers comparison over unit keys. Its time is proportional to the combined length times the edit distance, with quadratic worst-case time for unrelated inputs.

The default rules do not decode byte-level encodings of non-ASCII text. Supply a normalizer when tokens require that decoding. The comparison also keeps simple lowercase behavior, so mappings such as ß to ss are outside its scope.

License

The implementation is licensed under the MIT License. The generated Unicode 17.0.0 tables are also governed by the Unicode License v3. See LICENSE and LICENSE-UNICODE.