Introduction
In this tutorial, we'll explore how to work with AI model APIs, similar to what OpenRouter provides. You'll learn how to interact with multiple AI models through a unified interface, understand tokenization concepts, and build a simple application that can switch between different AI providers. This tutorial mirrors the kind of infrastructure that companies like Stripe might be building to support AI services at scale.
Prerequisites
- Basic understanding of Python programming
- Python 3.8 or higher installed
- Access to API keys from at least one AI provider (OpenAI, Anthropic, or Hugging Face)
- Basic knowledge of REST APIs and HTTP requests
Step-by-Step Instructions
1. Set Up Your Development Environment
We'll start by creating a virtual environment and installing the required dependencies. This ensures we have a clean, isolated space for our project.
python -m venv ai_api_env
source ai_api_env/bin/activate # On Windows: ai_api_env\Scripts\activate
pip install openai anthropic requests
Why: Creating a virtual environment isolates our project dependencies from the system-wide Python installation, preventing conflicts with other projects.
2. Create a Configuration File
Next, we'll create a configuration file to store our API keys securely. This is crucial for any production application.
# config.py
import os
from dotenv import load_dotenv
load_dotenv()
# AI Provider Configuration
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY')
HUGGINGFACE_API_KEY = os.getenv('HUGGINGFACE_API_KEY')
# Model Selection
DEFAULT_MODEL = 'gpt-4'
AVAILABLE_MODELS = {
'openai': ['gpt-4', 'gpt-3.5-turbo'],
'anthropic': ['claude-3-opus', 'claude-3-sonnet'],
'huggingface': ['meta-llama/Llama-2-7b-chat-hf']
}
Why: Using environment variables keeps sensitive information out of your codebase, which is essential for security.
3. Create an AI Model Interface
Now we'll create a base class that defines how different AI providers should behave, making it easy to switch between them.
# ai_interface.py
from abc import ABC, abstractmethod
class AIModelInterface(ABC):
@abstractmethod
def generate_response(self, prompt: str, **kwargs):
pass
@abstractmethod
def get_model_info(self):
pass
Why: Using an abstract base class ensures all AI model implementations follow the same interface, making your code more maintainable and extensible.
4. Implement OpenAI Integration
We'll now create a concrete implementation for OpenAI's API:
# openai_model.py
from ai_interface import AIModelInterface
from openai import OpenAI
import os
class OpenAIModel(AIModelInterface):
def __init__(self, api_key: str, model_name: str = 'gpt-4'):
self.client = OpenAI(api_key=api_key)
self.model_name = model_name
def generate_response(self, prompt: str, **kwargs):
try:
response = self.client.chat.completions.create(
model=self.model_name,
messages=[{'role': 'user', 'content': prompt}],
**kwargs
)
return response.choices[0].message.content
except Exception as e:
return f"Error generating response: {str(e)}"
def get_model_info(self):
return {
'provider': 'openai',
'model': self.model_name,
'type': 'chat_completion'
}
Why: This implementation follows the interface we defined earlier, allowing us to easily add more providers later without changing the rest of our code.
5. Implement Anthropic Integration
Similarly, we'll implement Anthropic's Claude API:
# anthropic_model.py
from ai_interface import AIModelInterface
import anthropic
class AnthropicModel(AIModelInterface):
def __init__(self, api_key: str, model_name: str = 'claude-3-opus'):
self.client = anthropic.Anthropic(api_key=api_key)
self.model_name = model_name
def generate_response(self, prompt: str, **kwargs):
try:
response = self.client.messages.create(
model=self.model_name,
max_tokens=1000,
messages=[{'role': 'user', 'content': prompt}],
**kwargs
)
return response.content[0].text
except Exception as e:
return f"Error generating response: {str(e)}"
def get_model_info(self):
return {
'provider': 'anthropic',
'model': self.model_name,
'type': 'message'
}
Why: Having separate implementations for each provider allows us to handle provider-specific features and error handling appropriately.
6. Create a Model Manager
This component will act as a central hub for switching between different AI models:
# model_manager.py
from openai_model import OpenAIModel
from anthropic_model import AnthropicModel
from config import OPENAI_API_KEY, ANTHROPIC_API_KEY, DEFAULT_MODEL, AVAILABLE_MODELS
class ModelManager:
def __init__(self):
self.models = {}
self.current_model = None
self._initialize_models()
def _initialize_models(self):
if OPENAI_API_KEY:
self.models['openai'] = OpenAIModel(OPENAI_API_KEY)
if ANTHROPIC_API_KEY:
self.models['anthropic'] = AnthropicModel(ANTHROPIC_API_KEY)
def switch_model(self, provider: str, model_name: str):
if provider not in self.models:
raise ValueError(f"Provider {provider} not available")
# For simplicity, we're not creating new instances here
# In a real application, you'd want to handle this more elegantly
self.current_model = self.models[provider]
print(f"Switched to {provider} model: {model_name}")
def generate_response(self, prompt: str, **kwargs):
if not self.current_model:
raise ValueError("No model selected")
return self.current_model.generate_response(prompt, **kwargs)
def get_available_models(self):
return AVAILABLE_MODELS
Why: The ModelManager acts as a bridge between your application logic and the various AI providers, providing a clean way to switch between models.
7. Test Your Implementation
Finally, let's create a simple test script to verify everything works:
# test_ai_integration.py
from model_manager import ModelManager
def main():
# Initialize the model manager
manager = ModelManager()
# Switch to OpenAI model
manager.switch_model('openai', 'gpt-4')
# Test prompt
prompt = "Explain the concept of tokenization in AI models"
response = manager.generate_response(prompt)
print("OpenAI Response:")
print(response)
# Switch to Anthropic model
manager.switch_model('anthropic', 'claude-3-opus')
response = manager.generate_response(prompt)
print("\nAnthropic Response:")
print(response)
if __name__ == "__main__":
main()
Why: Testing ensures that our integration works as expected and helps us catch any issues early in the development process.
Summary
This tutorial demonstrated how to build a flexible AI model interface that can work with multiple providers like OpenAI and Anthropic. We've created a system that mirrors what companies like Stripe might be building to offer unified access to various AI models, similar to what OpenRouter provides. The key concepts covered include:
- Using abstract base classes for consistent interfaces
- Implementing provider-specific logic
- Managing API keys securely
- Building a model switching mechanism
This approach allows you to easily extend the system to include more AI providers or add new features like token usage tracking, rate limiting, or caching mechanisms.



