Repository navigation
Description
Thanks for the recent import-cost work (lazy interactions, _gaos behind TYPE_CHECKING, defer_build=True in 2.18.0). It cut RSS roughly in half for us. Home Assistant's Gemini integration often runs on small devices, such as a Raspberry Pi with 1–2 GB of RAM, where every megabyte counts.
After 2.18, most of what's left of the SDK's own import cost is types.py (863 KB of source). About a third of that file is 457 TypedDict classes (*Dict) plus ~470 *OrDict / *UnionDict aliases built from them. They exist for type hints only: no pydantic field uses them, and the SDK only reads them in annotations, in error messages, and in the Live API.
Measurement (2.25.0, CPython 3.14, RSS of a fresh process, shared deps preloaded):
| stock | TypedDicts lazy | |
|---|---|---|
import google.genai |
18.2 MiB | 15.7 MiB |
| import + Client + chats.create with a typical GenerateContentConfig | 25.2 MiB | 22.5 MiB |
That's about 2.7 MiB, or ~15% of the SDK's own import cost.
What we tried (as a build-time patch on our side): move the *Dict classes and the aliases that depend on them into a private module (_types_dicts.py, same source text), and load it from the existing module-level __getattr__ in types.py on first access. types.ContentDict and from google.genai.types import ContentDict keep working. A small set stays eager: the names other SDK modules import at load time (HttpOptionsDict, HttpOptionsOrDict, ContentDict, ContentOrDict, GenerateContentConfigOrDict, PartUnionDict) and everything their definitions and annotations reference, about 100 names.
Risks and mitigations:
-
Behavioral equivalence: All 1381 public names in
google.genai.typesare verified identical to stock: same kind, fields, docstrings,__module__,get_type_hints()outcome, anddir(). The bundled test suite gives identical per-test outcomes with the patch applied. -
__module__attribute: Each moved TypedDict has its__module__set back togoogle.genai.typesafter loading, sopickle,inspect, and tooling see the same origin as before. Code doingfrom google.genai.types import SomeDictcontinues to work. -
First-access latency: The lazy module loads on first use of any deferred name. This is a one-time cost (~5 ms measured) that moves from import time to first use. After that, all names are cached in the module globals, and access is a normal attribute lookup.
-
Python < 3.14: The savings rely on PEP 649 (3.14+): function annotations such as
config: Optional[types.GenerateContentConfigOrDict]inmodels.pyare no longer evaluated at definition time. On 3.10–3.13 those annotations would trigger the load at import. That is still correct but saves nothing, unless the SDK's modules adoptfrom __future__ import annotations. -
Generated code: Since
types.pyis generated, the natural place for this is the generator. The patch is a build-time transform that could be folded into the code generation pipeline.
Proof of concept: rafaelborja/python-genai@main...lazy-load-typedicts. Happy to open a pull request if that helps, or it can serve as a reference for a generator change on your side.
A further step would be splitting the pydantic models themselves. A typical text + tools + thinking caller reaches only 137 of the 465 models, so that could save roughly another 5 MiB (estimated, not yet measured).
Happy to share the measurement scripts and help with testing.
Activity
Venkaiahbabuneelam commentedon Sep 28, 2026
Hi @rafaelborja, Thank you for your feedback. We appreciate you taking the time to share your thoughts with us, and we'll be filing a feature request.
Thanks
rafaelborja commentedon Sep 30, 2026
Thanks! Could you keep this issue open and link it to the internal request, so we can follow its status? The proof of concept branch (rafaelborja/python-genai@main...lazy-load-typedicts) stays available if it's useful to the team working on the generator.