class LLMClient
Multi-LLM client that provides a unified interface for interacting with OpenAI GPT-4o, Azure OpenAI, Google Gemini, and Anthropic Claude models.
/tf/active/vicechatdev/vice_ai/new_app.py
134 - 247
moderate
Purpose
This class abstracts the complexity of working with multiple LLM providers by offering a single, consistent interface for generating text responses. It handles provider-specific authentication, message formatting, and API calls, allowing developers to switch between different LLM models without changing their application code. The class supports four major LLM providers and automatically configures the appropriate client based on the selected model.
Source Code
class LLMClient:
"""Multi-LLM client that supports OpenAI GPT-4o, Azure OpenAI, Google Gemini, and Anthropic Claude"""
def __init__(self, model: str = None, api_key: str = None):
"""Initialize the LLM client with specified model and API key."""
self.model = (model or LLM_CONFIG['default_model']).lower()
if self.model == "gpt-4o":
if not OPENAI_AVAILABLE:
raise Exception("OpenAI library not installed. Run: pip install openai")
api_key = api_key or LLM_CONFIG['openai_api_key']
if not api_key:
raise Exception("OpenAI API key not provided")
self.client = openai.OpenAI(api_key=api_key)
elif self.model == "azure-gpt-4o":
if not OPENAI_AVAILABLE:
raise Exception("OpenAI library not installed. Run: pip install openai")
azure_endpoint = LLM_CONFIG['azure_openai_endpoint']
azure_api_key = api_key or LLM_CONFIG['azure_openai_api_key']
if not azure_endpoint or not azure_api_key:
raise Exception("Azure OpenAI endpoint and API key must be provided")
# Ensure the endpoint has the correct format
if azure_endpoint.endswith('/'):
azure_endpoint = azure_endpoint.rstrip('/')
self.client = openai.AzureOpenAI(
api_key=azure_api_key,
api_version="2024-08-01-preview",
azure_endpoint=azure_endpoint
)
elif self.model == "gemini":
if not GEMINI_AVAILABLE:
raise Exception("Google Generative AI library not installed. Run: pip install google-generativeai")
api_key = api_key or LLM_CONFIG['gemini_api_key']
if not api_key:
raise Exception("Gemini API key not provided")
genai.configure(api_key=api_key)
self.client = genai.GenerativeModel('gemini-2.0-flash-exp')
elif self.model == "claude-sonnet-4-5-20250929":
if not ANTHROPIC_AVAILABLE:
raise Exception("Anthropic library not installed. Run: pip install anthropic")
api_key = api_key or LLM_CONFIG['anthropic_api_key']
if not api_key:
raise Exception("Anthropic API key not provided")
self.client = anthropic.Anthropic(api_key=api_key)
else:
raise Exception(f"Unsupported model: {self.model}. Choose 'gpt-4o', 'azure-gpt-4o', 'gemini', or 'claude-sonnet-4-5-20250929'")
def generate_response(self, messages: List[Dict[str, str]], max_tokens: int = 4000, temperature: float = 0.7) -> str:
"""Generate a response using the configured LLM model"""
try:
if self.model in ["gpt-4o", "azure-gpt-4o"]:
# Use appropriate model name for the platform
model_name = "OneCo-gpt" if self.model == "azure-gpt-4o" else "gpt-4o"
response = self.client.chat.completions.create(
model=model_name,
messages=messages,
max_tokens=max_tokens,
temperature=temperature
)
return response.choices[0].message.content
elif self.model == "gemini":
# Convert messages to Gemini format
if len(messages) == 1:
prompt = messages[0]["content"]
else:
# Combine system and user messages
prompt = "\n\n".join([msg["content"] for msg in messages])
response = self.client.generate_content(
prompt,
generation_config=genai.types.GenerationConfig(
max_output_tokens=max_tokens,
temperature=temperature,
)
)
return response.text
elif self.model == "claude-sonnet-4-5-20250929":
# Convert messages to Claude format (separate system and messages)
system_message = None
claude_messages = []
for msg in messages:
if msg["role"] == "system":
system_message = msg["content"]
else:
claude_messages.append(msg)
# If no claude_messages but we have content, create a user message
if not claude_messages and system_message:
claude_messages = [{"role": "user", "content": system_message}]
system_message = None
response = self.client.messages.create(
model="claude-3-5-sonnet-20241022", # Use the actual model name
max_tokens=max_tokens,
temperature=temperature,
system=system_message,
messages=claude_messages
)
return response.content[0].text
except Exception as e:
logger.error(f"Error generating response with {self.model}: {e}")
raise Exception(f"Failed to generate response: {e}")
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
- | - |
Parameter Details
model: String identifier for the LLM model to use. Accepts 'gpt-4o' (OpenAI), 'azure-gpt-4o' (Azure OpenAI), 'gemini' (Google Gemini 2.0 Flash), or 'claude-sonnet-4-5-20250929' (Anthropic Claude). If not provided, uses the default model from LLM_CONFIG. Case-insensitive.
api_key: API key for authenticating with the selected LLM provider. If not provided, the class attempts to retrieve the key from LLM_CONFIG dictionary based on the selected model. Required for all models but can be configured globally.
Return Value
The __init__ method returns an instance of LLMClient with a configured client attribute specific to the chosen model. The generate_response method returns a string containing the LLM's generated text response to the provided messages.
Class Interface
Methods
__init__(self, model: str = None, api_key: str = None)
Purpose: Initialize the LLM client with the specified model and API key, configuring the appropriate provider-specific client
Parameters:
model: String identifier for the LLM model ('gpt-4o', 'azure-gpt-4o', 'gemini', 'claude-sonnet-4-5-20250929'). Defaults to LLM_CONFIG['default_model']api_key: API key for authentication. If not provided, retrieved from LLM_CONFIG based on the model
Returns: None (constructor)
generate_response(self, messages: List[Dict[str, str]], max_tokens: int = 4000, temperature: float = 0.7) -> str
Purpose: Generate a text response from the configured LLM model based on the provided conversation messages
Parameters:
messages: List of message dictionaries with 'role' (system/user/assistant) and 'content' keys representing the conversation historymax_tokens: Maximum number of tokens to generate in the response. Default is 4000temperature: Controls randomness in generation (0.0-1.0). Higher values produce more creative outputs. Default is 0.7
Returns: String containing the generated text response from the LLM
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
model |
str | Lowercase string identifier of the currently configured LLM model | instance |
client |
Union[openai.OpenAI, openai.AzureOpenAI, genai.GenerativeModel, anthropic.Anthropic] | Provider-specific client instance used to make API calls to the LLM service | instance |
Dependencies
openaigoogle-generativeaianthropictyping
Required Imports
from typing import List, Dict
Conditional/Optional Imports
These imports are only needed under specific conditions:
import openai
Condition: Required when using 'gpt-4o' or 'azure-gpt-4o' models
Required (conditional)import google.generativeai as genai
Condition: Required when using 'gemini' model
Required (conditional)import anthropic
Condition: Required when using 'claude-sonnet-4-5-20250929' model
Required (conditional)Usage Example
# Setup configuration
LLM_CONFIG = {
'default_model': 'gpt-4o',
'openai_api_key': 'sk-...',
'azure_openai_endpoint': 'https://your-resource.openai.azure.com',
'azure_openai_api_key': 'your-azure-key',
'gemini_api_key': 'your-gemini-key',
'anthropic_api_key': 'your-anthropic-key'
}
# Instantiate client with default model
client = LLMClient()
# Or specify a model explicitly
client = LLMClient(model='gemini', api_key='your-api-key')
# Generate a response
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
]
response = client.generate_response(
messages=messages,
max_tokens=1000,
temperature=0.7
)
print(response) # Output: 'The capital of France is Paris.'
Best Practices
- Always ensure the appropriate LLM library is installed before instantiating the client with that model
- Configure LLM_CONFIG dictionary with all necessary API keys and endpoints before creating instances
- Handle exceptions when calling generate_response as API calls may fail due to network issues or rate limits
- The client is stateless - each generate_response call is independent, so you can reuse the same instance for multiple requests
- For Azure OpenAI, ensure the endpoint URL does not have a trailing slash (the class handles this automatically)
- Message format should follow the standard chat format with 'role' and 'content' keys
- For Claude models, system messages are handled separately from conversation messages
- For Gemini, messages are concatenated into a single prompt if multiple messages are provided
- Consider implementing retry logic and rate limiting when making multiple API calls
- Store API keys securely using environment variables rather than hardcoding them
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class LLMClient_v2 79.5% similar
-
class LLMClient_v1 78.7% similar
-
function get_llm_instance 76.6% similar
-
class OpenAIChatLLM 71.4% similar
-
class AzureOpenAIChatLLM 67.2% similar