Skip to main content

llm-sdk-provider-gemini

Gemini provider plugin for llm-sdk, implemented using google-genai (Vertex AI). This package installs a provider plugin via Python entry points, enabling Gemini support without modifying the core SDK.


Table of Contents


Overview

llm-sdk-provider-gemini is a plugin package that adds support for:

  • Gemini chat completions
  • Gemini embeddings
  • Gemini streaming chat

It integrates with the llm-sdk core using Python entry points, so the provider is automatically discoverable via:

sdk.registry.load_plugins()

Architecture

Plugin mechanism

This package declares an entry point:

[project.entry-points."llm_sdk.providers"]
gemini = "llm_sdk_provider_gemini.plugin:GeminiProviderFactory"

At runtime:

  1. llm-sdk scans installed packages for llm_sdk.providers
  2. Loads the GeminiProviderFactory
  3. Calls:
    • spec() for metadata
    • create(settings) to build a provider client

Features

  • Async Gemini client
  • Supports:
    • chat completions
    • embeddings
    • streaming chat
  • Uses google-genai (Vertex AI mode)
  • Unified SDK error mapping (ProviderError)
  • Strong typing
  • Clean separation from SDK core

Installation

Install core SDK

pip install llm-sdk

Install Gemini provider

pip install llm-sdk-provider-gemini

Usage

Sync quickstart

from llm_sdk.sync_sdk import SyncSDK
from llm_sdk.retries import RetryPolicy
from llm_sdk.providers.sync_registry import ProviderSpec
from llm_sdk_provider_gemini import SyncGeminiClient
from llm_sdk.domain.chat import ChatMessage, ChatPart

sdk = SyncSDK.default()
sdk.registry.register(ProviderSpec(
    name="gemini",
    factory=lambda: SyncGeminiClient(
        location=sdk.settings.gemini.location,
    ),
    models={
        "gemini-2.5-flash",
        "text-multilingual-embedding-002"
    },
))

Normal chat example

from llm_sdk.sync_sdk import SyncSDK
from llm_sdk.retries import RetryPolicy
from llm_sdk.providers.sync_registry import ProviderSpec
from llm_sdk_provider_gemini import SyncGeminiClient
from llm_sdk.domain.chat import ChatMessage, ChatPart

sdk = SyncSDK.default()
sdk.registry.register(ProviderSpec(
    name="gemini",
    factory=lambda: SyncGeminiClient(
        location=sdk.settings.gemini.location,
    ),
    models={
        "gemini-2.5-flash",
    },
))

resp = sdk.chat(
    messages=[
        ChatMessage(
            role="user",
            parts=[
                ChatPart(
                    type="text",
                    text="¿Qué ves en la imágen?"
                ),
                ChatPart(
                    type="image_url",
                    uri="https://verdecora.es/blog/wp-content/uploads/2025/06/cuidados-pato-casa.jpg"
                )
            ]
        )
    ],
    provider="gemini",
    model="gemini-2.5-flash",
)

print(resp.content)

Streaming example

from llm_sdk.sync_sdk import SyncSDK
from llm_sdk.retries import RetryPolicy
from llm_sdk.providers.sync_registry import ProviderSpec
from llm_sdk_provider_gemini import SyncGeminiClient
from llm_sdk.domain.chat import ChatMessage, ChatPart

sdk = SyncSDK.default()
sdk.registry.register(ProviderSpec(
    name="gemini",
    factory=lambda: SyncGeminiClient(
        location=sdk.settings.gemini.location,
    ),
    models={
        "gemini-2.5-flash",
        "text-multilingual-embedding-002"
    },
))

text_out: list[str] = []
last_usage = None
for ev in sdk.stream_chat(
    messages=[
        ChatMessage(
            role="user",
            parts=[
                ChatPart(type="text", text="¿Qué ves en la imágen?"),
                ChatPart(
                    type="image_url",
                    uri="https://verdecora.es/blog/wp-content/uploads/2025/06/cuidados-pato-casa.jpg",
                ),
            ],
        )
    ],
    provider="gemini",
    model="gemini-2.5-flash",
):
    if ev.delta:
        text_out.append(ev.delta)
    if ev.usage:
        last_usage = ev.usage
    if ev.done:
        break

print("\n\n[done]")
print("usage:", last_usage)
full_text = "".join(text_out)
print("full text:", full_text)

Embedding example

from llm_sdk.sync_sdk import SyncSDK
from llm_sdk.retries import RetryPolicy
from llm_sdk.providers.sync_registry import ProviderSpec
from llm_sdk_provider_gemini import SyncGeminiClient
from llm_sdk.domain.chat import ChatMessage, ChatPart

sdk = SyncSDK.default()
sdk.registry.register(ProviderSpec(
    name="gemini",
    factory=lambda: SyncGeminiClient(
        location=sdk.settings.gemini.location,
    ),
    models={
        "gemini-2.5-flash",
        "text-multilingual-embedding-002"
    },
))

result = sdk.embed(
    provider="gemini",
    model="text-multilingual-embedding-002",
    input=["Hola mundo", "Hello world"],
)

Async quickstart

import asyncio
from llm_sdk.async_sdk import AsyncSDK
from llm_sdk.domain.chat import ChatMessage, ChatPart

async def main() -> None:
    sdk = AsyncSDK.default()

    # Load installed plugins (entry points)
    sdk.registry.load_plugins()

    resp = await sdk.chat(
        messages=[
            ChatMessage(
                role="user",
                parts=[
                    ChatPart(
                        type="text",
                        text="¿Qué ves en la imágen?"
                    ),
                    ChatPart(
                        type="image_url",
                        uri="https://verdecora.es/blog/wp-content/uploads/2025/06/cuidados-pato-casa.jpg"
                    )
                ]
            )
        ],
        provider="gemini",
        model="gemini-2.5-flash",
    )

    print(resp.content)


if __name__ == "__main__":
    asyncio.run(main())

Streaming example

import asyncio
from llm_sdk.async_sdk import AsyncSDK
from llm_sdk.domain.chat import ChatMessage, ChatPart


async def main() -> None:
    sdk = AsyncSDK.default()
    sdk.registry.load_plugins()

    async for ev in sdk.stream_chat(
        messages=[
            ChatMessage(
                role="user",
                parts=[
                    ChatPart(type="text", text="¿Qué ves en la imágen?"),
                    ChatPart(
                        type="image_url",
                        uri="https://verdecora.es/blog/wp-content/uploads/2025/06/cuidados-pato-casa.jpg",
                    ),
                ],
            )
        ],
        provider="gemini",
        model="gemini-2.5-flash",
    ):
        if ev.delta:
            print(ev.delta, end="", flush=True)
            text_out.append(ev.delta)
        if ev.usage:
            last_usage = ev.usage
        if ev.done:
            break

    print("\n\n[done]")
    print("usage:", last_usage)
    full_text = "".join(text_out)
    print("full text:", full_text)


if __name__ == "__main__":
    asyncio.run(main())

Embeddings example

import asyncio
from llm_sdk.async_sdk import AsyncSDK


async def main() -> None:
    sdk = AsyncSDK.default()
    sdk.registry.load_plugins()

    resp = await sdk.embed(
        provider="gemini",
        model="text-multilingual-embedding-002",
        input=["Hola mundo", "Hello world"],
    )

    print(resp.vectors[0][:10])


if __name__ == "__main__":
    asyncio.run(main())

Configuration

This provider uses Google credentials from the environment.

Authentication (Vertex AI)

You must have:

  • Google Cloud project enabled for Vertex AI
  • Proper credentials available through ADC (Application Default Credentials)

Typical local setup:

gcloud auth application-default login

Provider-specific settings

This package typically reads:

  • Gemini location (example: us-central1)

Depending on your llm-sdk settings design, you may configure:

export LLM_SDK_LOCATION="us-central1"

Or if you implement namespaced settings:

export LLM_SDK_GEMINI_LOCATION="us-central1"

Project Structure

llm-sdk-provider-gemini/
├─ src/
│  └─ llm_sdk_provider_gemini/
│     ├─ plugin.py
│     ├─ settings.py
│     ├─ async_client.py
│     ├─ sync_client.py
│     └─ __init__.py
├─ tests/
│  ├─ test_factory.py
│  └─ test_contracts.py
├─ pyproject.toml
└─ README.md

Setup

Development

python -m venv venv
source venv/bin/activate
pip install -U pip
pip install -e .

Install core SDK in editable mode (local dev)

pip install -e ../llm-sdk

Testing

pytest -q

Notes

Provider tests should include:

  • Factory loads correctly
  • Spec metadata is correct
  • Client implements required methods
  • Error mapping works as expected

Avoid real network tests in unit tests. If you want integration tests, put them behind an env flag.


Deployment

Build package

python -m build

Upload to TestPyPI

python -m twine upload --repository testpypi dist/*

Upload to PyPI

python -m twine upload dist/*

Roadmap

  • Better usage extraction for Gemini responses
  • Support for Gemini tool calling (if SDK adds tool abstractions)
  • Optional support for non-Vertex Gemini API mode
  • Optional response caching hooks

Contributing

PRs welcome.

Recommended workflow:

  1. Fork repo
  2. Create a feature branch
  3. Add tests
  4. Run pytest
  5. Submit PR

License

MIT License


Contact

Author: Esteban Flores

Metadata

Release files for llm-sdk-provider-gemini 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llm-sdk-provider-gemini 0.2.1
File Size Uploaded Provenance
llm_sdk_provider_gemini-0.2.1.tar.gz 7.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for llm-sdk-provider-gemini 0.2.1
File Interpreter ABI Platform
llm_sdk_provider_gemini-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 18.5 kB

Release files / llm_sdk_provider_gemini-0.2.1.tar.gz

Download URL llm_sdk_provider_gemini-0.2.1.tar.gz
Size 7.9 kB
Tags Source
SHA-256 checksum
How to use checksums
cc003ca32201c16a06cb4b3d50dca8efdee9ed6efed1240acc94b54fde933057
BLAKE2b-256 checksum
How to use checksums
591b9875157dbbe825d87c48ab4f0a1ebc285d79fb37c2559f222a11ceeaa55d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Release files / llm_sdk_provider_gemini-0.2.1-py3-none-any.whl

Download URL llm_sdk_provider_gemini-0.2.1-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c44e679c04b0ff686a806040e29a36e6ccf89bd69e5a397f29d4f755d56ee34
BLAKE2b-256 checksum
How to use checksums
43da2ff808c19853692f5fa8402eb6b0c04781df8db242548ef3ff8930de8624
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Security for llm-sdk-provider-gemini 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page