Structured Output & Schema Validation
Relevant source files
The following files were used as context for generating this wiki page:
Structured Output & Schema Validation governs the lifecycle of data generated by Large Language Models (LLMs) and user interactions within Oddity 1. The system ensures that AI-generated annotations, PDF summaries, and system prompts adhere to strict formatting requirements before they are rendered in the browser extension or exported.
This module enforces data integrity through three primary mechanisms: JSON-only system prompts for LLM instructions, Zod-based validators for backend payloads, and streaming parsers for progressive rendering. By validating outputs at the boundary of the backend and the extension, the project prevents malformed data from causing rendering errors in the Core Annotation Engine.
Sources: README.md:123-145, backend/config/prompts.json:1-50, backend/lib/pdf-page-summary-validator.ts:3-13
LLM Output Structuring
The backend utilizes complex system prompts to force LLMs into returning valid JSON arrays without preambles or markdown fences. These prompts define the exact fields, character limits, and structural rules (such as chunk contiguity) that the AI must follow.
Prompt Configuration Structure
The system prompts are categorized by intensity and task type, defining exactly how the LLM should format its response.
| Prompt Type | Output Format Requirement | Key Constraint |
|---|---|---|
| Overview | JSON Array of objects | Contiguous chunks; verbatim substrings for anchors |
| Provocateur | JSON Array of objects | Max 2 sentences per annotation; zero anchor overlap |
| PDF Summary | Flat JSON object | Single field summary; max 320 characters |
| Prompt Gen | Plain text | No markdown fences; maximum 400 words |
Sources: backend/config/prompts.json:67-108, backend/config/prompts.json:237-268, backend/config/prompts.json:281-295
Structured Response Workflow
The following diagram illustrates how the system requests and processes structured data from the LLM.
The workflow ensures that only validated JSON reaches the extension's rendering engine.
Sources: extension/src/background/index.ts:314-368, backend/config/prompts.json:62-66
Backend Schema Validation
The backend uses schemas to validate incoming data from the LLM and the extension. Specifically, for PDF processing, a validator ensures that generated summaries meet length and presence requirements.
PDF Page Summary Validation
The system employs zod to define a PdfPageSummaryPayloadSchema. This schema validates that the summary field is a non-empty string with a maximum length of 600 characters.
const PdfPageSummaryPayloadSchema = z.object({
summary: z
.string()
.trim()
.min(1, "summary is required")
.max(600, "summary must be 600 characters or fewer"),
});
Sources: backend/lib/pdf-page-summary-validator.ts:3-9
The validatePdfPageSummary function returns a result object containing either the validated data or a list of specific error messages.
Sources: backend/lib/pdf-page-summary-validator.ts:11-30
Extension-Side Processing
The extension handles structured data through streaming and PDF export preparation. It ensures that the received JSON objects are mapped correctly to the DOM.
Streaming Annotation Handling
When annotations are requested, the extension's background script handles a streaming JSON response. It validates that the user is authenticated before initiating the request and uses an AbortController to cancel stale requests if the content changes during processing.
- Auth Verification: Checks for a valid Supabase session before sending the payload.
- Payload Truncation: Ensures the text sent to the LLM does not exceed
MAX_TEXT_LENGTH. - Incremental Parsing: The
requestAnnotationsStreamingfunction receives individual annotation objects and forwards them to the content script.
Sources: extension/src/background/index.ts:308-360, CHANGELOG.md:83-95
Export Data Sanitization
Before exporting annotations to a PDF, the extension sanitizes the host-page HTML. This process removes non-content elements and ensures all images use absolute URLs to maintain a clean document structure.
- Junk Removal: Strips tags like
script,style,svg,button, andnav. - Attribute Stripping: Removes all attributes except for essential ones like
src,href,alt, andtitle. - URL Resolution: Converts relative
img[src]paths to absolute URLs using the window location.
Sources: extension/src/content/export-pdf.ts:77-108
Data Model Summary
The structured data exchanged between the backend and extension relies on the following fields:
| Field Name | Type | Source | Description |
|---|---|---|---|
chunk_start | String | LLM | Verbatim phrase starting a text chunk (8–15 words). |
anchor | String | LLM/User | The exact verbatim substring being annotated. |
label | String | LLM | A structural role or title (max 5-10 words). |
summary | String | LLM | Structured markdown summary for overview mode. |
content_hash | String | Extension | A unique identifier for the text being annotated. |
Sources: backend/config/prompts.json:44-58, backend/lib/pdf-page-summary-validator.ts:3-9, extension/src/background/index.ts:327-335
Conclusion
Structured Output & Schema Validation ensures that the Oddity 1 platform maintains high data quality across AI generation and user interactions. By combining strict system prompt constraints, Zod-based backend validation, and robust extension-side sanitization, the system provides reliable annotations and exports while minimizing the risk of malformed data entry or rendering failure.