Skip to main content
You have an LLM answering questions from paragraphs you retrieved for it, and most of its answers are right. Two kinds of mistake are common. The LLM gives an answer the paragraphs never state, filling a missing step with a guess. Or it says the paragraphs don’t answer the question when they do. Neither kind looks any different from a right answer. In this cookbook we check each answer with one Jev request that asks three Noul questions about the paragraphs and the answer:
  • answerable: do the paragraphs state every fact the question needs?
  • declines: does the answer decline, saying the paragraphs don’t have the answer?
  • supported: start from the question and follow the paragraphs step by step. Do you arrive at the LLM’s answer?
A few lines of code turn those three into one risk number, where higher means the answer is more likely wrong. If the LLM declined, the risk is the chance the paragraphs do answer the question. If it answered, the risk is the chance the paragraphs don’t lead to its answer. An answer with a risk of 0.2 or more goes to review. We ran this on 1,000 questions answered by gpt-6-luna. Each question takes two to four steps to answer, with earlier answers needed for later steps. 88.5% of the answers were right. The check passed 73% of the answers, and 95.7% of those were right. The other 27% went to review, and they included 84 of the 115 wrong answers. You end up with check_answer(). It takes a question, its paragraphs and an answer, and returns the three probabilities, the risk, and pass or review.

Setup

then set TYPESAFE_API_KEY and OPENAI_API_KEY. OpenAI models write the answers being checked. In the measurement at the end, an OpenAI model also decides whether an answer is right when it doesn’t match the dataset’s reference answer. The numbers below came from jev-1.14.0 on 2026-11-07, checking answers that gpt-6-luna wrote the same day.

Load the questions and their paragraphs

The questions come from MuSiQue (Trivedi et al., CC BY 4.0). Each one joins two to four simple questions about Wikipedia into one, so the answer to an earlier part is needed to ask a later one. Each comes with 20 paragraphs. Most of them are on nearby topics and don’t help answer the question. MuSiQue has two versions of each question. In one, the paragraphs hold every fact the question needs. In the other, a paragraph it needs has been removed, so the question can’t be answered, though the remaining paragraphs still look as if they might. The file holds a fixed random sample of 1,000 questions from MuSiQue’s development set, with one of the two versions of each. About half are the version that can’t be answered.

Answer them with gpt-6-luna

The instruction lets the model say the paragraphs don’t answer the question, which is where the refusals checked below come from. To check your own LLM, replace answer_prompt() and ask_llm().

Ask Jev three questions about each answer

Each answer gets one Jev request. Its state holds the question, the instruction the LLM was given, the paragraphs, and the LLM’s answer. The three questions go in the same request.

See how the check scores four answers

The check passes the first two and sends the last two to review. In order: a right answer, a right refusal, an answer the paragraphs don’t support, and a refusal of a question the paragraphs do answer.
The first two pass for opposite reasons. The Mud Bath answer gets supported at 0.98, so the paragraphs lead to it. The Assomada answer declines, and answerable is 0.07, so declining was right. Tammy Leitner was born in San Diego, but no paragraph gives San Diego’s population density in 2009. So supported is 0.08 and the risk is 0.92. The Patel question can be answered: one paragraph names Sardar Vallabhbhai Patel as Dahyabhai Patel’s father, and another gives the date he died. The LLM declined anyway. With answerable at 0.86, the refusal goes to review.

Label every answer

To measure the check, every answer needs a label: right or wrong. MuSiQue gives each question a reference answer. A separate Jev request with one Noul question compares the LLM’s answer with the reference. It doesn’t see the paragraphs, and it accepts the same answer in different words. An answer that matches counts as right. One that doesn’t goes to gpt-6.1-sol, which reads the paragraphs and labels the answer right, wrong or unclear. That second step is there because the reference is sometimes wrong about the paragraphs.
739 answers matched the reference. For the other 261, gpt-6.1-sol read the paragraphs and found 146 of them right after all. In each of those, the reference was wrong about the paragraphs in one of two ways. Either MuSiQue counts the question as answerable but the paragraphs skip a step, or the question was meant to be unanswerable but another paragraph still has its answer. That leaves 115 wrong answers.

Measure the check on 1,000 answers

The table compares two ways of using the LLM: take every answer, or take only the answers the check passes. The second is shown at a few thresholds, and an answer passes when its risk is below the threshold. In each row, “how many” is the number of answers used, “right” is the share of those that are correct, and “wrong held back” counts the LLM’s wrong answers that went to review instead.
At 0.2 the check passes 73% of the answers, and 95.7% of those are right, compared with 88.5% across every answer. It holds back 273 answers, and 84 of them are wrong. The other 189 were right, so most of the review work goes to confirming answers that were fine.
output output Right answers are concentrated near zero risk, and wrong answers are spread across the whole range. So the threshold has to be low to hold back most of the wrong answers, and a threshold that low also sends some right answers to review.

Before you use it on your own answers

  • What it misses. 31 wrong answers passed. 18 of them answer a related question instead of the one asked: “Leftover Salmon” when asked who is in the band, “the NFL” when asked what kind of thing the NFL is. The paragraphs do lead to those answers, so supported comes back high. The other 13 are refusals of questions the paragraphs do answer. For those, answerable also came back low, 0.10 to 0.19: Jev missed the same connection between paragraphs that the LLM missed.
  • Set the threshold on your own answers. The labelling step works on any set of questions that has reference answers. Swap in your questions, paragraphs and reference answers, run it again, and pick the threshold from the table.
  • What the numbers rest on. The right and wrong labels come from models, so a stricter or looser re-check would change the 88.5%. We picked the three check questions over two other sets by trying them on the first 100 questions of this sample. Those 100 helped make the choice, so the results on them are not a fair test.

Open it in the playground

The link below opens the Patel refusal in the playground, with its question, paragraphs, answer and the three check questions filled in. Run the same request there, and edit the questions in the browser.
Open in the TypeSafe playground →