Replace the loose '30/minute' cap with a layered '5/minute;20/hour;30/day'
on both /query and /ui/query. Same key (remote IP) on all three windows;
slowapi enforces them independently and the most restrictive wins.
Worst-case spend per IP per day: 30 queries x ~$0.011 (max_tokens=2048
on claude-haiku-4-5) = ~$0.33. Comfortably under the $1 ceiling and
still leaves room for a legitimate evaluator to try a handful of queries
in a single sitting.
Generalize system prompt to handle hypothetical patient scenarios
The old prompt's 'every factual claim comes from a chunk, otherwise refuse'
rule was too rigid for clinical reasoning. Users asking 'patient presents
with X, Y, Z - what could this be?' were getting the canonical refusal
even when the chunks contained the relevant criteria, because no single
chunk explicitly labelled that symptom constellation as a diagnosis.
New prompt allows pattern-matching: the model may apply chunk-sourced
criteria to user-described hypothetical facts, and report which conditions
are consistent with the described features. Guard-rails preserved:
- All clinical facts (criteria, prevalence, treatment, features) still
require chunk citations.
- Hedging language ('consistent with', 'could meet criteria for',
'overlaps with'), not diagnostic language ('the patient has').
- Explicit differential-question rule: list every supported candidate
with distinguishing features, cited.
- Polarity check kept unchanged.
- Refusal narrowed: only when the chunks do not cover …
Double DEFAULT_MAX_TOKENS from 1024 to 2048 and loosen the 'aim for 2-4
sentences' instruction. The new system prompt tells the model to match
length to the question: short answers for factual one-shot queries,
full detail (criteria, differentials, treatment lists, etc.) when the
question actually calls for it, with bullets or short paragraphs when
long answers need structure.
Wire a fourth source type through the retrieval, API, UI, and eval
dashboard layers:
- api/hybrid.py: add 'icd12' to SOURCE_TYPES so per-source retrieval
fans out to it alongside mtsamples, pubmed, icd11.
- api/main.py: add 'icd12' to the SourceType Literal so the JSON API
accepts it in source_types filters.
- api/templates/_results.html: amber chip treatment for icd12 hits.
- api/static/eval.js: amber colour + inclusion in the per-query source
mix chart on the /eval dashboard.
Redirect / to /ui (handles bare Space URL + HF healthcheck)