CodeVetter · Repo Unpack · Extension points
openai/whisper
Extension is mostly class-substitution rather than plugin registration: the get_writer() dict is a mini-registry for output formats; TokenDecoder, LogitFilter, SequenceRanker, and Inference are abstract seams inside DecodingTask; new checkpoints plug in via _MODELS/_ALIGNMENT_HEADS or by path; DecodingOptions is the frozen config dataclass every knob flows through. There is no dynamic plugin discovery — all seams require editing source.
- Output formats: subclass ResultWriter (set `extension`, implement write_result) and add it to the `writers` dict in get_writer() — the CLI's --output_format choices list in transcribe.py must also be updated.
- Search strategies: implement TokenDecoder (reset/update/finalize) — GreedyDecoder and BeamSearchDecoder are the built-ins — and select it in DecodingTask.__init__ where `options.beam_size is not None` chooses between them.
- Logit-level policies: implement LogitFilter.apply(logits, tokens) and append to DecodingTask.logit_filters, currently populated with SuppressBlank, SuppressTokens, and ApplyTimestampRules.
- Reranking: SequenceRanker.rank(tokens, sum_logprobs) → indices; MaximumLikelihoodRanker (length-normalized or Google-NMT penalty) is the only implementation, assigned in DecodingTask.__init__.
- Inference backend: Inference defines logits() / rearrange_kv_cache() / cleanup_caching(); PyTorchInference implements it via KV-cache forward hooks — an alternative (e.g. compiled or batched backend) would subclass Inference and be wired in DecodingTask.__init__.
- New official models: add a CDN URL to _MODELS and a base85 gzip'd (n_layers × n_heads) mask to _ALIGNMENT_HEADS in __init__.py; unofficial/fine-tuned checkpoints work without changes by passing a file path to load_model.
- DecodingOptions is the single frozen config dataclass for a decode (task, language, temperature, beam/best_of, prompt/prefix, suppress_tokens, timestamps, fp16); transcribe() forwards **decode_options straight into DecodingOptions(**kwargs), so new CLI/API knobs route through it.
- Languages are table-driven via LANGUAGES and TO_LANGUAGE_CODE, but special tokens are baked into the .tiktoken vocab — new languages can't be added without retraining; only aliases are cheap to extend.
- Accelerator backends: timing.py dispatches CUDA vs CPU implementations by trying the triton path inside try/except — the established pattern for adding a new kernel backend to median_filter and dtw.
- Normalizers are composable: EnglishTextNormalizer wires an ignore_patterns regex, a replacers dict, EnglishNumberNormalizer, and EnglishSpellingNormalizer(json map) — a new locale would follow the same class shape and export through normalizers/__init__.py.