Skip to main content

A lightweight Python library for Google Gemini API key rotation and model fallback.

Project description

Gemini Rotate

Async Python

A lightweight Async Python library for Google Gemini API key rotation, valid model selection, and automatic fallback to "Lite" models on server errors.

🚀 Features

  • ✅ Automatic Key Rotation: Seamlessly rotates through a list of API keys when quota is exhausted (429), permission denied (403), or any other API error occurs.
  • 🔄 Smart Model Fallback: Automatically downgrades specific models (e.g., gemini-2.0-flash -> gemini-2.0-flash-lite) if server errors (5xx) persist.
  • ⚡ Async First: Built on top of the google-genai async client for high-performance non-blocking applications.
  • 🛡️ Robust Error Handling: Implements exponential backoff before rotating keys or switching models.
  • 📝 Concise Logging: Logs only essential success/failure information (e.g., 400 INVALID_ARGUMENT) to keep your console clean.

📦 Installation

pip install gemini-rotate

⚡ Quick Start

  1. Configure Environment: Create a .env file.

    GEMINI_API_KEY_1="AIzaSy..."
    GEMINI_API_KEY_2="AI3yhj..."
    GEMINI_API_KEY_3="AIdf56..."
    
  2. Run Code:

    import asyncio
    from gemini_rotate import GeminiRotationClient
    
    async def main():
        client = GeminiRotationClient()
        response = await client.generate_content("Hello, Gemini!")
        print(response.text)
    
    asyncio.run(main())
    

📖 Usage Guide

Initialization

The client automatically loads API keys from your environment variables (GEMINI_API_KEY_1, GEMINI_API_KEY_2, etc.).

client = GeminiRotationClient()

Generating Content

The generate_content method wraps the standard google-genai call but adds rotation and fallback logic.

1. Basic Text Generation

import asyncio
from gemini_rotate import GeminiRotationClient
from dotenv import load_dotenv

load_dotenv()

async def generate_text():
    client = GeminiRotationClient()
    try:
        response = await client.generate_content(
            contents="Explain quantum computing in 50 words."
        )
        print(f"Generated text: {response.text}")
    except Exception as e:
        print(f"Error: {e}")

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

2. Advanced: Tool Calling & Structured Output

You can pass tools and response_schema (or response_mime_type) via the config parameter.

import asyncio
from google import genai
from gemini_rotate import GeminiRotationClient
from pydantic import BaseModel
from dotenv import load_dotenv

load_dotenv()

# Define a schema for structured output
class Recipe(BaseModel):
    title: str
    ingredients: list[str]
    instructions: list[str]

async def generate_recipe():
    client = GeminiRotationClient()

    try:
        response = await client.generate_content(
            contents="Give me a recipe for chocolate cake.",
            config={
                "response_mime_type": "application/json",
                "response_schema": Recipe,
            }
        )
        
        # Parse result directly into Pydantic model
        recipe = response.parsed
        print(f"Title: {recipe.title}")
        print(f"Ingredients: {recipe.ingredients}")
        
    except Exception as e:
        print(f"Error: {e}")

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

Parameters

Parameter Type Description
contents str | list The prompt or content to send.
model str (Optional) The specific model to use. Defaults to first in priority list.
config dict (Optional) Generation config (temperature, tools, schema) passed to google.genai.

⚙️ Configuration

1. API Keys (Required)

Define your keys in .env or environment variables using the pattern GEMINI_API_KEY_n.

GEMINI_API_KEY_1="key_one..."
GEMINI_API_KEY_2="key_two..."
GEMINI_API_KEY_3="key_three..."

(Note: A single GEMINI_API_KEY is also supported, but using the numbered pattern allows for rotation.)

2. Model Priority (Optional)

You can customize the order in which models are attempted by setting GEMINI_MODELS in .env. The library processes models in Primary -> Secondary pairs.

Default Behavior (if not set):

  1. gemini-flash-latest -> gemini-flash-lite-latest
  2. gemini-3-flash-preview -> gemini-2.5-flash
  3. gemini-2.5-flash-lite -> gemini-2.0-flash
  4. gemini-2.0-flash-lite -> (None)

Custom Configuration:

GEMINI_MODELS='["gemini-2.5-flash", "gemini-2.5-flash-lite", "gemini-2.0-flash"]'

🔍 How it Works

graph TD
    Start[Start Request] --> LoopPairs{Loop Model Pairs}
    LoopPairs -->|Primary, Secondary| LoopClients{Loop API Clients}
    
    LoopClients -->|Next Client| AttemptPrimary[Attempt Primary Model]
    
    AttemptPrimary -->|Success| ReturnResponse[Return Response]
    AttemptPrimary -->|Failure| CheckSecondary{Has Secondary Model?}
    
    CheckSecondary -->|Yes| AttemptSecondary[Attempt Secondary Model]
    CheckSecondary -->|No| NextClient[Next Client]
    
    AttemptSecondary -->|Success| ReturnResponse
    AttemptSecondary -->|Failure| NextClient
    
    NextClient -->|Clients Exhausted| NextPair[Next Pair]
    NextPair -->|Pairs Exhausted| RaiseError[Raise AllClientsFailed]
    
    style Start fill:#f9f,stroke:#333,stroke-width:2px
    style ReturnResponse fill:#9f9,stroke:#333,stroke-width:2px
    style RaiseError fill:#f99,stroke:#333,stroke-width:2px

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gemini_rotate-0.1.1.tar.gz (5.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gemini_rotate-0.1.1-py3-none-any.whl (6.3 kB view details)

Uploaded Python 3

File details

Details for the file gemini_rotate-0.1.1.tar.gz.

File metadata

  • Download URL: gemini_rotate-0.1.1.tar.gz
  • Upload date:
  • Size: 5.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for gemini_rotate-0.1.1.tar.gz
Algorithm Hash digest
SHA256 610e0b1cc83940f388f2cef9940bc3014cf6ff65dad5c34c1b66d118b745663a
MD5 75d526d652810a5ba7864737680d6ea8
BLAKE2b-256 e562c87d20de01b5d0a15af9f629ebe72d72b28bc892d29061ce375d6593b023

See more details on using hashes here.

Provenance

The following attestation bundles were made for gemini_rotate-0.1.1.tar.gz:

Publisher: pypi-publish.yml on jayeeed/gemini-rotate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gemini_rotate-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: gemini_rotate-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 6.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for gemini_rotate-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9e4d8b94eec33a4e16f525bbe3e505bf5d48145807cb959a88d8914d425f6317
MD5 537e54d6d7e9f35c99724fa5822cd4ff
BLAKE2b-256 8a8f0487f3bc477874ddea5cbb4b16d2df586d55c40f4b7a234c3c58823785dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for gemini_rotate-0.1.1-py3-none-any.whl:

Publisher: pypi-publish.yml on jayeeed/gemini-rotate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page