Build a local AI feature

Request structured output

Use a JSON schema to constrain the model response, then validate the returned value before the application trusts it.

Asking for “valid JSON” in a prompt is weaker than providing a schema. Models drift. Schemas give the runtime a concrete target.

Ollama accepts a JSON schema in the format field:

const summarySchema = {
  type: 'object',
  properties: {
    summary: { type: 'string' },
    confidence: { enum: ['low', 'medium', 'high'] },
  },
  required: ['summary', 'confidence'],
  additionalProperties: false,
}

Send that schema with stream: false. Put the same output requirements in the prompt so the task and structure agree. If the prompt asks for three paragraphs but the schema allows one string, you are fighting yourself.

A constrained response is still untrusted input. Parse the JSON, check both fields, enforce the sentence length, and compare factual claims with the source data where possible. Did the model mention 52 minutes when the record says 40? Reject or fall back.

A JSON schema can guarantee shape. It cannot guarantee truth.

Use a low temperature when consistency matters, then test whether the chosen model follows the schema reliably. Small models sometimes omit required keys under pressure. Your validator should catch that and route to the deterministic path.

Log parse failures separately from HTTP failures. “Invalid JSON” and “schema mismatch” tell you to adjust prompts or upgrade models. “Connection refused” tells you to start Ollama.

Put the schema in the request body beside your messages:

body: JSON.stringify({
  model: 'gemma3:1b',
  messages: [{ role: 'user', content: prompt }],
  format: summarySchema,
  stream: false,
}),

Run one call and inspect the raw string before you trust it. You should receive a single JSON object, not markdown fences around JSON.

Try this on your own project: send one activity record with the schema attached and assert the parsed object validates before you wire the UI. One green test here saves hours of frontend guessing.

Lesson completed