Skip to main content

Installation and Setup

The ABV client library installs via pip and works with Python 3.8 or later. Install it in your project or virtual environment:
The package includes both synchronous and asynchronous clients, so you don’t need separate packages for async support. Type stubs are included for better IDE support if you’re using type checkers like mypy or Pylance.

Client Initialization Patterns

How you initialize the ABV client affects your application’s structure. Let’s explore different patterns and their use cases. The simplest initialization provides your API key directly:
This works for quick prototypes or scripts, but storing credentials in code isn’t recommended for production. Instead, use environment variables:
The client checks for the ABV_API_KEY environment variable automatically, so you can simplify further:
This pattern keeps credentials out of your codebase and makes it easy to use different keys in different environments. For applications that need to support multiple regions, specify the region during initialization:
Region selection determines which ABV infrastructure handles your requests. Choose the region closest to your users or matching your data residency requirements.

Client Lifecycle and Module Organization

Creating an ABV client is lightweight, but you should generally create one client instance and reuse it throughout your application. Python’s module system makes this pattern natural. Create a module that initializes and exports the client:
Then import this client wherever you need it:
This pattern ensures you’re reusing the same client instance across your application, which is more efficient and simplifies testing since you can mock the imported client in test files.

Working with Type Hints

Python’s type hints help catch errors during development and improve code readability. While the ABV client library works fine without type hints, adding them makes your code more maintainable. Use type hints to document function signatures that work with gateway responses:
Type hints help your IDE provide better autocomplete and catch type errors before runtime. They also serve as documentation for other developers reading your code. For more sophisticated type checking, you can define TypedDict classes that represent the structure of gateway requests and responses:
This level of type safety catches more errors during development, though it requires more upfront definition effort.

Handling Streaming Responses

Streaming responses arrive as an iterator that yields chunks as the model generates tokens. Python’s iteration protocol makes working with streams natural. The basic streaming pattern uses a for loop to process chunks:
The nested .get() calls with default values handle the varying structure of chunks safely. Early chunks might not have content, and this pattern avoids KeyError exceptions. For applications that need both real-time display and the complete response, accumulate chunks while iterating:
This pattern works well for chatbots that display streaming text while also saving the complete conversation history.

Async/Await for Concurrent Requests

Python’s asyncio support enables efficient concurrent processing of multiple AI requests. The ABV client provides async methods for applications built with asyncio. For async streaming, use the create_async method and async for to iterate:
The real power of async comes when processing multiple requests concurrently. This is much faster than processing them sequentially:
Using asyncio.gather processes all requests concurrently, which is much faster than processing them one by one. This pattern is particularly valuable for batch processing or applications that need to make multiple AI requests in response to a single user action.

Error Handling Strategies

Gateway requests can fail for various reasons, and handling these failures appropriately improves application reliability. Python’s exception system gives you several approaches to error handling. The basic pattern uses try-except to catch failures:
For production applications, distinguish between different error types to handle them appropriately. Rate limit errors need different handling than authentication errors:
This pattern examines the error message to determine the failure type and responds appropriately. Different error types map to different user-facing messages or retry strategies. For applications requiring retry logic, implement exponential backoff to handle transient failures:
This retry logic handles temporary failures like network issues while avoiding endless loops on permanent failures. The exponential backoff prevents overwhelming the service with rapid retries.

Building Conversation Context

Most AI applications involve multi-turn conversations where the model needs context from previous messages. Managing this context is essential for building chat applications. The straightforward approach maintains a list of messages that grows with the conversation:
This class encapsulates conversation state and ensures history stays synchronized. Using it looks like this:
Each message includes the full conversation history, enabling the model to reference earlier exchanges and maintain context. For long-running conversations, manage the context window size to avoid token limits:
This approach prevents conversations from exceeding token limits by keeping only recent messages. The tradeoff is losing access to earlier context.

Working with Dataclasses

Python’s dataclasses provide a clean way to structure data for AI applications. They’re particularly useful for managing conversation state and request parameters:
Dataclasses make the structure explicit and provide useful methods like repr automatically, which helps with debugging.

Framework Integration

The gateway integrates naturally with popular Python web frameworks. Here are patterns for common frameworks. For Flask applications, create an endpoint that handles AI requests:
For FastAPI applications, the pattern is similar but uses FastAPI’s async support:
FastAPI’s async support and Pydantic models provide type safety and automatic validation, making it an excellent choice for AI-powered APIs. For Django applications, create a view that processes AI requests:
These patterns integrate the gateway into your existing framework naturally without requiring architectural changes.

Testing Strategies

Testing code that calls AI models requires different approaches than testing deterministic functions. You can’t assert exact outputs since model responses vary, but you can test your code’s structure and error handling. Mock the ABV client for unit tests to avoid making actual API calls:
This approach tests your code’s logic without depending on external services, making tests fast and deterministic. For integration tests where you want to verify actual API behavior, make real requests but structure tests to be flexible about specific outputs:
This approach verifies that your API integration works without depending on specific model outputs, making tests more robust.

Next Steps

You now understand how to implement the gateway in Python applications, handle errors, manage conversations, and integrate with frameworks. Here’s where to go next:

TypeScript Guide

Learn how to implement the gateway in TypeScript/JavaScript applications

Available Models

See all supported providers and models with pricing

LLM Gateway Overview

Understand the core concepts and architecture of the gateway

Quickstart

Get up and running with your first gateway request in 5 minutes