---
title: "Document Review With Unsiloed and TypeSafe Jev"
slug: document-review-with-unsiloed-and-typesafe-jev
url: https://listedarticles.com/articles/document-review-with-unsiloed-and-typesafe-jev
canonical_url: https://www.unsiloed.ai/blog/document-review-unsiloed-typesafe-jev
content_type: blog_post
language: en
published_at: 2026-10-01T00:00:00.000Z
updated_at: 2026-10-13T11:12:17.407Z
authored_by: human
publisher: "Unsiloed AI"
publisher_url: https://listedstartups.com/companies/unsiloed-ai
topics: ["AI", "Developer Tools", "Product", "Tutorials"]
about: ["https://listedstartups.com/companies/typesafe-ai", "https://listedstartups.com/products/jev"]
license: all-rights-reserved
word_count: 1330
reading_minutes: 6
citation: "Unsiloed AI. \"Document Review With Unsiloed and TypeSafe Jev.\" 1 Oct 2026. https://www.unsiloed.ai/blog/document-review-unsiloed-typesafe-jev (all-rights-reserved)"
# The full text follows. The web page shows an extract and sends readers
# to the source above; quote the citation and link the canonical URL.
---

# Document Review With Unsiloed and TypeSafe Jev

> Unsiloed AI and TypeSafe’s Jev show a document-review pipeline that pairs extraction with schema-validated checks so OCR-correct but semantically wrong values (like an extra zero) are caught before they flow downstream.

An extraction pipeline can read a value correctly and still pass bad data downstream. A clearly printed extra zero survives excellent optical character recognition (OCR).

Using Unsiloed and TypeSafe’s Jev together helps us check for OCR failures and general mistakes in a document. Unsiloed extracts structured fields and locates them on the page. Jev judges the extracted information against focused questions. We can combine these results to decide which fields need review.

## Jev Turns Focused Questions Into Typed Answers

A Jev request separates the information it considers (`state`) from the [decisions it makes](https://docs.typesafe.ai/introduction) (`questions`). In our workflow, state contains the records Unsiloed extracted and the context needed to interpret them. Each question tells Jev what to check and which answer type to return; it can also define criteria for the possible answers.

The type determines what our code receives. A **Noul** returns the probability that a statement is true. A **Choice** selects from named options; a **Score** evaluates a rubric of ordered levels. Choice and Score also return a probability distribution and a [confidence value](https://docs.typesafe.ai/confidence) summarizing its concentration. Noul has no separate confidence field.

The three types can share state in a single request, as the diagram shows. Later, we'll use only Noul in our example.

![Image 1: Shared state feeds independent Noul, Choice, and Score questions. Noul returns P(yes); Choice and Score also return distributions and confidence. Application code interprets the answers. This demo uses only Noul.](https://www.unsiloed.ai/blog-assets/unsiloed-jev/jev-question-contract.png)

A [Noul](https://docs.typesafe.ai/primitives/noul) value of `0.04` means a 4% probability of **yes** to our question, a strong **no**. It does not mean “Jev is 4% confident.” Values near either end indicate a clear direction; values near the middle deserve caution.

## Send Unsiloed’s Extracted Fields to Jev, Then Route the Results

Unsiloed preserves what is printed and provides confidence scores that help identify ambiguous readings. For our example, we use a medication list with six rows. A coffee stain obscures one dose, while another row contains a clearly printed but implausible quantity. We'll follow both through extraction and Jev's checks.

![Image 2: Medication list with six rows: a coffee stain obscures the cetirizine dose, and the ibuprofen instruction reads “10 tablets” three times daily.](https://www.unsiloed.ai/blog-assets/unsiloed-jev/prescription-demo.png)

Our [extraction schema](https://www.unsiloed.ai/docs/document-processing/extraction/schemas) defines the fields Unsiloed should return for each medication. It requests the complete dose cell, including quantity and unit, without correcting surprising quantities or guessing obscured text from usual prescribing practice. Enable source citations with `enable_citations=true` and wait for the extraction job to complete before constructing Jev’s state.

Each field has two [Unsiloed confidence scores](https://www.unsiloed.ai/docs/api-reference/extraction/extract-data): `extraction_score` measures confidence in the extracted value, while `grounding_score` measures confidence that the value was located in the document. Both range from zero to one. The citation identifies its page and bounding box, the rectangle around the source text.

Here is the stained cetirizine dose from the saved response, with pixel coordinates on the original 1,200 × 1,500 image:

```
{
  "value": "1 tablet",
  "score": { "grounding_score": 0.76, "extraction_score": 0.74 },
  "citation": {
    "page": 1,
    "bbox": [582, 975, 649, 994],
    "page_width": 1200,
    "page_height": 1500
  }
}
```

Assign each medication row an ID, such as `row-5`, and keep it with the extracted fields and their citations. This lets our code match Jev’s answer to the same row later. Keep the citations so reviewers can locate each extracted field on the original page.

Send Jev the extracted values and context. It judges the instruction as extracted, without seeing the image or Unsiloed scores. We ask one Noul question per row: is this dose and frequency plausible for this medicine? All six rows share one request, with [each question evaluated independently](https://docs.typesafe.ai/primitives#ask-multiple-questions-together).

In the server-side module that connects the two APIs, construct this request (one row and its question shown):

```
const request = {
  model: "jev-1.13.0",
  state: {
    context: "Check for obvious quantity, unit or frequency errors. " +
      "Dose means amount taken each time, not supply quantity. " +
      "Do not assess patient-specific safety or propose corrections.",
    careContext: "Adult outpatient medication reconciliation, age 52",
    medications: [{
      id: "row-5", medicine: "Cetirizine 10 mg tablet",
      dose: "1 tablet", frequency: "Once daily as needed",
      route: "Oral", instructions: "For allergy symptoms."
    }]
  },
  questions: {
    "row-5": {
      type: "noul",
      instructions: {
        question: "Is the extracted dose and frequency plausible on its " +
          "face for this medicine and strength in the stated adult " +
          "outpatient context, without an obvious quantity or " +
          "frequency transcription error?",
        row_id: "row-5"
      },
      criteria: {
        true: "Plausible on its face; no obvious quantity, unit or frequency error.",
        false: "Clearly implausible; warrants review of the original prescription."
      }
    }
  }
};
```

The context and criteria are shortened here; the [recorded request](https://www.unsiloed.ai/blog-assets/unsiloed-jev/jev-request.json) contains the exact text and all six rows. We use `row-5` as the question ID so our code can match the answer to that row. We also include it as `row_id` inside the instructions so Jev knows which record to judge: question IDs [are not sent to the model](https://docs.typesafe.ai/primitives/noul#request-structure).

Post the request as JSON to `https://api.typesafe.ai/v1/systemone`. Authenticate with your TypeSafe API key in the [`Authorization: Bearer <API_KEY>` header](https://docs.typesafe.ai/api), keeping the key on the server. The recorded answer at `answers["row-5"]` is `{ "type": "noul", "noul": 0.94 }`. Match that answer to the saved `row-5` extraction using the shared ID.

Our code now decides whether the row needs review. For the reading check, we take the lowest Unsiloed score across the row’s fields, so a low score on any field flags the whole row. For the plausibility check, we use Jev’s `noul` value.

In the same module, pass those two values as `reading` and `plausible` to this function. It returns the reasons to send the row for review, or an empty array when neither check flags it. These demo rules also flag missing or invalid scores:

```
const valid = n => Number.isFinite(n) && n >= 0 && n <= 1;
function reviewReasons(reading, plausible) {
  return [
    ...(!valid(reading) || reading < 0.90 ? ["Verify source reading"] : []),
    ...(!valid(plausible) || plausible < 0.50 ? ["Review instruction"] : [])
  ];
}
```

Here, a reading score below 0.90 or a plausibility answer below 0.50 triggers review. These are example cutoffs: test them against manually reviewed documents before using them in production. Jev answers near 0.50 may also need review because neither yes nor no is clearly favored.

Keep both reasons when both checks fail. A plausible instruction can still contain misread text, so a high Jev answer must not cancel a low Unsiloed score. Save the original extraction and Jev request and response alongside the reviewer’s decision so you can later check why a row was flagged and how it was resolved.

## Follow the Flagged Rows From Extraction to Review

Step through the saved API results to see what Unsiloed reads, what Jev checks, and why the two flagged rows need different kinds of review.

For the stained cetirizine dose, Unsiloed extracts “1 tablet” with an extraction score of 0.74 and a grounding score of 0.76. Jev returns `0.94` for plausibility, but it never sees the stain. That judgment depends on the extracted text being right. The reading check still flags the row because someone must confirm the obscured mark.

The ibuprofen row reverses the pattern. Unsiloed reads “10 tablets, three times daily” with both scores at 0.99; Jev returns `0.04` for the same plausibility question. The reviewer needs to investigate the clearly printed instruction. Neither model substitutes an assumed intended dose.

Each check flags a review need the other misses. The other four rows clear both demo thresholds, as the [recorded responses](https://www.unsiloed.ai/blog-assets/unsiloed-jev/receipts.json) show. The explanations and routing labels come from our application; Jev returns the typed answers, not those explanations.

## How Much Jev Adds Per Document

One medication list in this demo produces a Jev request with six questions and **1,812 input tokens**. At Jev 1.13.0’s [published price of $42 per billion input tokens](https://docs.typesafe.ai/models), with output free (checked September 30, 2026), that adds **$0.000076 per document**. Processing **100,000 similar documents would add about $7.61** in Jev charges.

This is a Jev-only estimate; Unsiloed extraction and human review cost separately. Your actual charge depends on the text and questions sent. For a closer estimate, take the `input_tokens` from a representative Jev response and apply the published rate.
