Files
6krrt/requirements-encoder.txt
adlee-was-taken 4c6798fc35 feat(classifier): configurable backend -- local_llm / cloud_llm / local_encoder
Foundation for a selectable classifier primary, generalizing "which
implementation answers a classification request" into config rather than
always assuming the local Ollama model:

- classifier.mode (default local_llm, unchanged behavior) plus
  cloud_primary / cloud_primary_auto for cloud_llm and an encoder block for
  local_encoder. Two new RouterConfig validators reject an incomplete
  combination at load time -- cloud_llm with neither/both primaries set,
  local_encoder with no encoder block -- the same model_validator(mode=
  "after") pattern this project already uses elsewhere.

- routing.cheapest_classifier_candidate: the "auto_classifier" resolver.
  Reuses select_candidates + estimated_cost -- the same functions real
  dispatch ranking uses -- rather than a second cost model, priced for the
  classifier's own short-prompt/short-completion call shape (500/50 tokens,
  cache_rate 0) instead of the task's. required_tier=1 is a floor, not a
  ceiling, so a tier-3 model can still win on price -- a test pins this
  after an initial wrong assumption in the test itself.

- local_encoder.py: zero-shot category classification via a non-generative
  encoder (default MoritzLaurer/deberta-v3-base-zeroshot-v2). Structurally
  immune to the one failure mode that has cost this project two prior
  classifier generations (docs/local-models.md): a generative model
  spending its budget on an unbounded reasoning trace. Zero-shot rather
  than fine-tuned, deliberately -- this router never stores raw task text
  anywhere, so there is no training corpus without a new, separate opt-in
  capture feature (scoped, not built). transformers/torch imported lazily
  inside the function, the same rule tui.py already follows for textual, so
  a deployment that never selects this mode needs neither installed.
  requirements-encoder.txt keeps them out of the main, pinned requirements
  file.

Every test here was run against unmodified main first and observed to
fail for the right reason before this commit made it pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
2026-09-05 23:53:44 -04:00

725 B