Benchmarks
haiku.rag is evaluated on OpenRAG Bench (ORB), T²-RAGBench, HotpotQA, FRAMES and MTRAG. Retrieval, QA accuracy and citation retrieval are scored end to end through the RAG capability, see Methodology.
Each footnote names the haiku.rag version and the judge a row was measured with. Rows are not re-run when either changes, so compare rows that share both. Rows before v0.87.0 ran the capability architecture that release replaced.
No benchmark database has a vector index, so every number reflects exact brute-force kNN. For the effect of an index, see Vector indexing.
OpenRAG Bench (ORB)
OpenRAG Bench is arXiv papers with multimodal question-answer pairs, text-based and image-based, over figures, charts and diagrams. Each query maps to one relevant document.
Two approaches are measured:
- Multimodal embedder (
Qwen/Qwen3-VL-Embedding-8Bornvidia/llama-nemotron-embed-vl-1b-v2, served by vLLM): pictures and text share one vector space, and no VLM runs at ingest. - Text embedder with VLM picture descriptions (
qwen3-embedding:4bwithollama/ministral-3): pictures are described at ingest and the descriptions join the chunk text. See Picture handling.
Multimodal embedder
Retrieval (MAP)
| Embedding Model | Reranker | Cases | MAP |
|---|---|---|---|
Qwen/Qwen3-VL-Embedding-8B |
none | 3045 | 0.9774 |
nvidia/llama-nemotron-embed-vl-1b-v2 |
none | 3045 | 0.9798 |
nvidia/llama-nemotron-embed-vl-1b-v2 |
nvidia/llama-nemotron-rerank-vl-1b-v2 (multimodal) |
3045 | 0.9899 |
The reranked row: v0.88.0, reranking.multimodal: true, the stack of the QA rows below. The Qwen3-VL row: v0.52.0. The Nemotron row without a reranker was measured earlier.
QA accuracy and citation retrieval
| Capability model | Cases | QA accuracy | Mean cited_map |
|---|---|---|---|
vllm:Muse-Glimmer-30B-NVFP4-W4A4 |
3045 | 0.9620 | 0.9847 |
vllm:Qwen3.8-27B-NVFP4 |
3045 | 0.9688 | 0.9907 |
v0.88.0, the reranked retrieval stack above, judged by Qwen3.8-27B at reasoning_effort: low. Accuracy is over judged cases, 3028 and 3043 of 3045, the rest lost to the search tool exhausting its retry limit. Counting the unjudged as failures gives 0.9566 and 0.9682. Mean 26.15 s and 13.95 s per case. Muse-Glimmer runs at chat_template_kwargs.reasoning_strength: high, Qwen3.8 at reasoning_effort: low.
Paired on the 3023 cases judged in both, accuracy does not separate the models (McNemar exact p = 0.09). cited_map favours Qwen3.8, better on 44 cases and worse on 19 (sign test p = 0.0025). The Qwen3.8 row is self-judged. An independent judge agreed on 95% of a 120-case sample and was never stricter.
Text embedder with VLM picture descriptions
Retrieval (MAP)
| Embedding Model | VLM | Reranker | Cases | MAP |
|---|---|---|---|---|
qwen3-embedding:4b |
Ollama / ministral-3 | mxbai-rerank-base-v2 |
3045 | 0.9834 |
nvidia/llama-nemotron-embed-vl-1b-v2 |
Ollama / ministral-3 | mxbai-rerank-base-v2 |
3045 | 0.9863 |
v0.50.0.
QA accuracy and citation retrieval
| Embedding Model | VLM | Capability model | Cases | QA accuracy | Mean cited_map |
|---|---|---|---|---|---|
qwen3-embedding:4b |
Ollama / ministral-3 | vllm:Gemma-4-26B-A4B-NVFP4 |
3045 | 0.92 | 0.80 |
nvidia/llama-nemotron-embed-vl-1b-v2 |
Ollama / ministral-3 | vllm:Gemma-4-26B-A4B-NVFP4 |
2836 | 0.96 | 0.81 |
v0.50.0 with mxbai-rerank-base-v2, judged by vllm:Qwen3.6-35B-A3B-NVFP4. The Nemotron row covers 2836 of 3045 cases.
T²-RAGBench (FinQA)
T²-RAGBench turns financial-report QA into context-independent questions with short numeric answers and one gold document each. The FinQA subset is 2,789 single-page PDFs and 8,281 questions. QA is scored by exact numeric match (NumberMatchEvaluator, relative tolerance 0.01), not by a judge.
QA accuracy and citation retrieval
| Embedding Model | Reranker | Capability model | Cases | QA accuracy | Mean cited_map |
|---|---|---|---|---|---|
qwen3-embedding:4b |
mxbai-rerank-base-v2 |
vllm:Qwen3.6-35B-A3B-NVFP4 |
7939 | 0.77 | 0.78 |
v0.55.0, qwen3-embedding:4b (vLLM, 2560) with mxbai-rerank-base-v2. 341 of 8281 cases produced no answer, and accuracy and cited_map are over the 7939 scored. Mean 16.0 s per case.
HotpotQA
HotpotQA is multi-hop QA over Wikipedia: each question combines facts from two paragraphs, among distractor paragraphs. The distractor validation split has 7,405 questions over about 66k paragraphs, two gold documents per question.
Retrieval (MAP)
| Embedding Model | Reranker | Cases | MAP |
|---|---|---|---|
qwen3-embedding:4b |
Qwen3-Reranker-4B |
7405 | 0.8202 |
qwen3-embedding:4b |
none | 7405 | 0.6995 |
Hybrid search usually ranks the first-hop document first. The second-hop document often needs the reranker to reach the result window.
QA accuracy and citation retrieval
| Capability model | Reranker | QA accuracy | Mean cited_map |
|---|---|---|---|
vllm:Gemma-4-26B-A4B-NVFP4 |
Qwen3-Reranker-4B |
0.85 | 0.80 |
vllm:Gemma-4-26B-A4B-NVFP4 |
none | 0.83 | 0.75 |
v0.66.0, qwen3-embedding:4b (vLLM, 2560), judged by vllm:Qwen3.6-35B-A3B-NVFP4, 7,405 cases. Without a reranker, cited_map (0.75) exceeds retrieval MAP (0.70): the capability searches several times and recovers second-hop documents one query misses.
FRAMES
FRAMES is Google's multi-hop QA benchmark: 824 questions, each grounded in 2 to 23 Wikipedia articles, with temporal, numerical and tabular reasoning. 822 are evaluated, 2 being excluded because a linked article was deleted, over a fixed corpus of the 2,500 linked articles fetched at their current revision. FRAMES has no official evaluation setup. A fixed corpus with agentic retrieval and judged accuracy corresponds to the paper's multi-step retrieval setting, where the paper reports 0.66 with Gemini-Pro-1.5 (0.729 given the gold articles). Answers were written against 2024 revisions and may have drifted with the articles.
Gold sets span 2 to 23 articles, more than a result window holds or an answer cites, so MAP and cited_map stay well below 1.
Retrieval (MAP)
| Embedding Model | Reranker | Cases | MAP |
|---|---|---|---|
nvidia/llama-nemotron-embed-vl-1b-v2 |
nvidia/llama-nemotron-rerank-vl-1b-v2 |
822 | 0.5966 |
v0.88.0, the stack of the QA rows below. Single-query retrieval scores zero on 11 questions, those whose gold article's subject the question never names. The agentic run answers 6 of them correctly.
QA accuracy and citation retrieval
| Capability model | Cases | QA accuracy | Mean cited_map |
|---|---|---|---|
vllm:Muse-Glimmer-30B-NVFP4-W4A4 |
822 | 0.8938 | 0.7342 |
vllm:Qwen3.8-27B-NVFP4 |
822 | 0.9077 | 0.7312 |
v0.88.0, nvidia/llama-nemotron-embed-vl-1b-v2 (vLLM, 2048) with nvidia/llama-nemotron-rerank-vl-1b-v2, judged by Qwen3.8-27B at reasoning_effort: low. Accuracy is over judged cases, 810 and 802 of 822, the rest lost to the search tool exhausting its retry limit. Counting the unjudged as failures gives 0.8808 and 0.8856. Mean 62.56 s and 30.21 s per case. The Qwen3.8 row is self-judged.
Paired on the 791 cases judged in both, neither metric separates the models (accuracy McNemar exact p = 0.80, cited_map sign test p = 0.16). Not comparable with FRAMES results before v0.87.0, which used a different corpus build, embedder, reranker and capability.
MTRAG (ClapNQ)
MTRAG is IBM's multi-turn RAG benchmark: human-written conversations with per-turn answerability labels and binary relevance judgments. The ClapNQ (Wikipedia) domain has 183,408 passages, 29 conversations, 224 turns and 208 retrieval queries.
Four dataset keys share one database:
mtrag_clapnqretrieves with the last user turn as written, and answers each turn after replaying the reference conversation before it.mtrag_clapnq_rewriteretrieves with the human standalone rewrites.mtrag_clapnq_livereplays whole conversations through one capability session, carrying the model's own answers, tools and state, withEvidenceCompactionCapabilityregistered.mtrag_clapnq_live_uncompactedis the same replay without compaction. It is the only evaluation where compaction acts.
Retrieval (Recall@k / nDCG@k)
Comparable with IBM's published results. Elser is IBM's strongest reported retriever.
| Retriever | Queries | R@5 | R@10 | nDCG@5 | nDCG@10 |
|---|---|---|---|---|---|
| Elser (IBM) | lastturn | 0.49 | 0.58 | 0.45 | 0.49 |
haiku.rag |
lastturn | 0.501 | 0.600 | 0.455 | 0.497 |
| Elser (IBM) | rewrite | 0.52 | 0.64 | 0.48 | 0.54 |
haiku.rag |
rewrite | 0.548 | 0.668 | 0.503 | 0.556 |
QA accuracy and citation retrieval
| Mode | Capability model | Turns | QA accuracy | Mean cited_map |
|---|---|---|---|---|
Gold-prefix (mtrag_clapnq) |
vllm:Muse-Glimmer-30B-NVFP4 |
224 | 0.76 | 0.35 |
Live compacted (mtrag_clapnq_live) |
vllm:Muse-Glimmer-30B-NVFP4 |
224/224 scored | 0.83 micro / 0.84 macro | 0.42 |
Live uncompacted (mtrag_clapnq_live_uncompacted) |
vllm:Muse-Glimmer-30B-NVFP4 |
224/224 scored | 0.78 micro / 0.79 macro | 0.42 |
v0.74.0, qwen3-embedding:4b (vLLM, 2560), Qwen3-Reranker-4B, reasoning_strength: high, judged by vllm:Qwen3.6-35B-A3B-NVFP4 (temperature 0.6, thinking). QA uses our judge and rubric and is not comparable with IBM's generation metrics. Gold-prefix and live rates answer different judge questions and are not comparable with each other. cited_map is over the 208 turns with gold passages.
The two live arms replay the same 224 turns and differ only in compaction:
| Compacted | Uncompacted | |
|---|---|---|
| Input tokens per model request | 7,461 | 13,539 |
| Turns passed | 185 | 175 |
| Citation MAP (macro, 208 eligible turns) | 0.4174 | 0.4230 |
| Refusal precision / recall (16 unanswerable turns) | 0.33 / 0.44 | 0.23 / 0.31 |
Compaction cut input tokens per request by 44.9%. Of the 18 turns where the arms disagree, 14 pass only compacted (McNemar exact p = 0.031, paired difference +4.5 points, 95% CI +0.8 to +8.1). The gold-prefix arm's refusal precision and recall are 0.24 and 0.44.
Methodology
Retrieval metrics
The retrieval benchmark runs one search per question through the configured search stack, with the reranker when one is configured and without context expansion. It keeps the top 5 chunks, 10 for MTRAG, and scores the distinct documents they come from, in rank order.
Mean Average Precision (MAP) scores those documents against the gold expected_uris:
- At each relevant document's position k, precision@k is the relevant documents in the top k divided by k.
- Average precision (AP) is the sum of those precisions divided by the number of relevant documents.
- MAP is the mean AP over queries, from 0 to 1. For a single-document query it is
1/rank.
MTRAG also reports Recall@k and nDCG@k.
QA accuracy
A pydantic-evals LLM judge decides whether each answer is correct, and accuracy is the fraction judged correct. The default judge is ollama:qwen3.8, pinned so that changing the capability model does not change the judge. evaluations.judge in haiku.rag.yaml overrides it, including any OpenAI-compatible endpoint. Against the previous judge on 120 ORB cases, qwen3.8 agreed on 95% (Cohen's κ 0.90).
A dataset with its own deterministic evaluator is scored by it, and no judge runs. T²-RAGBench is the only one, with NumberMatchEvaluator.
A case that ends in an error gets no verdict, and accuracy is over judged cases. A floor in a footnote counts the unjudged as failures.
Citation retrieval
cited_map scores the URIs the capability registered with cite against the gold expected_uris, with the same MAP arithmetic. It comes from the same run as QA accuracy. Where retrieval MAP measures whether the retriever returned the gold document, cited_map measures whether the answer was grounded on it. The console also reports the cite rate, the share of cases with at least one citation, and mean citations per case.
Comparing runs
Two runs are compared on the same cases: exact McNemar on the verdicts, the sign test on cited_map. Two runs of identical code and config already answer some cases differently, because the capability model samples and vLLM batching reorders near-tied scores, so a small difference needs that test before it means anything. See Comparing two runs in the evaluations README.
Running evaluations
The evaluations CLI in the repository's evaluations/ package runs the benchmarks, orchestrated with pydantic-evals. Its README covers installation, every dataset and option, per-case result files, comparing two runs and restricting a run to part of a database.
Pre-built databases
Building an evaluation database takes long, especially for OpenRAG Bench. Pre-built ones are on HuggingFace:
| Dataset | Size |
|---|---|
orb_text: OpenRAG Bench, qwen3-embedding:4b with VLM picture descriptions in the chunk text |
~15.9 GB |
orb_multimodal: OpenRAG Bench, multimodal qwen3-vl-embedding-8b |
~16.7 GB |
orb_multimodal_nemotron: OpenRAG Bench, multimodal nvidia/llama-nemotron-embed-vl-1b-v2 |
~15.2 GB |
t2_finqa: T²-RAGBench FinQA, qwen3-embedding:4b |
~2.0 GB |
t2_tatdqa: T²-RAGBench TAT-DQA, qwen3-embedding:4b |
~1.8 GB |
hotpotqa: HotpotQA, qwen3-embedding:4b |
~1.2 GB |
frames: FRAMES, nvidia/llama-nemotron-embed-vl-1b-v2 |
~7.2 GB |
mtrag_clapnq: MTRAG ClapNQ, qwen3-embedding:4b, shared by the _rewrite, _live and _live_uncompacted keys |
~2.8 GB |
The hosted frames and orb_multimodal_nemotron databases are the corpora behind the current FRAMES and ORB rows.
A database opens only against the embedder recorded in it, so run a downloaded one with --skip-db and its reference config from evaluations/configs/:
uv run evaluations run orb_multimodal_nemotron --skip-db --config evaluations/configs/orb_multimodal_nemotron.yaml
t2_tatdqa has no reference config of its own. evaluations/configs/t2_finqa.yaml uses the same embedder and opens it.
The configs use vLLM endpoints. Point their base_url at your own OpenAI-compatible servers to run them.
Judge settings
The capability runs on qa.model and the judge on evaluations.judge, both from the configuration. The recommended judge settings, pinned in every reference config of a judged dataset:
evaluations:
judge:
provider: openai
name: Inferact/Qwen3.8-27B-NVFP4
base_url: http://localhost:8000/v1 # optional, for OpenAI-compatible servers
temperature: 0.6
max_tokens: 16384
extra_body:
top_p: 0.95
top_k: 20
min_p: 0
chat_template_kwargs:
reasoning_effort: low # qwen3.8: low | medium | xhigh (default)
Faster judging with a System One model
evaluations.system_one puts a System One model in front of the judge. It is optional and off by default, and the benchmarks on this page are judged by Qwen3.8 alone. A System One model returns a probability instead of generated text.
Each answer goes to the decision model first, with the question, the expected answer and the generated answer as its state and the rubric as its question. At a probability of 0.8 or more the answer passes, and below 0.2 it fails, with no call to the judge. The judge in evaluations.judge decides everything in between, every case the endpoint fails on, and gold-prefix conversation cases. Live conversation runs do not use the model, and say so when the block is set. The run asks the model the judge's question before the first case and stops if it does not answer.
TypeSafe's hosted Jev is reached on its /v1/systemone API and reads the key from TYPESAFE_API_KEY:
Set model explicitly: when it is unset, the TypeSafe SDK sends jev-latest.
Tev1 4B is an open decision model from Together AI that runs on Ollama or vLLM. With provider set, the judge asks it on the OpenAI-compatible chat API in Tev1's own format, reads the probability from the answer letter's logprobs, and averages the two orders of the yes and no options. Two requests per answer, no key.
On Ollama 0.35 or later, the measurements used digest cef45ef93cf6:
On vLLM, the measurements used revision 0b7becf with vLLM 0.29:
vllm serve togethercomputer/Tev1-4B-experimental \
--revision 0b7becf017daa0e5eb222f8ce7483c8c8259c52f \
--served-model-name tev1-4b --max-num-seqs 256
vLLM refuses to start when --max-num-seqs exceeds the cache blocks it can give the model's linear-attention layers. 256 fit at --gpu-memory-utilization 0.22 on a 96 GB GPU, and the default of 1024 did not.
Tev1 was trained on prompts of up to 2,048 tokens. Its Ollama model sets a context of 2,050 and rejects longer prompts, which the judge then decides: 8 of 3,043 ORB answers and 8 of 797 FRAMES answers. On vLLM the prompt limit is --max-model-len.
Ollama's own /v1/systemone API also serves tev1:4b, but renders its own prompt and rejects the judge's list criteria, so use provider: ollama instead.
Measured against Qwen3.8 alone, on fresh orb_multimodal_nemotron and frames runs of the current capability: Jev on 2026-09-24, Tev1 4B on 2026-09-30. Every case where the verdicts differed was adjudicated by three independent labellers (one reviewer and two fresh-context LLM labellers), blind to which judge produced which verdict. Tev1 on vLLM served bf16 weights on a CUDA GPU, and on Ollama its Q8_0 build on Apple silicon. The two gave the same verdict on 3,033 of 3,035 ORB answers and 788 of 789 FRAMES answers.
| Endpoint | Dataset | Cases | Decided alone | Pass rate (Qwen3.8 → gated) | Changed verdicts | Qwen3.8 right / gated right |
|---|---|---|---|---|---|---|
| Jev 1.13.0 | ORB | 3,043 | 90.0% | 96.39% → 96.09% | 9 | 6 / 3 |
| Jev 1.13.0 | FRAMES | 797 | 94.9% | 90.97% → 90.97% | 2 | 0 / 2 |
| Tev1 4B, vLLM | ORB | 3,043 | 92.7% | 96.39% → 96.39% | 6 | 2 / 4 |
| Tev1 4B, vLLM | FRAMES | 797 | 96.7% | 90.97% → 90.59% | 5 | 2 / 3 |
| Tev1 4B, Ollama | ORB | 3,043 | 92.9% | 96.39% → 96.39% | 8 | 3 / 4 (one not adjudicated) |
| Tev1 4B, Ollama | FRAMES | 797 | 96.6% | 90.97% → 90.72% | 6 | 2 / 4 |
All 9 of Jev's ORB changes are fails below 0.2 on answers Qwen3.8 passed (McNemar exact p = 0.004), so a Jev-gated ORB run reads lower than Qwen3.8 alone. Tev1's changes go both ways. The splits of who was right rest on 2 to 9 cases per row and are too small to rank the endpoints. Neither model is deterministic between runs: replaying 390 labelled cases moved up to 11 across a band edge for Jev, and vLLM's batching moves Tev1's probabilities by up to 0.03, so a gated run does not reproduce verdict for verdict.
Result rows record judge_decided_by (system_one, fallback, fallback_on_error or fallback_conversation), judge_probability and system_one_model, and the run prints the count of each. A gated run and an ungated run of the same system differ by the judge as well, so they do not form a null pair, and evaluations pair warns when only one of its two files was gated or when they were gated by different models.