// What the extraction does with one page, decided from the reader's own classification (ocr-service // OCR3.15) and nothing the model says: whether the page is read at all, whether the model is shown the // image besides the text, and which of the page's lines make up the text it is shown. // // scan the recognised text is a reading, not a record: image and text, the text marked as low trust // table image and text: the grid is better read than recognised // text text alone, unless the page is weak by the reader's own measure (isWeakPage) // drawing left out by default: tens of thousands of characters of labels, no specification in them // empty left out by default // // A class in `excluded` is never read, whatever the rule above; the deployment chooses the list. import type { PageClass } from "../contract/index.js" import type { ReadPage } from "./ports.js" import { isWeakPage } from "./verify.js" export type PagePlan = | { readonly kind: "skip" } | { readonly kind: "read" /** The model should be shown the page image besides the text. */ readonly image: boolean /** The text is a recognition of an image and may be wrong: the prompt says so, and the image wins. */ readonly lowTrustText: boolean } export function planPage(page: ReadPage, excluded: readonly PageClass[]): PagePlan { if (excluded.includes(page.class)) return { kind: "skip" } switch (page.class) { case "scan": return { kind: "read", image: true, lowTrustText: true } case "table": case "drawing": return { kind: "read", image: true, lowTrustText: page.source === "ocr" } case "text": return { kind: "read", image: isWeakPage(page), lowTrustText: false } case "empty": return { kind: "read", image: false, lowTrustText: false } } } /** * The text of a page as the model is shown it: the lines in reading order without the ones the reader * flagged as repeating on most pages (a running header, a footer, a page stamp), which are the * document's furniture and not its content. A page the reader returned no lines for is its text as is. */ export function promptTextOf(page: ReadPage): string { if (page.lines.length === 0) return page.text return [...page.lines] .sort((a, b) => a.order - b.order) .filter((line) => !line.repeated) .map((line) => line.text) .join("\n") }