视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
tokenization-and-stopwords【文档与办公】Tokenize bm25s documents and queries with consistent vocabularies, stopwords, stemming, streaming, and tokenizer persistence.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Use this route when the task is to turn text into bm25s token IDs or token strings, keep a corpus/query vocabulary aligned, configure stopwords or stemming, stream a large input, or persist tokenizer state. Keep BM25 indexing, retrieval, index-file persistence, and CLI search in their sibling routes.
bm25s.tokenize for a self-contained batch. It accepts one string or an iterable of strings and returns a Tokenized object by default.bm25s.tokenization.Tokenizer when corpus and query calls must share mutable vocabulary state, when a callable splitter is needed, or when streaming and vocab/stopword persistence are required.return_ids (module function) with return_as (class method). Details and signatures are in references/api-reference.md.import bm25s
corpus_tokens = bm25s.tokenize(
["A cat likes to purr", "A dog likes to play"],
stopwords="en",
show_progress=False,
)
assert hasattr(corpus_tokens, "ids") and hasattr(corpus_tokens, "vocab")
query_strings = bm25s.tokenize(
"cat purr", stopwords="en", return_ids=False, show_progress=False
)
return_ids=True returns Tokenized(ids=..., vocab=...); return_ids=False returns list-of-list strings. The module function builds a fresh vocabulary for each call, so IDs from separate calls are not a shared query vocabulary.
from bm25s.tokenization import Tokenizer
tok = Tokenizer(
lower=True,
splitter=r"(?u)\\b\\w\\w+\\b", # regex or callable
stopwords="en",
stemmer=None,
)
corpus_ids = tok.tokenize(
["A cat likes to purr", "A dog likes to play"],
update_vocab=True,
return_as="ids",
show_progress=False,
)
query_ids = tok.tokenize(
["cat purr", "unknown term"],
update_vocab=False,
return_as="ids",
show_progress=False,
)
query_text = tok.decode(query_ids)
Build the corpus vocabulary first. For ordinary retrieval queries, use update_vocab=False so unseen words are omitted rather than changing the indexed vocabulary. Use update_vocab="never" when even a known stem must not create a new surface-word mapping; this distinction matters with a stemmer.
lower=True, then split, stopword-filtered, and optionally stemmed. Custom stopword entries should normally already be lowercase.get_vocab_dict() is word -> id; with a stemmer it is stem -> stem_id.allow_empty=True; its empty-token sentinel is deliberately documented in the API reference because empty behavior differs from the module function.Tokenizer.tokenize(..., update_vocab="if_empty") updates only when word_to_id is empty. It is the class default. streaming_tokenize does not support this mode; choose True, False, or "never" there.return_as="stream" is lazy and cannot be decoded until consumed. length= is needed when a non-streaming call receives a one-shot generator.lower, splitter, stemmer, or other construction settings; recreate compatible settings before loading.See references/stemming-and-stopwords.md for language aliases and stemmer contracts, and references/streaming-and-parallelism.md for lazy and multiprocessing patterns.
allow_empty explicit in production recipes. At this revision, the module and class implement opposite-looking empty defaults: module bm25s.tokenize(..., allow_empty=True) leaves an empty document as [], while allow_empty=False inserts ""; the class inserts "" for an empty document when allow_empty=True and has an existing/created sentinel, while False yields [].update_vocab=False, an unknown non-stemmed word is omitted. If no known IDs remain, the result is usually []; an existing empty sentinel can make an empty class result [empty_id] when allow_empty=True.ValueError; pass None/False for no stopwords or pass a list.ValueError during construction. The module stemmer must expose stemWords or be callable on a token list; see the exact contracts in the references.from pathlib import Path
tok.save_vocab("tokenizer-state")
tok.save_stopwords("tokenizer-state")
# Recreate the same lower/splitter/stemmer configuration, then:
restored.load_vocab("tokenizer-state")
restored.load_stopwords("tokenizer-state")
Use the defaults vocab.tokenizer.json and stopwords.tokenizer.json, or explicit unique names. Never pass the BM25 index's vocab.index.json as vocab_name: save_vocab has no collision guard and can overwrite it. Run the bounded local check at scripts/tokenizer_persistence_smoke.py to verify a compatible state round trip without downloading a dataset.
Before handing token IDs to a retrieval workflow, record the tokenizer settings, confirm corpus and query use the same get_vocab_dict(), and choose allow_empty deliberately. Prefer Tokenized/to_tokenized_tuple when the vocabulary must travel with IDs. Use references/troubleshooting.md for failures involving optional PyStemmer, malformed callable outputs, one-shot streams, or persistence files.
Do not download BEIR/NQ data merely to validate tokenization. Use a tiny local fixture and show_progress=False; benchmark-scale multiprocessing is an opt-in adaptation described in the streaming reference.