Use cases

How to extract key terms from contracts

Extraction looks easier than classification until you have to say what counts as right. A renewal term can be written a dozen ways, and a clause that isn't there is an answer too.

The pain points

How to do it

  1. Write the schema first. Every field gets a type (date, duration, amount with currency, enumerated value, short text), a normalized form, and an explicit "not present". The schema is the contract between the prompt and everything downstream.
  2. Label from records you already keep, such as the contract-management system or the renewal calendar, and spot-check a sample against the documents.
  3. Score each field on its own terms. Equality on normalized dates and enumerations, a numeric tolerance on amounts, word-overlap F1 on short text. Keep each field as its own metric so you can see which one a rewrite broke.
  4. Weight fields by what they drive, and score precision and recall separately on "present". That keeps "always say missing" from looking good.
  5. Hold out by counterparty or template. Contracts from one paper template are near-duplicates. If they sit on both sides of the split, the score is flattering.

Pitfalls worth checking first

PitfallWhat it looks likeHow to check, before spending anything
"Not present" winsHigh field accuracy, low recall on clauses that existScore recall on present clauses separately, per field.
Template duplicatesGreat hold-out score, poor on new counterpartiesSplit by template or counterparty, not by document.
AmendmentsThe base agreement's term is extracted, the amendment's is notInclude amendments with the base document, and label the term in force.
Unnormalized labelsCorrect answers scored as wrongNormalize labels and outputs the same way before comparing.
Judge driftScores rise, answers do not get betterPrefer deterministic scorers wherever the field allows one.

References

Tools that run this loop: DSPy and its GEPA optimizer, bpto (ours, open source), and Impromptune, the studio built on it.