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…
Adds the only legitimate BBB <-> MRI bridge in the platform — researcher
lane only. Fusion engine still excludes BBB as a diagnostic modality.
Modules:
- src/models/bbb_permeability_map.py: scalar BBB leakage score in [0,1]
with two modes. heuristic_proxy (default) reuses the 2D resnet18
Alzheimer classifier and computes 1 - P(NonDemented). dce_onnx loads
a real 4D DCE-MRI ONNX model from BBB_PERMEABILITY_DCE_PATH and
averages a normalised Ktrans map; raises a clear FileNotFoundError
with contract documentation when no artifact exists.
- src/research/drug_dose_adjuster.py: pure-function dose revision keyed
on (BBB intact?, drug BBB-permeable?). Permeable drugs see an
aggressive linear cut floored at 30%; non-permeable drugs see a mild
cut floored at 60%; intact BBB returns baseline unchanged. Unknown
drug permeability is treated as permeable (safer). Rationale always
includes the 'research suggestion, not medical advice' disclaimer.
API:
- POST /predict/bbb_permea…
feat(eeg,frontend): EEG fusion-flow test + Streamlit EEG form + real-artifact sanity
- tests/fusion/test_eeg_modality_flow.py: end-to-end EEG -> fusion `eeg`
modality flow (alzheimers feature spike lifts AD score; control profile
doesn't inflate it).
- tests/models/test_eeg_model_real.py: skip-if-absent sanity for the real
EEG joblib; runs automatically once the file lands at the canonical path.
- src/frontend/app.py: doctor MRI tab grows an EEG predict form
(comma-separated features) calling POST /predict/eeg. 503 surfaces as a
human-readable warning instead of a stack trace.
feat(frontend): expose MRI_MODEL_KIND in MRI predict tab; 2D upload path
Add 6th "🤖 Agent" tab to the Streamlit UI that calls POST /agent/run,
renders the response text + model/finish_reason caption, and shows an
expandable decision-trace panel listing each tool call's name, args,
and result (or error). Also makes _post() timeout configurable via a
keyword arg (default 120 s) for backwards compatibility.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
One-shot in-container probe to diagnose why /explain/* falls back
to template on HF Space. Shows key presence (length + 12-char prefix
only — never full secret), kill-switch state, and an 8-token probe
against the chain's first model. Surfaces 401/429/CONN errors as
JSON so deployment issues can be diagnosed without container shell
or HF logs API access.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(frontend): toast icon must be valid emoji, not ✓
Streamlit's st.toast(icon=...) accepts only single emoji characters,
not arbitrary unicode shortcodes. The check-mark "✓" tripped a
StreamlitAPIException after every successful prediction. Switched all
three success toasts (BBB / EEG / MRI) to "✅".
fix(frontend): EEG default path points at fixture (HF container has no data/raw/eeg.fif)
- New 5th tab in main(): BBB / EEG / MRI / AI Assistant / Experiments.
- _render_experiments_tab loads /experiments/runs (cached in session
state, refresh button to invalidate), shows a runs table with run_id
prefix / experiment / start_time / status / metric+param counts.
- Two selectboxes pick run ids; 'Show diff' POSTs /experiments/diff
and renders a key/kind/A/B/differs table.
- Empty-state messaging when MLflow is disabled or no runs exist;
helpful hint to trigger a pipeline first.
- New _get() helper for symmetric GET calls.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(frontend): inline AI Assistant in EEG + MRI tabs
- EEG tab gains an expander after pipeline results: 3 preset questions
+ custom input + Ask button → POST /explain/eeg.
- MRI tab gains a parallel expander inside _render_combat_diagnostics:
feeds site_gap_pre/post + reduction_factor + n_subjects (derived
from distinct subject_id count) into POST /explain/mri.
- Both expanders show source/model audit caption like the BBB
AI Assistant tab. Uses last_eeg_run session state.
- No new tests — UI wiring covered by import-smoke tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(frontend): AI Assistant tab — natural-language explainer
- New 4th tab in main(): BBB / EEG / MRI / AI Assistant.
- _render_ai_assistant_tab pulls last_bbb_prediction from session
state, shows a snapshot caption, lets the user pick from 3 preset
questions or type a custom one, POSTs to /explain/bbb, and renders
a reverse-chronological history (capped at 10).
- Each history entry shows source (llm | template) and model so
jurors can audit which path served each rationale.
- Empty state when no prediction yet: explicit prompt to run BBB tab
first.
- No new tests; covered by 2 existing import-smoke tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(api+frontend): MLflow provenance badge in decision card
- ModelProvenance schema (mlflow_run_id, model_version, train_date,
n_examples). BBBPredictResponse.provenance is always populated; failed
MLflow lookup degrades to None fields without breaking the response.
- _build_provenance() module-level cache: one MLflow query per worker.
NEUROBRIDGE_DISABLE_MLFLOW=1 short-circuits to None fields. n_examples
pulled per-request from model._neurobridge_train_stats.
- Streamlit decision card renders a one-line audit badge above the
label: run id (first 8 chars), model version, train date, n_examples.
- 1 new test: provenance field present in /predict/bbb body with the
fixture model (n_examples ≥ 1 from train stats).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(frontend): drift metric line + last-prediction session state
- Renders one-line drift caption between the calibration caption and
the SHAP section. Three states: warming up (<10 samples), unavailable
(no train stats), drift z-score with magnitude tag (in-band / mild /
significant).
- Stashes /predict/bbb response in st.session_state["last_bbb_prediction"]
so the Day-7 T3C AI Assistant tab can pick it up.
- No backend / schema / test count changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replaces the bare /pipeline/mri call with /pipeline/mri/diagnostics
to surface the harmonization story directly to the jury.
- 3 KPI metrics on the top row: Site-gap (Pre), Site-gap (Post), and
Reduction factor (e.g. ~3290× on the synthetic fixture).
- Faceted altair density chart: per-site KDE before vs after ComBat,
with shared axes so the convergence is visually obvious.
- Local altair/pandas imports keep cold-start light when only the BBB
tab is exercised.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surfaces the calibration bin from /predict/bbb under the confidence
progress bar, e.g. 'Test set'te ≥75% güven üreten tahminlerin
precision'ı 92% (n=146).' Silently skips when the response has no
calibration field (legacy models). support==0 path shows an explicit
hedge instead of misleading zeros.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(frontend): edge-case dropdown for BBB robustness demo