🔍 Code Extractor

class LLMClient

Maturity: 51

Multi-LLM client that provides a unified interface for interacting with OpenAI GPT-4o, Azure OpenAI, Google Gemini, and Anthropic Claude models.

File:
/tf/active/vicechatdev/vice_ai/new_app.py
Lines:
134 - 247
Complexity:
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 history
  • max_tokens: Maximum number of tokens to generate in the response. Default is 4000
  • temperature: 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

  • openai
  • google-generativeai
  • anthropic
  • typing

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

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class LLMClient_v2 79.5% similar

    Client for interacting with LLM providers (OpenAI, Anthropic, Azure, etc.)

    From: /tf/active/vicechatdev/contract_validity_analyzer/utils/llm_client.py
  • class LLMClient_v1 78.7% similar

    A client class for interacting with Large Language Models (LLMs), specifically designed to work with OpenAI's chat completion API.

    From: /tf/active/vicechatdev/QA_updater/core/llm_client.py
  • function get_llm_instance 76.6% similar

    Factory function that creates and returns an appropriate LLM (Large Language Model) instance based on the specified model name, automatically detecting the provider (OpenAI, Azure OpenAI, or Anthropic) and configuring it with the given parameters.

    From: /tf/active/vicechatdev/docchat/llm_factory.py
  • class OpenAIChatLLM 71.4% similar

    Adapter class for interacting with OpenAI's Chat Completions API, supporting both GPT-4 and GPT-5 model families with automatic parameter adjustment based on model type.

    From: /tf/active/vicechatdev/docchat/llm_factory.py
  • class AzureOpenAIChatLLM 67.2% similar

    Adapter class for interacting with Azure OpenAI's Chat Completions API, providing a simplified interface for generating chat responses using Azure-hosted OpenAI models.

    From: /tf/active/vicechatdev/docchat/llm_factory.py
← Back to Browse