AI Engineer Portal
Your personal operating system for career transition.
Exercise
Build a Pydantic model hierarchy for multi-provider LLM responses
Build a Pydantic Model Hierarchy for Multi-Provider LLM Responses
Different LLM providers return fundamentally different response shapes. OpenAI wraps content in choices[0].message.content, Anthropic wraps it in content[0].text, and a local Ollama server returns {"response": "..."}. Without a shared internal type, your application code ends up scattered with if provider == "openai" conditionals.
What to build
Design a Pydantic model hierarchy that:
- Defines provider-specific models —
OpenAIResponse,AnthropicResponse, andLocalResponse, each with the fields that match that provider's real API shape. - Uses discriminated unions — add a
provider: Literal[...]field to each model so Pydantic can route validation automatically. - Exposes a shared interface — each model must implement a
.normalized()method that returns aNormalizedLLMResponsewith fields:request_id,text,model,input_tokens,output_tokens. - Validates via a factory function —
parse_provider_response(raw: dict, provider: str) -> NormalizedLLMResponsethat accepts raw JSON and the provider name, validates the correct model, and returns the normalized form. - Handles validation failures gracefully — if the raw dict does not match the expected shape, raise a descriptive
ValueError.
Why this matters
Every AI backend that touches more than one provider needs this pattern. Without it, normalization logic leaks into application code, provider changes break multiple callsites, and testing requires mocking raw provider SDKs. A clean model hierarchy confines the mess to one place.
Constraints
- Use Pydantic v2 (
from pydantic import BaseModel). - Do not use
Anyin model fields — be explicit about types. - The
parse_provider_responsefunction should work for all three providers from a single entry point.
Python Ai / medium / Step 1 of 6
General drill
Keep the solution explicit and reviewable.
Make the solution explicit, debuggable, and easy to explain.
Review where the boundary is, what gets validated, and what would be hard to debug later.
Practice
Generate a variation
Generate a new exercise variation to deepen understanding or practice a related concept.
Attempt history
Recent submissions
Before you submit, decide what a strong answer should make obvious to the reviewer.
No attempts yet.