MaruOpsInfrastructure and AI notes

About (Korean)Contact (Korean)

[Local LLM 15] Validate Structured Responses with JSON Schema

Document spread out in front of the monitor

Reference photo · Document spread out in front of the monitor · Photo: Taduuda taduuda / Source / CC0 · Resized for listings; illustrative photo, not the tested environment

Building a Local LLM · 15/30 · API and Document Search

Full series and learning sequence · Practice code ZIP

An answer passed to another program needs a predictable structure. Even a greeting before a JSON object can prevent parsing. Check the response format separately from the correctness of the values inside it.

We use the common functions from Part 13. It sequentially checks JSON grammar, field data types, and consistency with the original text.

JSON Schema definition

By passing JSON Schema to Ollama’s format field, you can specify the required fields and data types. It helps the program get a readable format. However, it is not possible to judge from the schema alone whether a person in charge or a date that was not in the original text was created.

Items not found are marked as null in this example. It is easier to handle unspecified items if you separate them from empty strings. Standards for interpreting units, time zones, and dates are also defined for actual business data.

Comparison of extracted values with the original text

import json
from llm_http import post, MODEL

schema = {
    "type": "object",
    "properties": {
        "time": {"type": ["string", "null"]},
        "retention_days": {"type": ["integer", "null"]},
        "owner": {"type": ["string", "null"]}
    },
    "required": ["time", "retention_days", "owner"],
    "additionalProperties": False
}
response = post("/api/chat", {
    "model": MODEL,
    "messages": [{"role": "user", "content":
        "메모: 백업은 매일 02시에 실행하고 14일 보관한다. "
        "스키마에 맞춰 추출하라. 없는 값은 null. 스키마: " + json.dumps(schema)}],
    "format": schema, "stream": False,
    "options": {"temperature": 0, "num_ctx": 4096, "num_predict": 256}
})
data = json.loads(response["message"]["content"])
if set(data) != {"time", "retention_days", "owner"}:
    raise ValueError("Unexpected fields")
if data["time"] != "02시" or type(data["retention_days"]) is not int:
    raise ValueError("Check time format and number type")
if data["retention_days"] != 14 or data["owner"] is not None:
    raise ValueError("Extracted facts do not match this sample")
print(json.dumps(data, ensure_ascii=False, indent=2))
.\.venv\Scripts\python.exe .\structured_demo.py

The sample specifies the hour as 02 followed by the Korean hour suffix. If the output is 02:00, distinguish a different display format from a factually wrong time. Production code can normalize time values before comparison. json.loads parses JSON syntax; it does not validate a complete JSON Schema.

Grammar, schema, and business rule inspection

inspectionProblems that can be caught
JSON parsingIncorporation of unclosed parentheses and explanatory text
Schema validationMissing field, wrong data type, unexpected item
work rulesStorage period is negative/exceeds acceptable range
original text comparisonMaking up people in charge and misreading numbers

The code below directly checks the fields and textual facts of a small sample. If it is a complex app, it is better to separate the inspection of libraries such as jsonschema from the inspection of business rules. Pass validation before saving the model results or converting them into commands.

Validation failures and retry limits

If validation fails, check to see if the input is ambiguous or if you are putting too much work into the model. You can ask again by telling us the reason for the failure, but limiting the number of times and for how long. Values ​​that are not confirmed until the end are not automatically saved and are left for manual review.

Requesting complex objects from a small model at once may result in omissions. Another way is to separate document-specific item extraction and final assembly. In this case, the document ID and source location are kept together to prevent values ​​from different original texts from being mixed.

reference material

Documentation and model tags checked: October 18, 2026. Primary lab environment: Windows 11 x64.