Goal: every endpoint and every Streamlit tab must work in a 2-minute
hackathon demo without requiring the demoer to fetch external data.
Code fixes:
- src/api/routes.py + src/agents/tools.py: fix two stale references —
bbb_model.load (not load_model) and bbb_model.predict_with_proba (not
predict_one); also corrects the agent-side default BBB artifact path
from .pkl to .joblib so the auto-resolve in adjust_drug_dose works.
- src/api/routes.py: replace hard-coded _AGENT_DEFAULT_MODEL = google/
gemini-2.0-flash-exp:free (now 404 on OpenRouter) with a fallback
chain probed at orchestrator-build time. Picks the first model that
returns a non-404/429 ping. Override via NEUROBRIDGE_AGENT_MODEL
(single id) or NEUROBRIDGE_AGENT_MODEL_CHAIN (csv).
- src/llm/explainer.py: prepend openai/gpt-oss-20b:free (verified 2026-
05-02) to the explainer fallback chain so /explain/* doesn't fall
back to the deterministic template when free-tier ids churn.
- src/frontend/app.py: drop the en…
feat(llm): user-question-driven prompt (language match + intent split)
The previous prompt forced every LLM call into "paper-style rationale"
mode, ignoring the user's actual question. Result: Turkish questions
got English paper-prose answers, casual greetings got SHAP rationales,
"what does 93% mean" got the same canned SHAP citation.
New prompt:
- Puts the user's question above the data, not below it.
- When a non-default question is supplied: instructs the model to
match the question's language, answer it directly, and reply
conversationally if the question is casual.
- When no question is supplied (default /explain caller): preserves
the original 2-4 sentence paper-style rationale behavior.
11/11 LLM unit tests pass; template path untouched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docs(llm): add probe-date + 429-policy notes; fix chain capability order
Replaces single-model call with a configurable fallback chain. On 429
(rate-limit / quota), 402 (credits), 403/404 (retired id) or 5xx
(upstream) the explainer advances to the next free model. Network and
timeout errors still drop straight to the deterministic template,
since switching models can't fix an unreachable host.
Loads .env via python-dotenv at import time so OPENROUTER_API_KEY
flows through without manual exports. .env added to .gitignore.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(llm): modality dispatch — explain(payload, modality) for BBB/EEG/MRI
- explain() gains modality kwarg ('bbb' | 'eeg' | 'mri'), default 'bbb'
for backward compat with Day-7 callers.
- _template_explain renamed to _template_explain_bbb; added
_template_explain_eeg (epochs, features, ICA story) and
_template_explain_mri (site-gap pre/post, reduction factor).
- _build_llm_prompt branches on modality with a domain-specific header
+ body. Unknown modality logs warning and falls back to BBB template.
- ExplainPayload loosened from strict TypedDict to dict[str, Any] since
shapes differ across modalities.
- 3 new tests (TestEEGTemplate, TestMRITemplate, TestModalityDispatch).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(llm): explainer with deterministic template + OpenRouter fallback
- New module src/llm/explainer.py — single public entry point
explain(payload). Returns {rationale, source, model}. Never raises.
- Deterministic template (4 sentences: verdict, calibration if any,
top-3 SHAP, drift) is the source of truth for tests.
- LLM path: OpenRouter chat completions via openai==1.51.0 SDK,
model meta-llama/llama-3.2-3b-instruct:free, 8s timeout, 256 max
tokens, temperature 0.3. Gated by OPENROUTER_API_KEY presence and
NEUROBRIDGE_DISABLE_LLM=1 kill-switch.
- Fallback chain: env-disabled → no key → SDK ImportError → API error
→ empty/malformed response → all degrade to template, log WARNING,
source="template".
- 4 new tests: deterministic, top features included, label text
included, kill-switch overrides key.
- New pip dep: openai==1.51.0 (~600KB, transitive deps already present).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>