Skip to content

feat: open by default — scripts default to local Ollama, not Anthropic - #18

Open
mattekudacy wants to merge 3 commits into
mainfrom
claude/serene-ritchie-g11dsf
Open

mattekudacy wants to merge 3 commits into
mainfrom
claude/serene-ritchie-g11dsf

Conversation

@mattekudacy

Copy link
Copy Markdown
Owner

Ownership. This PR was opened directly by an automated Claude Code session working in
this repo — see the "Exception" paragraph in this template. The Co-Authored-By: trailer and
session-link footer on the commit and this description are required by the platform this
session runs on and can't be suppressed from inside the PR; nothing else here is exempt, and a
human still decides whether to merge it.

What does this change and why?

Addresses feedback that this project shouldn't default to depending on a paid Anthropic key —
it should be open source by default, like Ollama.

The starting truth was already good: RulesClassifier (the actual default classifier=)
makes zero API calls to any vendor, and LLMClassifier was always backend-agnostic
(Ollama/Groq/OpenAI via base_url, or Anthropic without it). What wasn't open by default was
the framing: every scripts/*_accuracy.py measurement harness fell back to an Anthropic
model and required ANTHROPIC_API_KEY when nothing else was configured, and the
README/docs/concepts/classifiers.md/triage/classifier/llm.py docstrings all presented
Anthropic first, labeled "(default)."

Concrete changes:

  • scripts/llm_classifier_accuracy.py, hybrid_ambiguity_accuracy.py,
    mast_mode_pilot_accuracy.py each gain a _resolve_backend() helper: an explicit
    TRIAGE_LLM_BASE_URL always wins (unchanged), an explicit Anthropic credential with no
    base_url still routes to Anthropic (unchanged — nothing breaks for an existing caller who set
    one), and with nothing configured at all, they now default to local Ollama
    (http://localhost:11434/v1, llama3.2) instead of Anthropic.
  • triage/classifier/llm.py: LLMClassifier.__init__ behavior is unchanged — it already
    raises ValueError naming all backend options rather than silently picking one, which is the
    more honest design than defaulting to either vendor. Only the docstring and error-message
    ordering changed (Ollama listed first, noted as needing no account or key).
  • docs/concepts/classifiers.md: new "Open by default" note; OpenAI-compatible section moved
    ahead of Anthropic's.
  • README.md: classifier examples and the env-var configuration block now lead with Ollama.
  • CLAUDE.md: Optional Extras table gains the previously-missing [openai] row ahead of
    [anthropic]; new design-decision entry recording the rationale.
  • scripts/README.md: Benchmarks table and bash examples updated — "requires an LLM API key"
    (implying a paid vendor) corrected to "requires an LLM backend" with Ollama shown as the
    no-key default path.

No triage/ core behavior changed — this is a default/framing correction in scripts and docs,
not an API change.

Related issue

None


Type of change

  • New feature (a backend-resolution default flip in 3 scripts; LLMClassifier itself
    unchanged)
  • Documentation

Checklist

  • No AI-attribution trailers or badges anywhere in this PR — commit messages and this
    description are clean. I am the author and I am responsible for this change.
    (N/A — see the "Ownership" exception above.)
  • pytest tests/ -x --tb=short passes locally (816 passed, unchanged — no new test surface,
    since LLMClassifier's public behavior didn't change)
  • ruff check ., ruff format --check ., and mypy triage/ --strict are all clean
  • No new imports of openai/anthropic/langchain/langgraph/opentelemetry/etc. inside
    triage/ core — the only triage/ file touched (triage/classifier/llm.py) is a
    docstring/error-message reorder, zero new imports or behavior change
  • Docs updated: docs/concepts/classifiers.md, README.md, CLAUDE.md, scripts/README.md,
    CHANGELOG.md ([Unreleased]### Changed)
  • N/A — no new FailureType or RecoveryAction added

If this touches rules.py or an error corpus — N/A, no rules.py or corpus file touched.


Anything reviewers should look at closely?

_resolve_backend() (duplicated in all three scripts per this repo's self-contained-script
convention) is the load-bearing piece — worth checking its precedence order against your own
setup: explicit TRIAGE_LLM_BASE_URL > explicit Anthropic credential (no base_url) > local
Ollama default. Verified all four cases (nothing set, Anthropic key set, custom base_url set,
--model override) manually for each script since none of this is covered by the existing test
suite (these are opt-in scripts outside triage/, not imported by any test).

🤖 Generated with Claude Code

https://claude.ai/code/session_01M4WNEkbnKSx9mTg5Q1jX39


Generated by Claude Code

Addresses feedback that this project shouldn't default to depending on a
paid Anthropic key. The starting truth was already good — RulesClassifier
(the actual default classifier=) makes zero API calls to any vendor, and
LLMClassifier was always backend-agnostic (Ollama/Groq/OpenAI via base_url,
or Anthropic without it) — but the *framing* wasn't: every scripts/*_accuracy.py
harness fell back to an Anthropic model and required ANTHROPIC_API_KEY when
nothing else was configured, and the README/docs/llm.py docstrings all
presented Anthropic first, labeled "(default)".

Concrete changes:

- scripts/llm_classifier_accuracy.py, hybrid_ambiguity_accuracy.py,
  mast_mode_pilot_accuracy.py each gain a _resolve_backend() helper: an
  explicit TRIAGE_LLM_BASE_URL always wins (unchanged), an explicit
  Anthropic credential with no base_url still routes to Anthropic
  (unchanged — nothing breaks for an existing caller who set one), and with
  NOTHING configured at all, they now default to local Ollama
  (http://localhost:11434/v1, llama3.2) instead of Anthropic. Verified the
  resolution logic against all four cases (nothing set, Anthropic key set,
  custom base_url set, --model override) for each script.

- triage/classifier/llm.py: LLMClassifier.__init__ behavior is UNCHANGED —
  it already raises ValueError naming all backend options rather than
  silently picking one, which is the more honest design than defaulting to
  either vendor. Only the docstring and error-message ordering changed
  (Ollama listed first, noted as needing no account or key).

- docs/concepts/classifiers.md: new "Open by default" note; OpenAI-compatible
  section moved ahead of Anthropic's.

- README.md: classifier examples and the env-var configuration block now
  lead with Ollama; installation section shows the open path first.

- CLAUDE.md: Optional Extras table gains the previously-missing [openai]
  row ahead of [anthropic]; new design-decision entry recording the
  rationale so this isn't re-litigated or silently reverted later.

- scripts/README.md: Benchmarks table and bash examples updated — "requires
  an LLM API key" (implying a paid vendor) corrected to "requires an LLM
  backend" with Ollama shown as the no-key default path.

No triage/ core behavior changed — this is a default/framing correction in
scripts and docs, not an API change. Verified: ruff check, ruff format
--check, pytest (816 passed, unchanged), mypy --strict, mkdocs build
--strict all clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M4WNEkbnKSx9mTg5Q1jX39
mypy triage/ --strict failed in CI with a hard parse error, unrelated to
this branch's diff:

  numpy/__init__.pyi:737: error: Type statement is only supported in
  Python 3.12 and greater  [syntax]
  Found 1 error in 1 file (errors prevented further checking)

Root cause, confirmed by reproducing exactly (Python 3.13 venv, matching
CI's numpy==2.5.3 and mypy 2.3.1) and tracing the import chain with
`mypy --verbose`: a separate, already-merged PR added matplotlib/seaborn to
the dev extra for scripts/gen_readme_charts.py, which pulled in a numpy
release whose .pyi stub uses a PEP 695 `type` statement (valid only on
Python 3.12+) — a hard syntax error against this project's
[tool.mypy] python_version = "3.10" target. mypy reaches it via
langchain_core/embeddings/fake.py (real, non-stub source triage/adapters/
langchain.py's import chain leads to), which does `import numpy` directly.
ignore_missing_imports (already set for langchain_core/etc.) only suppresses
"stub not found" errors — it doesn't stop mypy from parsing a stub it does
find, and a numpy-specific override with follow_imports = "skip" (tried
first) did not work either: the parse happens before mypy consults it.

Fixed by moving follow_imports = "skip" onto the override covering
anthropic/openai/aiosqlite/redis/langgraph/langchain/langchain_core:
triage/ only calls these libraries' public APIs, so treating each as opaque
Any without mypy recursing into its internal source is safe and sidesteps
whatever transitive import chain a future dependency bump reaches next.
opentelemetry deliberately stays on a separate override (ignore_missing_
imports only, no skip) — triage/observability/otel_ingest.py relies on mypy
actually resolving opentelemetry.trace.StatusCode's real type, and applying
skip there breaks a real strict-mode check (turns it into Any, trips
warn_return_any) — found while testing this fix, not hypothetical.

triage/ itself was never at fault; this branch's own diff didn't touch
pyproject.toml before this commit. Fixing it here because main is currently
red from the same cause and no other fix exists yet to port.

Verified against a disposable Python 3.13 venv built to match CI's exact
dependency versions: reproduces the original failure without this fix,
clean with it. Also verified: ruff check, ruff format --check, pytest
(816 passed) on both that venv and this session's own Python 3.11
environment, mypy --strict, mkdocs build --strict.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M4WNEkbnKSx9mTg5Q1jX39

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants