01 — The Task

Finding the needle in a contract

CUAD is 510 real commercial contracts, hand-annotated by lawyers, marked up across 41 clause types — anti-assignment, cap on liability, non-compete, and so on. The job: hand the model a full contract and one clause type, and ask it to find that clause, verbatim, if it's there.

Every answer is a small JSON object. Two ways to fail: say a clause exists when it doesn't (or miss one that does), or find the right clause but misquote it.

Prompt (abridged)

SYSTEM: You are a contract analyst.
Given a contract and a clause type,
return JSON: {"found": bool, "quote": string}.
The quote must be an exact, verbatim
excerpt from the contract, or "" if
not found.

CONTRACT: "This Distributor Agreement
is made effective as of the 31st day
of March, 2000, by and between
Airspan Networks Incorporated..."
[...11,400 more tokens...]

CLAUSE TYPE: Agreement Date

Response

{
  "found": true,
  "quote": "31st day of March, 2000"
}

02 — The Experiment

Four contenders, one blind test

Same contracts, same prompts, same scoring — the only variable is the model.

Base 9B base

Qwen3.5-9B, untouched. Zero-shot, out of the box — the control.

Fine-tuned 9B ft

The same 9B model after LoRA fine-tuning on 4,058 examples, 3 epochs, 2.2 H100-hours, run through the Overmind platform.

GPT-5.6-luna luna

A frontier model behind a closed API, used as-is with the same zero-shot prompt.

GPT-5.6-terra terra

A second frontier model, evaluated on the same paired sample and prompt.

Held to the same bar:

  • Evaluated on 1,639 paired questions across held-out contracts none of the models saw during training — split at the contract level, not the question level, so nothing leaks.
  • Identical prompts and scoring pipeline for all four active models.
  • An invalid or malformed output always counts as a wrong answer — no giving anyone the benefit of the doubt.

03 — Results

The fine-tune wins — on a frontier model's home turf

On a 1,639-question paired sample scored across all four active models:

Detection F1

Did it correctly say the clause is present or absent?

Span F1

Of the clause it found, how much of the true text does its quote actually cover?

Exact match

Is the quote character-for-character identical to the lawyer's annotation?

Four-way comparison — n = 1,639 paired questions
Base 9B (untuned) Fine-tuned 9B GPT-5.6-luna (frontier) GPT-5.6-terra (frontier)

On the active paired sample, the fine-tuned model has the strongest detection F1 at 91.6%, ahead of Terra at 82.0%, Luna at 80.5%, and base at 80.4%. Terra and Luna find more real clauses than the fine-tune, but do so with lower precision and more false alarms. The fine-tune also has the strongest exact-match rate at 59.6%, versus 8.5% for Terra and 10.4% for Luna.

1.4s / 4.3s
frontier latency, p50 / p95 (OpenAI API)
5.6s / 20.0s
ft latency, p50 / p95 (shared eval pool, one L4 — a dedicated deployment would be faster)
Full run, fine-tuned vs base — n ≈ 4,100 questions across all held-out contracts
Base 9B Fine-tuned 9B

Luna and Terra have no bar here on purpose. They were run on the 1,639-question paired sample, while base and fine-tuned are scored on the full held-out run. The like-for-like four-way numbers are the chart above.

+0.099
detection F1, ft − base
95% CI [+0.080, +0.120]
+0.204
span F1 (on true positives), ft − base
95% CI [+0.178, +0.234]
1000 / 1000
bootstrap resamples where ft beat base
n = 1,639 paired questions, seed 43

Per-category explorer

Fine-tuning didn't just move the average. Detection F1 rose on 31 of the 41 clause types, held level on 3, and fell on 7 — the losses are all under 0.08 and all still in the table. Sort or filter to check any of them.

Detection F1 and span F1 by clause type. Base and fine-tuned are scored on the full held-out run; Luna and Terra come from the same 1,639-question paired sample, so treat single frontier rows as indicative. The like-for-like four-way number is the chart above. Δ F1 is fine-tuned minus base.
Category Base 9B F1 Fine-tuned F1 Δ F1 luna F1 * terra F1 Fine-tuned span F1

04 — The Reported Run

One frozen recipe, one reported run

All results in this article use seed 43: the same data pipeline, prompt, scorer, and paired question set for every active model.

0.916 / 0.764 / 0.596
fine-tuned 9B — detection F1 / span F1 / exact match
0.804 / 0.667 / 0.042
base 9B — detection F1 / span F1 / exact match
1,639
paired questions across FT, base, Luna, and Terra

The active frontier comparison uses the identical 1,639-question sample for base, fine-tuned, Luna, and Terra. The fine-tune used LoRA over 4,058 examples for 3 epochs, at about $8.67 and 2.2 H100-hours as recorded by the platform ledger.

The comparison is paired and reproducible from the published seed-43 artifacts: same questions, same parser, same scoring rules.


05 — Methodology & Fairness

The checks behind the numbers

A benchmark win is only as good as the design underneath it. Here's what was — and wasn't — done to keep this one honest.


06 — Real Examples

What the difference looks like on the page

Same contract, same clause type, same instructions — different sense of where the clause actually ends.


07 — The Money

Same accuracy tier, your own weights

The cost figures below apply measured tokens from the active paired sample to the relevant published rates. Terra is much more expensive on this workload, while the case for owning the 9B weights isn't only about the sticker price: you hold the weights, avoid someone else's rate limits, and keep contract text on your own infrastructure.

Per-question inference cost

Fine-tuned 9B: $1.03 per 1,000 questions — measured tokens at published open-model reference rates, not a platform serving bill.

GPT-5.6-luna: $2.15 per 1,000 questions; GPT-5.6-terra: $20.94 per 1,000 questions.

That makes the fine-tune about 2.1× cheaper than Luna and about 20× cheaper than Terra on this measured workload, plus you keep the weights and data.

Training — a one-time cost

$8.67 for 2.2 H100-hours, LoRA over 4,058 examples — as billed by the platform’s credits ledger, not an estimate. It amortizes fast:

Volume$ / question, amortized
1,000 questions$0.00867
10,000 questions$0.00087
100,000 questions$0.00009
1,000,000 questions$0.00001