Fine-tuned Mapper API
Big-model answers. Small-model prefill. Trained on your task.
A small model reads your document, a trained mapper converts its KV cache into a big model's representation, and the big model answers without ever reading the document. You send one JSONL file of questions over your documents; we train, benchmark, and host the mapper, or hand you the artifact.
Measured results
Production pair: Qwen3.5-4B (reader) → Qwen3.8-27B (answerer), n=100 held-out questions per benchmark, 95% document-grouped CIs. Your evaluation report runs the same four arms on your own held-out questions.
| Benchmark | 4B alone | Fine-tuned mapper | 27B native |
|---|---|---|---|
| QuALITY (long stories) | 0.850 | 0.900 | 0.900 |
| BAMBOO PaperQA (papers) | 0.857 | 0.881 | 0.869 |
| MATH-500 | 0.930 | 0.900 | 0.960 |
| QMSum (meetings, judge) | 0.440 | 0.424 | 0.497 |
The pattern holds across pairs: on Qwen3 1.7B→8B, a task-specific mapper trained on 465 documents matches native 8B on ZebraLogic exactly (0.79 vs 0.79) at about 39% of the 8B's TTFT at 32K context, and beats a parameter-matched LoRA of the small model on the same data. Mappers pay off most on long, domain-specific documents: contracts, papers, patient records, codebases. Short-context tasks (see MATH-500) gain little, because the small model is already close.
How it works
- Send data. One JSONL file: questions over your documents. No GPUs, no model weights, no configs on your side.
- We train. The two models read your training documents, the big model answers your training questions itself, and a rank-16 adapter is distilled to those answers (2–6 hours). Your gold labels are used only for your benchmark report, never for training.
- You verify, then ship. The evaluation report scores all four arms on 100 held-out questions whose documents were never trained on. Then call hosted inference, or take the packaged artifact (safetensors + hash manifest) into your own stack.
Quick start
1 · Format your data (data.jsonl, one JSON object per line)
{"id": "q-0017", "group_id": "contract-07",
"context": "<full document text>",
"query": "Can the supplier terminate without cause? Answer Yes or No.",
"reference": "No"} group_id ties every question to its document; held-out splits are document-disjoint.
Recommended: ≥1,000 questions over ≥50 documents (minimum 150 questions). Documents up to
~32k tokens.
2 · Create, train, evaluate
export KVT_API_KEY=kvt_sk_...
BASE=https://api.onetriangle.ai/v1
curl -X POST $BASE/projects -H "Authorization: Bearer $KVT_API_KEY" \
-d '{"project": "support-bot", "data_path": "/uploads/data.jsonl"}'
curl -X POST $BASE/projects/support-bot/prepare -d '{"test_size": 100}' ...
curl -X POST $BASE/projects/support-bot/train ... # poll until "trained"
curl -X POST $BASE/projects/support-bot/evaluate -d '{"n": 100}' ... 3 · Use it
# Hosted inference
curl -X POST $BASE/projects/support-bot/generate \
-H "Authorization: Bearer $KVT_API_KEY" \
-d '{"context": "<document>", "query": "<question>", "max_new": 512}'
# -> {"answer": "..."}
# Or take the artifact into your own stack
curl -X POST $BASE/projects/support-bot/package ...
# -> mapper.safetensors + SHA-256 manifest + configs Acceptance, plainly
We suggest shipping when your report shows the mapper within 0.03 of the big model natively, or when the "gap closed" confidence interval excludes 0.5. If your report shows the mapper at small-model level, your contexts are probably too short to matter or there's too little training data; the report tells you which.
- Quality is task-specific by design: the mapper matches the big model on your trained distribution, not on unrelated tasks.
- Documents past ~100k tokens are not yet supported.
- Keys are revocable, usage is metered per call, and customer projects are isolated.