Skip to content

Feature: Use TypedDict for Python SDK Model Configuration Options #5553

@huangjeff5

Description

@huangjeff5

[Feature Request/Design Proposal]: Use TypedDict for Model Configuration Options in Python SDK

Background

Currently, in the Genkit Python SDK, model configuration options (such as those for the Gemini plugin) can be specified using either plain dictionaries or typed config objects (e.g., GeminiConfigSchema which is typically a Pydantic model).

As noted in recent discussions, our current documentation frequently shows configuration options being passed as plain dictionaries:

# Current docs often show:
response = await ai.generate(
    model='googleai/gemini-2.0-flash',
    prompt='Write a python script to reverse a list.',
    config={"temperature": 0.7, "maxOutputTokens": 100} # Untyped
)

While users can use the typed GeminiConfigSchema:

from genkit.plugins.google_genai import GeminiConfigSchema

gemini_config = GeminiConfigSchema(
    temperature=0.7,
    max_output_tokens=100,
    code_execution=True
)

The Problem:

  1. Developer Experience: Plain dictionaries provide no IDE autocompletion, static type checking, or documentation hints. While Pydantic schema objects solve this, requiring users to import and instantiate specific Pydantic models can feel heavy for simple configuration tasks.
  2. AI Generation: LLMs and AI agents tend to generate plain dictionary configurations naturally.
  3. Documentation: Our docs heavily feature dicts, leading users away from the typed objects.

Proposed Solution

Introduce typing.TypedDict for model configuration options across the Python SDK.

Using TypedDict allows users to construct simple dictionaries while still benefiting from static type checking and IDE autocompletion.

from typing import TypedDict, NotRequired

class GeminiConfigDict(TypedDict):
    temperature: NotRequired[float]
    max_output_tokens: NotRequired[int]
    code_execution: NotRequired[bool]

# Users can just pass a dict, and static analyzers/IDEs will validate keys and types!
response = await ai.generate(
    model='googleai/gemini-2.0-flash',
    prompt='...',
    config={"temperature": 0.7, "max_output_tokens": 100} 
)

Pros and Cons

Pros

  • Frictionless DX: Users get the simplicity of dictionaries (no need to instantiate class objects) combined with the benefits of type hints (autocompletion, error checking in IDEs).
  • AI-Friendly: Aligns with the tendency of AI agents to generate standard Python dictionaries.
  • Documentation Alignment: If we type config as Union[GeminiConfigDict, GeminiConfigSchema], the docs showing dict usage remain valid but are now implicitly typed.

Cons

  • No Runtime Validation: TypedDict only provides static type checking. Unlike Pydantic models, it does not validate data types at runtime.
  • Case Conversion Complexity: (See below)

Key Considerations & Open Questions

1. Snake Case vs. Camel Case

The most significant hurdle is handling naming conventions. Python developers expect snake_case (e.g., max_output_tokens), while the underlying Genkit core or specific model SDKs (like Gemini) often expect camelCase (e.g., maxOutputTokens).

With Pydantic, we easily map snake_case to camelCase using aliases (alias_generator=to_camel). TypedDict does not have built-in runtime aliasing.

Potential Mitigations:

  • Standardize on snake_case for the TypedDict: We would need a generic utility function in the SDK that recursively converts snake_case keys to camelCase before passing the config payload to the core/underlying SDK.
  • Require camelCase in TypedDict: This goes against Pythonic conventions and would lead to an awkward DX ({"maxOutputTokens": 100}).

2. Static Typing vs. Runtime Validation

If a user bypasses static type checkers and passes an invalid type in a TypedDict at runtime (e.g., {"temperature": "hot"}), it will pass through.
Question: Is runtime validation of the config object strictly necessary at the SDK boundary, or is it acceptable to let the underlying Model Provider SDK throw the validation error?

3. Implementation Strategy

Do we replace GeminiConfigSchema (and other plugin schemas) entirely with TypedDict, or do we support both via Union[GeminiConfigDict, GeminiConfigSchema]?
Supporting both gives users a choice (Pydantic for runtime safety, TypedDict for convenience), but increases API surface area and maintenance.

Action Items

  1. Spike/Exploration: Create a proof-of-concept for replacing or augmenting a model plugin's config with a TypedDict.
  2. Case Conversion Strategy: Design a clean mechanism for automatically mapping the snake_case keys of the TypedDict to the camelCase expected by the internal Genkit engine/providers.
  3. Docstring Updates: Update the Python SDK docstrings and test cases to actively push towards the newly adopted typed config behavior, ensuring auto-generated documentation reflects best practices.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions