PH AI WorksRAG Demo

Evaluation

Measured on a 60-case gold set. The headline figures are the shipped configuration — dense retrieval — with hybrid shown alongside as the comparison it lost. Out-of-scope cases are scored separately on refusal: a pipeline tuned only for recall answers every question, including the ones it should decline.

gemini-embedding-001 · top_k=5 · min_score=0.655 · run 2026-08-05T03:08:04Z

top-1 accuracy
96%
hybrid: 90%
recall@5
100%
hybrid: 100%
MRR
0.979
hybrid: 0.938
refusal, retrieval only
75%
 

End to end, through the agent

The retrieval threshold above refuses 75% of out-of-scope questions. It cannot do better, because the ones it lets through are squarely on topic — asking for a diagnosis, a drug dose, a product recommendation. A cosine score has no way to tell those apart from a legitimate question about the same biomarker. The generation stage does, and catches all of them.

out-of-scope refused
100%
in-scope answered
94%
cited the right brief
94%

gemini-2.5-flash · zero hallucinated citations: the harness asserts every cited id was in the retrieval result

The in-scope cases it declined are all requests for a personal diagnosis. The retrieval label is right — HbA1c is the brief for “am I prediabetic” — but declining to diagnose is also right, so these are counted as misses by a gold set that only labels retrieval:

  • lay-02 am I prediabetic model_declined
  • lay-05 is my thyroid underactive model_declined
  • lay-16 my periods have stopped and I get hot flushes model_declined

Why hybrid retrieval was dropped

Hybrid search is the standard recommendation and was the original design here. Sweeping the weight BM25 carries in the fusion shows it never helps on this corpus and degrades monotonically: BM25 latches onto a domain word many briefs share — “cholesterol” — and floats all of them above the one that answers the question. Kept in the code, off by default.

BM25 weighttop-1MRR
dense-only96%0.979
096%0.979
0.196%0.979
0.294%0.969
0.392%0.958
0.490%0.944
0.590%0.944
0.790%0.939
190%0.938

By case type

Broken down by the failure each case type is designed to catch. The `exact` row is the one that settled the hybrid question: keyword search exists to rescue verbatim names, and dense retrieval already gets every one of them.

case typendense (shipped)hybrid
confusable2090%85%
exact12100%100%
lay16100%88%
oos1275%75%

Threshold sweep

Why min_score is 0.655 and not a rounder number. Raising it refuses more out-of-scope questions and starts declining ones it could have answered; the chosen value is the peak of the combined column.

thresholdanswered correctlycorrectly refusedcombined
0.5196%8%78%
0.5396%17%80%
0.5496%17%80%
0.5696%17%80%
0.5796%25%82%
0.5996%33%83%
0.6096%33%83%
0.6296%42%85%
0.6396%58%88%
0.6594%75%90%
0.6694%75%90%
0.6892%75%88%
0.6983%92%85%
0.7179%100%83%
0.7271%100%77%
0.7467%100%73%
0.7648%100%58%
0.7738%100%50%
0.7921%100%37%
0.808%100%27%
0.820%100%20%

Remaining failures (5)

Published rather than trimmed. A gold set with no failures left has usually been edited to match the system rather than the other way round.

  • conf-05confusablewhich liver enzyme tells me whether a high ALP is bone or liver
    expected GGT · got ALP, GGT, ALT · best cosine 0.816
  • conf-10confusablethe iron test that is not thrown off by inflammation
    expected Transferrin Saturation · got Serum Iron, Transferrin Saturation, Ferritin · best cosine 0.7572
  • oos-06ooswhich brand of vitamin D supplement should I buy
    expected a refusal · got Vitamin D, Calcium, Folate · best cosine 0.6802
  • oos-07ooswhat dose of levothyroxine should I take for my TSH
    expected a refusal · got TSH, Free T4, Free T3 · best cosine 0.6858
  • oos-08oosdo I have diabetes, just tell me yes or no
    expected a refusal · got HbA1c, Fasting Glucose, C-Peptide · best cosine 0.7012

← Back to the demo