Skip to main content

Minimal, reusable AI service handlers for Gemini and other LLMs

Project description

AI Proxy Core

A minimal Python package providing reusable AI service handlers for Gemini and other LLMs. No web framework dependencies - just the core logic.

Installation

Basic (Google Gemini only):

pip install ai-proxy-core

With specific providers:

pip install "ai-proxy-core[openai]"     # OpenAI support
pip install "ai-proxy-core[anthropic]"  # Anthropic support (coming soon)
pip install "ai-proxy-core[telemetry]"  # OpenTelemetry support
pip install "ai-proxy-core[all]"        # Everything

Or install from source:

git clone https://github.com/ebowwa/ai-proxy-core.git
cd ai-proxy-core
pip install -e .
# With all extras: pip install -e ".[all]"

Usage

Provider-Specific Completions

from ai_proxy_core import GoogleCompletions, OpenAICompletions, OllamaCompletions

# Google Gemini
google = GoogleCompletions(api_key="your-gemini-api-key")  # or uses GEMINI_API_KEY env
response = await google.create_completion(
    messages=[{"role": "user", "content": "Hello!"}],
    model="gemini-1.5-flash"
)

# OpenAI
openai = OpenAICompletions(api_key="your-openai-key")  # or uses OPENAI_API_KEY env
response = await openai.create_completion(
    messages=[{"role": "user", "content": "Hello!"}],
    model="gpt-4"
)

# Ollama (local)
ollama = OllamaCompletions(base_url="http://localhost:11434")  # or uses OLLAMA_HOST env
response = await ollama.create_completion(
    messages=[{"role": "user", "content": "Hello!"}],
    model="llama2"
)

# All return the same standardized format
print(response["choices"][0]["message"]["content"])

OpenAI-Compatible Endpoints

# Works with any OpenAI-compatible API (Groq, Anyscale, Together, etc.)
groq = OpenAICompletions(
    api_key="your-groq-key",
    base_url="https://api.groq.com/openai/v1"
)

response = await groq.create_completion(
    messages=[{"role": "user", "content": "Hello!"}],
    model="mixtral-8x7b-32768"
)

Gemini Live Session

from ai_proxy_core import GeminiLiveSession

# Example 1: Basic session (no system prompt)
session = GeminiLiveSession(api_key="your-gemini-api-key")

# Example 2: Session with system prompt (simple string format)
session = GeminiLiveSession(
    api_key="your-gemini-api-key",
    system_instruction="You are a helpful voice assistant. Be concise and friendly."
)

# Example 3: Session with built-in tools enabled
session = GeminiLiveSession(
    api_key="your-gemini-api-key",
    enable_code_execution=True,      # Enable Python code execution
    enable_google_search=True,       # Enable web search
    system_instruction="You are a helpful assistant with access to code execution and web search."
)

# Example 4: Session with custom function declarations
from google.genai import types

def get_weather(location: str) -> dict:
    # Your custom function implementation
    return {"location": location, "temp": 72, "condition": "sunny"}

weather_function = types.FunctionDeclaration(
    name="get_weather",
    description="Get current weather for a location",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "location": types.Schema(type="STRING", description="City name")
        },
        required=["location"]
    )
)

session = GeminiLiveSession(
    api_key="your-gemini-api-key",
    custom_tools=[types.Tool(function_declarations=[weather_function])],
    system_instruction="You can help with weather information."
)

# Set up callbacks
session.on_audio = lambda data: print(f"Received audio: {len(data)} bytes")
session.on_text = lambda text: print(f"Received text: {text}")
session.on_function_call = lambda call: handle_function_call(call)

async def handle_function_call(call):
    if call["name"] == "get_weather":
        result = get_weather(**call["args"])
        await session.send_function_result(result)

# Start session
await session.start()

# Send audio/text
await session.send_audio(audio_data)
await session.send_text("What's the weather in Boston?")

# Stop when done
await session.stop()

Integration with FastAPI

Chat Completions API

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from ai_proxy_core import CompletionsHandler

app = FastAPI()
handler = CompletionsHandler()

class CompletionRequest(BaseModel):
    messages: list
    model: str = "gemini-1.5-flash"
    temperature: float = 0.7

@app.post("/api/chat/completions")
async def create_completion(request: CompletionRequest):
    try:
        response = await handler.create_completion(
            messages=request.messages,
            model=request.model,
            temperature=request.temperature
        )
        return response
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

WebSocket for Gemini Live

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from ai_proxy_core import GeminiLiveSession

app = FastAPI()

@app.websocket("/ws/gemini")
async def gemini_websocket(
    websocket: WebSocket,
    enable_code_execution: bool = False,
    enable_google_search: bool = False
):
    await websocket.accept()
    
    # Create session with tools if requested
    session = GeminiLiveSession(
        enable_code_execution=enable_code_execution,
        enable_google_search=enable_google_search
    )
    
    # Set up callbacks to forward to WebSocket
    session.on_audio = lambda data: websocket.send_json({
        "type": "audio", "data": data
    })
    session.on_text = lambda text: websocket.send_json({
        "type": "text", "data": text
    })
    
    await session.start()
    
    try:
        async for message in websocket.iter_json():
            if message["type"] == "audio":
                await session.send_audio(message["data"])
            elif message["type"] == "text":
                await session.send_text(message["data"])
    except WebSocketDisconnect:
        await session.stop()

Features

  • No framework dependencies - Use with FastAPI, Flask, or any Python app
  • Async/await support - Modern async Python
  • Type hints - Full type annotations
  • Minimal surface area - Just the core logic you need
  • Easy testing - Mock the handlers in your tests
  • Built-in tools - Code execution and Google Search with simple flags
  • Custom functions - Add your own function declarations
  • Reusable design - Tools configured by consumers, not hardcoded
  • WebSocket support - Real-time audio/text streaming with Gemini Live
  • Callback system - Handle responses with custom callbacks
  • Optional telemetry - OpenTelemetry integration for production monitoring

Telemetry

Basic observability with OpenTelemetry (optional):

# Install with: pip install "ai-proxy-core[telemetry]"

# Enable telemetry via environment variables
export OTEL_ENABLED=true
export OTEL_EXPORTER_TYPE=console  # or "otlp" for production
export OTEL_ENDPOINT=localhost:4317  # for OTLP exporter

# Automatic telemetry for:
# - Request counts by model/status
# - Request latency tracking
# - Session duration for WebSockets
# - Error tracking with types

The telemetry is completely optional and has zero overhead when disabled.

Development

Releasing New Versions

We provide an automated release script that handles version bumping, building, and publishing:

# Make the script executable (first time only)
chmod +x release.sh

# Release a new version
./release.sh 0.1.9

The script will:

  1. Show current version and validate the new version format
  2. Prompt for a release description (for CHANGELOG)
  3. Update version in all necessary files (pyproject.toml, setup.py, init.py)
  4. Update CHANGELOG.md with your description
  5. Build the package
  6. Upload to PyPI
  7. Commit changes and create a git tag
  8. Push to GitHub with the new tag

Manual Build Process

If you prefer to build manually:

python setup.py sdist bdist_wheel
twine upload dist/*

License

MIT

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

ai_proxy_core-0.1.9.tar.gz (16.9 kB view details)

Uploaded Source

Built Distributions

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

ai_proxy_core-0.1.9.0-py3-none-any.whl (19.0 kB view details)

Uploaded Python 3

ai_proxy_core-0.1.9-py3-none-any.whl (19.0 kB view details)

Uploaded Python 3

File details

Details for the file ai_proxy_core-0.1.9.tar.gz.

File metadata

  • Download URL: ai_proxy_core-0.1.9.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.0

File hashes

Hashes for ai_proxy_core-0.1.9.tar.gz
Algorithm Hash digest
SHA256 0b337f6c3658bc3f7bc9b16aa36aa763e06bcbc9528cd026c6e3ef263bb6832d
MD5 563bcb541918cf9874610b99023c450d
BLAKE2b-256 33340315e0464fbd6c3e67a3e54e5fa6a531020017c174a77852219a7882d131

See more details on using hashes here.

File details

Details for the file ai_proxy_core-0.1.9.0-py3-none-any.whl.

File metadata

File hashes

Hashes for ai_proxy_core-0.1.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ac37e678b9eca6fdc3bbd19a00ac741ec606a2fbe9cf9ffb1e612e5e395eba7e
MD5 324b1c0e2f8c5fb18143f645e7bf1f31
BLAKE2b-256 984baf43e90183cae2b1113addbdfa36000ba6c96966fe312cf8a296e497257d

See more details on using hashes here.

File details

Details for the file ai_proxy_core-0.1.9-py3-none-any.whl.

File metadata

  • Download URL: ai_proxy_core-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 19.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.0

File hashes

Hashes for ai_proxy_core-0.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 ecbfca4ce00465de65044149c909c329b99d9dde7ede713980d1043b87cdd026
MD5 772134f679142b778780b5fca1802fbe
BLAKE2b-256 17725217b72348ec0ed4ee79ae0139e7a92adb405232613520df158cbcaba9df

See more details on using hashes here.

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