Jev for analytics: turn text columns into gold, in plain SQL TypeSafe's Jev classified 100,000 complaint narratives in 82.2 seconds using its prompt_jev() function, with no LLM generating the per-row answers, according to a launch benchmark that put Jev at $0.50 per 100,000 rows versus $1.58 for gpt-5-nano and $37.58 for GPT-5.6 Terra. On the same complaints, gpt-5-nano through prompt() needed 6 minutes 9 seconds for only 10,000 rows, where Jev took 12.5 seconds. Jev is described as a "System One" model that reads text once and scores a fixed list of allowed answers, returning a typed label, probability, or score with a confidence value instead of free text. Every now and then, we all end up with a table that has a big text column. A comment, some customer feedback, or worse, an address nobody parsed upstream. There are insights in that column, but they're hard to get out. And sometimes it's plain extra compute you keep paying for: the address never got parsed into typed columns, so every query parses text again, and parsing text is $$$. Let's take a dataset with 100,000 complaints. Each row has a narrative someone explaining what went wrong with a bank, a lender, or their credit report and how the company responded. The column I actually want is missing: what was the person asking for? It sounds like a job for an LLM. But running an LLM over every row just to pick one of seven known answers is like using a cannon to kill a fly. It's slow on a big table, so it scales badly, or it just burns your credit card. prompt jev classified the 100,000 rows in 82.2 seconds, with no LLM generating the per-row answers. On the same complaints, gpt-5-nano through prompt needed 6 minutes 9 seconds for only 10,000 rows Jev: 12.5 seconds . On cost, the launch benchmark put Jev at $0.50 per 100,000 rows, against $1.58 for gpt-5-nano and $37.58 for GPT-5.6 Terra API prices . That's about 1% of the frontier model's bill. Faster and cheaper? Let's look at what Jev does, run it on the dataset, and see where I would and wouldn't trust the result. What Jev does TypeSafe calls Jev a "System One" model, borrowing from Kahneman's Thinking, Fast and Slow. System 1 is the quick, intuitive answer. System 2 is the slow, deliberate one. A classic LLM is System 2: it reasons and writes its answer token by token. Jev is System 1: it reads the text once and scores the answers you allowed. System 2: a classic LLM System 1: Jev How it answers Writes text, token by token Scores a fixed list of answers in one pass What you get back Free text you parse it, or force a schema A typed label, probability, or score Can invent a new answer Yes No, only the options you give it Tells you how sure it is Not directly A probability per option, plus a confidence 100k rows benchmark 18 to 32 minutes, $1.58 to $37.58 40 seconds, $0.50 Good at New taxonomies, summaries, explanations The same bounded decision over many rows Example: customer request: "Please refund the two fees you charged me." Answer is something like "The customer is asking for a refund of the two fees..." a sentence to parse For SQL, think of it as a smart decision function: you give it one row of text, a question, and the allowed answers. You get back a typed decision, plus a number that tells you how sure it is. There are three question shapes. Here they are on the same real complaint 10306039, someone charged low balance fees on an account they had closed : Shape You ask You get back Real answer SQL use Choice "What outcome is the consumer asking for?" + 7 labels one label + confidence refund or charge reversal, 0.95 GROUP BY Noul "The complaint is about fees the bank charged." a probability, 0 to 1 0.97 and 0.02 for "reports identity theft" WHERE Score "How urgent is this?" on low / medium / high a position on the scale + confidence 1.62 0 = low, 2 = high , 0.43 ORDER BY This walkthrough uses Choice, since each complaint should land in one request category. How does that compare to what you already use? An LLM is the right tool for a new taxonomy, a summary, or an explanation. A schema can hold it to your labels, but it still writes each one out token by token. Jev picks from your list, so you always get back one of your strings. CASE WHEN or a regex only works when the rule is literal. People write "reverse the charge" instead of "refund", and mentioning money isn't always asking for it. A trained classifier scales well but is painful to run labelled examples, a model to maintain . With Jev, you describe the categories in the query and try them right away. Parsing rules JSON paths, address parsers are static and break when the format changes. Jev works from what the text says, so messy input hurts it less. Jev can only return one of the options you gave it, so poor options get you a neatly typed poor answer. Garbage in, garbage out. About the dataset: complaints from CFPB The complaints come from the U.S. Consumer Financial Protection Bureau CFPB's archive , the agency that collects complaints about banks, lenders, credit bureaus, and other financial services. My table complaints 100k has spoiler alert 100,000 rows with complaint id, narrative, company response, and a few other fields. Here's what four rows look like: complaint id product narrative trimmed company response 9906201 credit reporting "This account is incorrectly being reported as a charged off account with a balance due. Please provide proof of the charge off and update the balance to {$0.00}..." Closed with explanation 10306039 bank account "I closed my Chase checking account in XXXX by sending Chase a letter via mail. Chase conveniently ignored the account closure request so they can charge low balance fees..." Closed with monetary relief 6084737 debt collection "I have no outstanding debts owed that I am aware of. Americollect has called numerous times almost daily..." Closed with explanation 2042216 credit card "I paid my credit card with a money order. They did not apply the payment to my account..." Closed with monetary relief Let's get the gold out of that narrative column. Step 1: define the labels, then classify Before classifying 100,000 rows, we need the categories. I sampled 40 narratives and asked MotherDuck's prompt function, running gpt-5-mini, to suggest seven requested-outcome categories. That took 7.6 seconds. How you sample matters and you can take a bigger one , but that's a business question more than a technical one. Then Jev classifies every row against these categories, in less than 2 minutes: Jev requires the question and the choices to be constants, so the simplest way is to paste the taxonomy straight into choice :=. Here's the classification step, with the same labels and descriptions as the measured run: CREATE TABLE complaint requests AS SELECT complaint id, company response, prompt jev narrative, 'What outcome is the consumer asking for?', choice := {label: 'refund or charge reversal', description: 'Consumer requests money returned, reversal of fees/charges, or reimbursement.'}, {label: 'correct or remove credit report entry', description: 'Consumer asks to fix, update, or remove inaccurate items on their credit report.'}, {label: 'investigate and credit transaction error', description: 'Consumer requests investigation and correction of a transaction or deposit error and credit to their account.'}, {label: 'stop harassment or contact', description: 'Consumer asks for communications or collection calls/texts/emails to stop or follow rules.'}, {label: 'address identity theft or fraud', description: 'Consumer requests action to resolve identity theft, fraudulent accounts, or unauthorized inquiries.'}, {label: 'explain decision or account status', description: 'Consumer asks for clarification or explanation of a decision, account action, or why charges occurred.'}, {label: 'other', description: 'Any requested outcome that does not fit the categories above.'} AS request FROM complaints 100k; request is a struct. request.choice is the picked label, and request.confidence and request.probabilities help you inspect the decision. Here's what came back for the Chase fees complaint 10306039 : { choice: 'refund or charge reversal', confidence: 0.95, probabilities: {value: 'refund or charge reversal', probability: 0.96}, {value: 'other', probability: 0.03}, {value: 'explain decision or account status', probability: 0.01}, ... -- the other 4 labels at 0.00 } Bonus: keep the labels in a table Pasting 7 labels into a query is fine once. If the taxonomy sticks around versioned, shared across queries, edited by the business , you'd rather keep it in a table. A subquery in choice := doesn't work "choice" parameter must be a constant value , but a DuckDB variable does, because it's resolved before the query runs: SET VARIABLE request labels = SELECT list {label: label, description: description} ORDER BY label FROM request taxonomy ; SELECT complaint id, prompt jev narrative, 'What outcome is the consumer asking for?', choice := getvariable 'request labels' AS request FROM complaints 100k; Why bother: one source of truth for the labels, easy to version add a taxonomy version column , and the business can review the labels without reading SQL. Step 2: don't trust Jev blindly Jev can't invent a label, but it can still pick the wrong one. The first thing to look at is confidence. Jev scores every label, and confidence says how concentrated those scores are: 1.0 when one label takes everything, low when two or three labels share the probability. Across the 100,000 rows, the mean confidence is 0.83, 65.8% of rows are at 0.8 or above, and 10.9% are below 0.5. SQL gives you the review queue: SELECT complaint id, request.choice, request.confidence FROM complaint requests WHERE request.confidence < 0.8 ORDER BY request.confidence; 0.8 is an example, and a row above it can still be wrong. Send uncertain rows to a human or a bigger model, and keep the rest in the analytics table once you've validated that cut on your data. The second check is to compare against another model on a sample. On 300 rows, I labelled them twice: with GPT-5 through prompt the newest model MotherDuck's prompt offers today and with Claude Opus 5.5, which read each narrative blind, without seeing any other label. Here's what came out: Comparison on 300 rows Agreement GPT-5 vs Claude Opus 5.5 72.7% Jev vs GPT-5 77.3% Jev vs Claude Opus 5.5 74.0% Jev, on the 218 rows where GPT-5 and Opus agree 90.4% Jev, on those rows with confidence = 0.8 161 rows 96.9% The two big LLMs agree with each other less often than Jev agrees with either of them. So the task itself is fuzzy: most disagreements sit on the boundaries we already saw identity theft vs credit-report fix, "other" vs a specific label . Step 3: ask the question the good boring part Once the requested outcome is a typed column, it's plain SQL: SELECT request.choice AS requested outcome, count AS complaints, round 100.0 avg company response = 'Closed with monetary relief' ::INT , 1 AS pct monetary relief FROM complaint requests GROUP BY 1 ORDER BY complaints DESC; It runs in 0.9 seconds on MotherDuck. The 82.2 seconds of classification happen once, and every question after that costs what any other GROUP BY costs. When I would use this pattern Use prompt jev when the same decision repeats across many rows and you can write the possible answers down: complaint intent, product family, "did they ask for a refund?", a severity rubric. Use an LLM when you need new categories, generated text, or an explanation a human will read. Or use both, like here: the LLM helps design the question, Jev applies it at scale. The MotherDuck launch benchmark classified 100,000 short news articles in 40 seconds. My 82.2-second complaint run is a different task longer narratives, seven described choices , so I wouldn't promise either number on your table. Test on a sample first : prompt jev is available on MotherDuck paid plans. The text is sent to TypeSafe for inference, so check your data-handling requirements before passing sensitive customer data. The guide and function reference have the full syntax. Define your dashboards in YAML with dbt Charts, then the same dbt build that runs your pipeline deploys them to MotherDuck Dives. Just 2 config changes Your Dives will refresh live whenever your stakeholders take a look. See how we constructed the dbt package as well. Common Crawl publishes petabytes of web crawl data on S3. With DuckDB and MotherDuck you can query the Common Crawl dataset directly, no cluster and no download, and measure how fast the vibe-coded web is growing.