rag_template / src /llms /factory.py
Guilherme Favaron
Major update: Add hybrid search, reranking, multiple LLMs, and UI improvements
1b447de
"""
Factory para criação de providers LLM com fallback automático
"""
import os
from typing import Optional, List, Dict, Any
from .base import BaseLLM
from .huggingface import HuggingFaceLLM
from .openai import OpenAILLM
from .anthropic import AnthropicLLM
from .ollama import OllamaLLM
def create_llm(
provider: Optional[str] = None,
model_id: Optional[str] = None,
fallback: bool = True,
**kwargs
) -> Optional[BaseLLM]:
"""
Cria instância de LLM com base no provider especificado
Args:
provider: Nome do provider (huggingface, openai, anthropic, ollama)
Se None, usa variável de ambiente LLM_PROVIDER
model_id: ID do modelo. Se None, usa default do provider
fallback: Se True, tenta outros providers em caso de falha
**kwargs: Argumentos adicionais para o provider
Returns:
Instância de BaseLLM ou None se nenhum provider disponível
"""
# Define provider
if provider is None:
provider = os.getenv("LLM_PROVIDER", "huggingface").lower()
# Lista de providers para tentar (com fallback)
if fallback:
providers_to_try = _get_fallback_order(provider)
else:
providers_to_try = [provider]
# Tenta cada provider
for prov in providers_to_try:
llm = _create_provider(prov, model_id, **kwargs)
if llm and llm.is_available():
return llm
return None
def _get_fallback_order(primary: str) -> List[str]:
"""
Define ordem de fallback com base no provider primário
Args:
primary: Provider primário
Returns:
Lista de providers na ordem de tentativa
"""
# Ordem de preferência: primário -> outros disponíveis
all_providers = ["huggingface", "openai", "anthropic", "ollama"]
# Coloca primário primeiro
if primary in all_providers:
all_providers.remove(primary)
all_providers.insert(0, primary)
return all_providers
def _create_provider(
provider: str,
model_id: Optional[str] = None,
**kwargs
) -> Optional[BaseLLM]:
"""
Cria instância específica de provider
Args:
provider: Nome do provider
model_id: ID do modelo
**kwargs: Argumentos adicionais
Returns:
Instância de BaseLLM ou None
"""
try:
if provider == "huggingface":
if model_id is None:
model_id = os.getenv("HF_MODEL_ID", "mistralai/Mistral-7B-Instruct-v0.2")
api_token = os.getenv("HF_TOKEN", "")
return HuggingFaceLLM(model_id, api_token, **kwargs)
elif provider == "openai":
if model_id is None:
model_id = os.getenv("OPENAI_MODEL_ID", "gpt-3.5-turbo")
api_key = os.getenv("OPENAI_API_KEY", "")
return OpenAILLM(model_id, api_key, **kwargs)
elif provider == "anthropic":
if model_id is None:
model_id = os.getenv("ANTHROPIC_MODEL_ID", "claude-3-haiku-20240307")
api_key = os.getenv("ANTHROPIC_API_KEY", "")
return AnthropicLLM(model_id, api_key, **kwargs)
elif provider == "ollama":
if model_id is None:
model_id = os.getenv("OLLAMA_MODEL_ID", "llama2")
base_url = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
return OllamaLLM(model_id, base_url, **kwargs)
else:
return None
except Exception:
return None
def get_available_providers() -> Dict[str, Dict[str, Any]]:
"""
Lista todos os providers disponíveis e suas informações
Returns:
Dicionário com informações de cada provider
"""
providers_info = {}
for provider_name in ["huggingface", "openai", "anthropic", "ollama"]:
llm = _create_provider(provider_name)
if llm:
providers_info[provider_name] = {
"available": llm.is_available(),
"info": llm.get_model_info(),
"error": llm.last_error if llm.last_error else None
}
else:
providers_info[provider_name] = {
"available": False,
"info": None,
"error": "Provider não pôde ser criado"
}
return providers_info