File size: 4,307 Bytes
1b447de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
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