Files
wehub-resource-sync 9201ef759e
CI / lint (push) Waiting to run
CI / mypy (push) Waiting to run
CI / docs (push) Waiting to run
CI / test on 3.10 (standard) (push) Waiting to run
CI / test on 3.11 (standard) (push) Waiting to run
CI / test on 3.12 (standard) (push) Waiting to run
CI / test on 3.10 (all-extras) (push) Waiting to run
CI / test on 3.11 (all-extras) (push) Waiting to run
CI / test on 3.12 (all-extras) (push) Waiting to run
CI / test on 3.13 (all-extras) (push) Waiting to run
CI / test on 3.14 (pydantic-evals) (push) Waiting to run
Harness Compat / harness compat (push) Waiting to run
CI / test on 3.13 (standard) (push) Waiting to run
CI / test on 3.14 (standard) (push) Waiting to run
CI / test on 3.14 (all-extras) (push) Waiting to run
CI / test on 3.10 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.11 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.12 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.13 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.14 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.10 (pydantic-evals) (push) Waiting to run
CI / test on 3.11 (pydantic-evals) (push) Waiting to run
CI / test on 3.12 (pydantic-evals) (push) Waiting to run
CI / test on 3.13 (pydantic-evals) (push) Waiting to run
CI / test on 3.10 (lowest-versions) (push) Waiting to run
CI / test on 3.11 (lowest-versions) (push) Waiting to run
CI / test on 3.12 (lowest-versions) (push) Waiting to run
CI / test on 3.13 (lowest-versions) (push) Waiting to run
CI / test on 3.14 (lowest-versions) (push) Waiting to run
CI / test examples on 3.11 (push) Waiting to run
CI / test examples on 3.12 (push) Waiting to run
CI / test examples on 3.13 (push) Waiting to run
CI / test examples on 3.14 (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / check (push) Blocked by required conditions
CI / deploy-docs (push) Blocked by required conditions
CI / deploy-docs-preview (push) Blocked by required conditions
CI / build release artifacts (push) Blocked by required conditions
CI / publish to PyPI (push) Blocked by required conditions
CI / Send tweet (push) Blocked by required conditions
chore: import upstream snapshot with attribution
2026-07-13 13:27:52 +08:00

4.4 KiB

pydantic_ai_slim/pydantic_ai/models/ Guidelines

API Design

  • Document unsupported model settings in docstrings and silently ignore at runtime — prevents breaking client code when models have different capabilities — Different model providers support different features; failing noisily when a setting is unsupported would break code portability across models, while silent degradation with clear documentation lets users make informed choices
  • Apply identical response processing to both request() and request_stream() — if request() calls _process_response(), request_stream() must apply it to each chunk — Ensures streaming and non-streaming code paths support the same message types (ToolCallPart, NativeToolCallPart, TextPart, etc.) with consistent behavior, preventing bugs where features work in one mode but fail in the other
  • Expose provider-specific data via ModelResponse.provider_details or TextPart.provider_details — prevents API bloat and maintains consistent provider integration patterns — Keeps the core response interface clean while allowing providers to expose logprobs, safety filters, content filtering, and usage metrics without breaking consistency across integrations
  • Verify provider limitations through testing before implementing workarounds in pydantic_ai/models/ — defer validation to runtime API responses rather than preemptive client-side checks — Prevents degrading functionality with unnecessary workarounds based on outdated assumptions, and lets the underlying API return clear error messages about actual incompatibilities
  • Token counting must mirror actual request parameters (tools, system_prompt, configs) and use identical message formatting — Ensures token count estimates match actual API usage, preventing billing surprises and quota errors
  • Per-request injections or mutations of request content (message blocks, tool defs, instructions, cache breakpoints) must anchor to a position that doesn't move with history length (e.g. the first user message or a fixed index), never the last message or a length-based index — anchoring to a moving position shifts the cacheable prefix every turn, so the provider silently re-processes the tail instead of reading from cache, a cost/latency regression that surfaces no error

Error Handling

  • Raise explicit errors for unsupported model features/content/parameters — never silently skip or degrade — Prevents silent failures and makes capability limits discoverable to users at runtime rather than producing unexpected behavior
  • Use exhaustive pattern matching for message part/content types in model adapters; raise explicit errors for unsupported types instead of filtering or assertions — Prevents silent data loss during message mapping and provides clear feedback when model APIs don't support certain content types (e.g., FileContent), making integration failures debuggable rather than mysterious
  • Return ModelResponse with empty parts=[] but populated metadata (finish_reason, timestamp, provider_response_id) for recoverable API failures (content filters, empty content) — enables graceful degradation instead of cascading errors — Allows the system to handle provider-level failures gracefully by preserving response metadata for observability while signaling no usable content, preventing unnecessary exception propagation in model adapters

Type System

  • Use typed settings classes (e.g., OpenAISettings, AnthropicSettings) with provider-prefixed fields instead of extra_body or dict literals — Enables type checking and autocomplete for provider-specific config, preventing runtime errors from typos or invalid values
  • Define Pydantic models to validate API responses — avoids .get() fragility and catches schema changes early — Prevents runtime errors from missing/malformed fields and provides type safety when parsing external API data

General

  • Place provider-specific code in models/{provider}.py, not shared modules — add functions consistently across all providers even if some are simple — Maintains clear architectural boundaries and prevents shared compatibility layers from accumulating provider-specific logic that becomes hard to maintain