dol-rdt-zerogpu-random-verify / Tokenizer /docs /external_implementation_notes.md
GABIRI's picture
Include tokenizer package for full model import
56f291f verified
|
Raw
History Blame Contribute Delete
5.18 kB

A newer version of the Gradio SDK is available: 6.24.0

Upgrade

External Implementation Notes

Design principles distilled from open-source tokenizers and multimodal processors. We do not vendor code or weights; we record contracts and patterns that shape this repo's API.

HuggingFace tokenizers (tokenizers.Encoding)

  • Source: https://huggingface.co/docs/tokenizers/api/encoding
  • Encoding carries ids, tokens, offsets, attention_mask, special_tokens_mask, type_ids, word_ids, sequence_ids. We mirror this contract: DualTrackResult exposes input_ids, tokens, attention_mask, special_tokens_mask plus our routed track.
  • Special tokens carry offsets = (0, 0) to signal "synthetic, not from text". We use (-1, -1) instead for BOS/EOS to make detection unambiguous against zero-length real spans; placeholder tokens (image patches) reuse the source <image> span and surface image_index in metadata.
  • char_to_token / token_to_chars is feasible only when every token has a real character span. We document our offset contract (see offset_contract.md) so downstream layers can do the same lookups.

tiktoken

  • Source: https://github.com/openai/tiktoken
  • BPE state is split into mergeable_ranks + a separate special_tokens dict; specials are matched out-of-band (regex split before BPE). We do the same: vocab.SPECIAL_TOKENS is reserved in segment 0 and routed before language detection.
  • Rank-based BPE: merges are stored as (piece -> rank) and the lowest rank wins at each pair. Our MorphBPETrainer records merges in order and reconstructs ranks on load — the merge order is the rank.
  • Byte-level fallback is guaranteed reversible & lossless. We adopt the same invariant in generic_bpe.byte_fallback: any input byte sequence encodes to vocab tokens and decodes back to the exact bytes; emoji round-trip is tested.

SentencePiece

  • Source: https://github.com/google/sentencepiece
  • Trains directly from raw sentences; whitespace is a regular symbol (). We respect this: is reserved id 17, decoders treat it as a word boundary, and _strip_hf_boundary_markers normalizes /Ġ.
  • NFKC normalization is part of the tokenizer, not a pre-step the caller must remember. Our Rust normalize_to_nominal_unicode plays the same role for Mongolian and is wired in via the CLI bridge so training pipelines cannot skip it.
  • Vocabulary size is predetermined and the trainer optimizes inside that budget. Our MorphBPETrainer.train(vocab_size=...) stops at the target size and skips merges below min_pair_freq for stability.

LLaVA processor

  • Source: https://huggingface.co/docs/transformers/main/en/model_doc/llava
  • The processor expands a single <image> placeholder into N image tokens based on patch_size, image_seq_length, and num_additional_image_tokens (CLS). We mirror this with expand_image_placeholders_by_sizes driven by image_patch_count.
  • The processor validates that the text contains the right number of image placeholders for the supplied images. We raise ValueError when image_sizes length disagrees with <image> count.
  • Image embeddings are merged into the LM after tokenization using the image-token positions. We therefore must return image_token_spans as input_ids-index ranges (not char ranges) so the model layer can locate the slot.

Qwen2-VL processor

  • Source: https://huggingface.co/docs/transformers/main/en/model_doc/qwen2_vl
  • Vision tokens are bracketed by explicit start/end markers (<|vision_start|> / <|vision_end|>); the count between them depends on image_grid_thw. We adopt the same triple (<image_start>/<image_patch>*N/<image_end>) and document image_token_spans = (start_index, end_index) as the inclusive token range covering all three.
  • Video is handled with the same scheme plus a temporal patch factor. Our video_patch_count(num_frames, w, h, patch_size, temporal_patch_size, merge_size) matches the formula ceil(num_frames/temporal_patch_size) * (w/patch_size/merge_size) * (h/patch_size/merge_size).
  • Dynamic resolution: the number of vision tokens is data-dependent. Processors must compute counts per-sample, not at config time. Our MultimodalProcessor.__call__ accepts per-call image_sizes / video_sizes rather than baking patch counts into the tokenizer.

vLLM multimodal processing

  • Source: https://docs.vllm.ai/en/latest/features/multimodal_inputs.html
  • vLLM enforces that the number of image placeholders in the prompt equals the number of supplied images (and exposes limit_mm_per_prompt). We validate the same invariant in the processor and surface a clear ValueError.
  • The multi-modal data dict is keyed by modality ("image", "video") and accepts lists for batched inputs. Our processor accepts images=[...] / videos=[...] in the same shape so future vLLM-style serving is a thin wrapper.
  • Allowed-media-domains and redirect controls are a security primitive, not a tokenizer concern. We note this for the future pipeline layer: the tokenizer must never fetch remote bytes itself; callers preload PIL images / bytes.