Providers Module Documentation¶
This module provides different language model provider implementations for the LatteReview package. It handles interactions with various LLM APIs in a consistent, type-safe manner and now supports image-based inputs in addition to text inputs.
Overview¶
The providers module includes:
BaseProvider
: Abstract base class defining the provider interfaceOpenAIProvider
: Implementation for OpenAI API (including GPT models)OllamaProvider
: Implementation for local Ollama modelsLiteLLMProvider
: Implementation using LiteLLM for unified API access
** You can use any of the models offered by the providers above as far as they support structured outputs. **
BaseProvider¶
Description¶
The BaseProvider
class serves as the foundation for all LLM provider implementations. It provides a consistent interface and error handling for interacting with language models.
Class Definition¶
class BaseProvider(pydantic.BaseModel):
provider: str = "DefaultProvider"
client: Optional[Any] = None
api_key: Optional[str] = None
model: str = "default-model"
system_prompt: str = "You are a helpful assistant."
response_format: Optional[Any] = None
last_response: Optional[Any] = None
calculate_cost: bool = True # Controls whether to calculate token costs
Error Types¶
class ProviderError(Exception): pass
class ClientCreationError(ProviderError): pass
class ResponseError(ProviderError): pass
class InvalidResponseFormatError(ProviderError): pass
class ClientNotInitializedError(ProviderError): pass
Core Methods¶
create_client()
¶
Abstract method for initializing the provider's client.
def create_client(self) -> Any:
"""Create and initialize the client for the provider."""
raise NotImplementedError
get_response()
¶
Get a text or image response from the model.
async def get_response(
self,
input_prompt: str,
image_path_list: List[str],
message_list: Optional[List[Dict[str, str]]] = None,
system_message: Optional[str] = None,
) -> tuple[Any, Dict[str, float]]:
"""Get a response from the provider."""
raise NotImplementedError
get_json_response()
¶
Get a JSON-formatted response from the model.
async def get_json_response(
self,
input_prompt: str,
image_path_list: List[str],
message_list: Optional[List[Dict[str, str]]] = None,
system_message: Optional[str] = None,
) -> tuple[Any, Dict[str, float]]:
"""Get a JSON-formatted response from the provider."""
raise NotImplementedError
Cost Calculation¶
All providers include built-in cost calculation for both input and output tokens (by default using the tokencost
package, unless the provider offers unique solutions for cost calculation). This can be controlled using the calculate_cost
parameter:
# Initialize provider with cost calculation disabled
provider = BaseProvider(calculate_cost=False) # All costs will be 0
# Initialize provider with cost calculation enabled (default)
provider = BaseProvider(calculate_cost=True) # Costs will be calculated based on token usage
The cost calculation returns a dictionary with three values:
input_cost
: Cost of the input tokensoutput_cost
: Cost of the output tokenstotal_cost
: Sum of input and output costs
When calculate_cost
is False, all costs will be 0.
OpenAIProvider¶
Description¶
Implementation for OpenAI's API, supporting OpenAI models, Gemini models through a compatible endpoint, and OpenRouter's model marketplace. The updated version supports processing text and image inputs.
Class Definition¶
class OpenAIProvider(BaseProvider):
provider: str = "OpenAI"
api_key: str = None
base_url: str = None
model: str = "gpt-4o-mini"
response_format_class: Optional[Any] = None
Key Features¶
- Automatic API key handling from environment variables
- Support for OpenAI and Gemini models
- Custom base URL support for alternative endpoints
- OpenRouter integration for access to multiple model providers
- JSON response validation
- Image input handling
- Comprehensive error handling
Usage Example¶
from lattereview.providers import OpenAIProvider
# Initialize with OpenAI model
provider = OpenAIProvider(model="gpt-4o")
# Initialize with Gemini model
provider = OpenAIProvider(model="gemini/gemini-1.5-flash")
# Initialize with OpenRouter
provider = OpenAIProvider(
model="anthropic/claude-3-opus",
api_key="your_openrouter_key",
base_url="https://openrouter.ai/api/v1"
)
# Get a response
response, cost = await provider.get_response("What is the capital of the country shown in this map?", ["path/to/image.jpg"])
# Get JSON response
provider.set_response_format({"key": str, "value": int})
response, cost = await provider.get_json_response("Format this as JSON", [])
Using OpenRouter¶
OpenRouter provides access to a wide variety of language models through a unified API endpoint. To use OpenRouter with the OpenAIProvider:
- Sign up at OpenRouter to get an API key
- Set the following configuration:
base_url
: "https://openrouter.ai/api/v1"api_key
: Your OpenRouter API keymodel
: Any model available on OpenRouter (e.g., "anthropic/claude-3-opus", "meta-llama/llama-2-70b", etc.)
This gives you access to models from:
- Anthropic (Claude models)
- Meta (Llama models)
- Mistral
- Google (Gemini models)
- And many more
Example:
provider = OpenAIProvider(
model="mistral/mistral-large",
api_key="your_openrouter_key",
base_url="https://openrouter.ai/api/v1"
)
OllamaProvider¶
Description¶
Implementation for local Ollama models, supporting both chat and streaming responses. The updated version handles image inputs for advanced tasks.
Class Definition¶
class OllamaProvider(BaseProvider):
provider: str = "Ollama"
client: Optional[AsyncClient] = None
model: str = "llama3.2-vision:latest"
response_format_class: Optional[Any] = None
invalid_keywords: List[str] = ["temperature", "max_tokens"]
host: str = "http://localhost:11434"
Key Features¶
- Local model support
- Streaming capability
- Free cost tracking (local models)
- Image input processing
- Connection management
Usage Example¶
from lattereview.providers import OllamaProvider
# Initialize provider
provider = OllamaProvider(
model="llama3.2-vision:latest",
host="http://localhost:11434"
)
# Get response
response, cost = await provider.get_response("What is the capital of the country shown in this map?", ["path/to/image1.png"])
# Get JSON response with schema
provider.set_response_format({"answer": str, "confidence": float})
response, cost = await provider.get_json_response("What is the capital of France?", [])
# Stream response
async for chunk in provider.get_response("Tell me a story", [], stream=True):
print(chunk, end="")
# Clean up
await provider.close()
LiteLLMProvider¶
Description¶
A unified provider implementation using LiteLLM, enabling access to multiple LLM providers through a single interface. It now supports text and image-based interactions.
Class Definition¶
class LiteLLMProvider(BaseProvider):
provider: str = "LiteLLM"
model: str = "gpt-4o-mini"
custom_llm_provider: Optional[str] = None
response_format_class: Optional[Any] = None
Key Features¶
- Support for multiple model providers
- JSON schema validation
- Image input handling
- Cost tracking integration
- Tool calls handling
Usage Example¶
from lattereview.providers import LiteLLMProvider
# Initialize with different models
provider = LiteLLMProvider(model="gpt-4o-mini")
# Get response
response, cost = await provider.get_response("What is the capital of the country shown in this map?", ["path/to/image1.png"])
# Get JSON response with schema
provider.set_response_format({"answer": str, "confidence": float})
response, cost = await provider.get_json_response("What is the capital of France?", [])
Error Handling¶
Common error scenarios:
- API key errors (missing or invalid keys)
- Unsupported model configurations
- Models not supporting structured outputs or JSON responses
- Invalid image file paths
Best Practices¶
- For all online APIs, prefer using LiteLLMProvider class as it provides unified access and error handling.
- For local APIs, use OllamaProvider directly (rather than through LiteLLMProvider) for better performance and control.
- Set API keys at the environment level using the python-dotenv package and .env files for better security.
Limitations¶
- Requires async/await syntax for all operations
- Depends on external LLM providers' availability and stability
- Rate limits and quotas depend on provider capabilities