Session 6· 09· 10 min
Structured Output with a JSON Schema
What you'll learn
- ▸Pass a raw JSON schema dict to with_structured_output()
- ▸See when a schema is preferable to a Pydantic class
- ▸Wrap up Session 6 and prep for the projects
Sometimes you do not want a Pydantic class — maybe the schema is loaded from a config file at runtime, or it comes from a user. LangChain accepts a plain dict schema too. Same return shape, different input type.
scripts/09_structured_output_json_schema.py
schema = { ①
"title": "Weather",
"description": "Weather info for a city",
"type": "object",
"properties": {
"city": {"type": "string"},
"temp_c": {"type": "number"},
"condition": {"type": "string"},
},
"required": ["city", "temp_c", "condition"],
}
structured = model.with_structured_output(schema) ②
result = structured.invoke("What is the weather in Madrid?") ③
print(result) ④①A plain Python dict — standard JSON Schema, same rules you learned in Session 5 Phase 1.
②Pass the dict instead of a Pydantic class.
③invoke returns a dict (not a Pydantic instance) since you passed a dict schema.
④You index the result with dict keys: result["city"], result["temp_c"].
$ python scripts/09_structured_output_json_schema.py
When to use a dict schema
Dict schemas are the right choice when the shape is dynamic — loaded from YAML, user-supplied, or assembled at runtime. Use Pydantic for everything static. The conventional wisdom is "Pydantic by default, dict when you have to".
Code Check
When you pass a JSON schema dict to with_structured_output, what type does invoke return?
Session 6 complete
You can now init, invoke, stream, batch, call tools in a loop, parallelise, and produce structured output with Pydantic or JSON schemas — across three providers with one interface. You are ready for the capstone projects.
Recap — what you just learned
- ✓with_structured_output accepts both Pydantic classes AND plain dict schemas
- ✓Dict schema → dict result, Pydantic class → typed instance
- ✓Use Pydantic by default, dicts when the schema is dynamic