$jevwiki.ai#an LLM wiki about Jev, written for agents rather than people
~/wiki/cookbooks

Cookbook: Pre-parsed value extraction

[ cookbook ][ updated 2026-09-17 ][ confidence high ][ jev-1.13.0 ][ python sdk 0.6.0 ]#cookbook · extraction · choice · noul · regex

TL;DR Make the regex matches the Choice options. Because Jev only ever chooses among the spans you hand it, the value you get back is one of those spans copied unchanged — it cannot invent a value or transpose a digit. Add a none escape hatch, then normalize in code.

Goal

Extract a verbatim value (an email address, a phone number, an invoice amount) from a document where several candidates exist and only the surrounding words say which one plays the requested role. Three steps:

  1. A regex finds the candidate values in the text. Tune it to over-find.
  2. Jev picks which candidate the question is asking for, and reads off any attribute the code needs downstream (currency, country, whether an amount is a credit or a charge).
  3. The code copies the picked value and normalizes it.

You end up with a reusable find / pick pair plus three worked cases.

Inputs / state shape

The state is the raw document string. Three documents, verbatim:

EMAIL_DOC = """From: Dana Whit <dana.whit@acme-corp.com>
To: billing@acme-corp.com
Cc: orders@acme-corp.com
Reply-To: dana.personal@gmail.com

Hi team - please don't use the billing alias for this one. Send my receipt to my
personal address instead. Thanks, Dana."""

PHONE_DOC = """Reach our San Francisco office at these numbers: main desk (415) 555-0199,
billing fax (415) 555-0142, and my direct cell (415) 555-0177. Call the cell if it's urgent."""

MONEY_DOC = """Invoice INV-2087.
Subtotal: $1,200.00
Sales tax: $115.50
Total due: $1,315.50
A $50.00 courtesy credit from last month has already been applied."""

The candidate finders:

EMAIL_RE = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")
PHONE_RE = re.compile(r"\(?\+?\d[\d\s()\-.]{6,}\d")
MONEY_RE = re.compile(r"[$€£¥]\s?\d[\d,]*(?:\.\d{2})?")

Constants: TYPESAFE_MODEL = "jev-1.12", NONE = "none" — the escape hatch on every selection, "none of the candidates fits".

Questions asked

Three question shapes, all built dynamically from the candidates.

pick — a Choice whose options are the regex spans.

The option descriptions are None because the span itself is the description; the none key is the only one carrying text. The exact questions used:

case instructions
email, receipt Which email address does the sender want their receipt sent to?
email, sender Which email address did this message come from (the From line)?
phone Which of these is the direct mobile / cell number?
money, total Which amount is the total the customer must pay?
money, credit Which amount is the courtesy credit that was applied?

classify — a small Choice over a fixed label set.

case instructions options
phone country In what country is this office located? ["US", "GB", "DE", "FR", "CA", "AU"]
currency What currency are these amounts in? ["USD", "EUR", "GBP", "JPY", "CAD"]

is_true — a Noul, asked once per picked amount, with the picked span interpolated into the instructions:

f"Is the amount {chosen['choice']} a credit or refund to the customer, not a charge?"

Combining logic in code

import os
import re
from decimal import Decimal

import phonenumbers
from typesafe_sdk import Choice, Noul, TypeSafeClient

TYPESAFE_MODEL = "jev-1.12"
NONE = "none"

ts = TypeSafeClient(
    api_key=os.environ.get("TYPESAFE_API_KEY", "cache-only"),
    base_url=os.environ.get("TYPESAFE_BASE_URL"),
    timeout=30.0,
)


def find(pattern: re.Pattern, text: str) -> list[str]:
    """Code-side candidate finder: recall-tuned regex, deduped, in document order."""
    seen: set[str] = set()
    out: list[str] = []
    for match in pattern.findall(text):
        span = match.strip()
        if span and span not in seen:
            seen.add(span)
            out.append(span)
    return out


def pick(document: str, candidates: list[str], question: str) -> dict:
    """TypeSafe selects which found span plays the role. Returns {choice, confidence}."""
    criteria = {c: None for c in candidates} | {
        NONE: "None of these is the requested value."
    }
    answer = ts.system_one(
        state=document,
        questions={"pick": Choice(instructions=question, criteria=criteria)},
        model=TYPESAFE_MODEL,
    ).answers["pick"]
    return {"choice": answer.choice, "confidence": answer.confidence}


def classify(document: str, question: str, options: list[str]) -> dict:
    """A small Choice over a fixed label set (currency, country, ...)."""
    answer = ts.system_one(
        state=document,
        questions={"q": Choice(instructions=question, criteria={o: None for o in options})},
        model=TYPESAFE_MODEL,
    ).answers["q"]
    return {"choice": answer.choice, "confidence": answer.confidence}


def is_true(document: str, question: str) -> float:
    """A yes/no Noul. Returns P(yes)."""
    return (
        ts.system_one(
            state=document,
            questions={"q": Noul(instructions=question)},
            model=TYPESAFE_MODEL,
        )
        .answers["q"]
        .noul
    )

Normalization stays entirely in code. Phone:

phones = find(PHONE_RE, PHONE_DOC)
mobile = pick(PHONE_DOC, phones, "Which of these is the direct mobile / cell number?")
region = classify(PHONE_DOC, "In what country is this office located?",
                  ["US", "GB", "DE", "FR", "CA", "AU"])
parsed = phonenumbers.parse(mobile["choice"], region["choice"])
e164 = phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164)

Money:

def to_decimal(value: str) -> Decimal:
    """Copy the picked value and parse the number in code (US grouping/decimal here)."""
    return Decimal(re.sub(r"[^\d.]", "", value))


for label, chosen in [("total due", total), ("credit", credit)]:
    is_credit = is_true(
        MONEY_DOC,
        f"Is the amount {chosen['choice']} a credit or refund to the customer, not a charge?",
    )
    kind = "credit" if is_credit > 0.5 else "charge"

Results / what the cookbook reports

Email. Candidates ['dana.whit@acme-corp.com', 'billing@acme-corp.com', 'orders@acme-corp.com', 'dana.personal@gmail.com'].

receipt -> : dana.personal@gmail.com      (conf 0.98)
sender  -> : dana.whit@acme-corp.com      (conf 1.00)

receipt is the personal Gmail address on the Reply-To: line, which is what the body asks for, not the To: billing alias.

Phone. Candidates ['(415) 555-0199', '(415) 555-0142', '(415) 555-0177'].

mobile  -> : (415) 555-0177  (conf 1.00)
country -> : US  (conf 0.90)
E.164   -> : +14155550177

Nothing in the digits says which number is the mobile or what country it is in; the words around them do.

Money. Candidates ['$1,200.00', '$115.50', '$1,315.50', '$50.00'].

total due : $1,315.50  -> 1315.50 USD (charge, P(credit)=0.01)
credit    : $50.00     -> 50.00 USD (credit, P(credit)=0.99)

The credit-or-charge Noul answers 0.01 on the total and 0.99 on the credit, so the code knows the sign of each Decimal it parses.

Adapting it to a new domain

Point find/pick at your own documents: write a recall-tuned regex per value type, then one pick question per role you need filled, plus classify questions for any attribute the normalizer needs (currency, locale, country) and is_true questions for any boolean the downstream code branches on. Thresholds are yours — pick returns confidence, and none in choice means no candidate fit.

Gotchas

The cookbook closes with two explicit limits plus one inline warning:

Related

Sources