Spaces:
Running
Running
| """Cliente de inferência hospedada (Hugging Face Inference Providers). | |
| Em vez de rodar o modelo localmente (lento em CPU), envia o prompt para um | |
| modelo bom hospedado nos provedores roteados pela Hugging Face (GPU), via API | |
| compatível com OpenAI (``chat.completions``). Rápido e 100% online. | |
| Requisitos: | |
| - ``HF_TOKEN`` com permissão de uso de Inference Providers. | |
| - ``HF_INFERENCE_MODEL`` (ex.: ``Qwen/Qwen2.5-7B-Instruct``). | |
| Princípio do projeto: a IA apenas interpreta; nunca calcula indicadores. | |
| Qualquer falha levanta :class:`HFInferenceError` para acionar o fallback. | |
| """ | |
| from __future__ import annotations | |
| from ..utils.logger import get_logger | |
| logger = get_logger("models.hf_inference") | |
| class HFInferenceError(RuntimeError): | |
| """Erro controlado ao usar a inferência hospedada da Hugging Face.""" | |
| class HFInferenceClient: | |
| """Encapsula chamadas de chat à Inference API da Hugging Face.""" | |
| def __init__( | |
| self, | |
| model: str, | |
| token: str, | |
| max_tokens: int = 320, | |
| provider: str | None = None, | |
| temperature: float = 0.3, | |
| ) -> None: | |
| """Inicializa o cliente. | |
| Args: | |
| model: Repo do modelo (ex.: ``Qwen/Qwen2.5-7B-Instruct``). | |
| token: Token da Hugging Face (``HF_TOKEN``). | |
| max_tokens: Limite de tokens da resposta. | |
| provider: Provedor específico (opcional; ``None`` = roteamento automático). | |
| temperature: Temperatura de amostragem (baixa = mais objetivo). | |
| Raises: | |
| HFInferenceError: Se faltar token ou modelo. | |
| """ | |
| if not token: | |
| raise HFInferenceError( | |
| "HF_TOKEN não configurado para inferência hospedada." | |
| ) | |
| if not model: | |
| raise HFInferenceError( | |
| "HF_INFERENCE_MODEL não configurado. Ex.: Qwen/Qwen2.5-7B-Instruct." | |
| ) | |
| self._model = model | |
| self._token = token | |
| self._max_tokens = max_tokens | |
| self._provider = provider or None | |
| self._temperature = temperature | |
| def gerar(self, prompt: str, system: str | None = None) -> str: | |
| """Gera a interpretação via chat completion hospedada. | |
| Args: | |
| prompt: Prompt com o JSON de métricas já calculado. | |
| system: Instrução de sistema (papel do modelo). | |
| Returns: | |
| Texto interpretativo gerado pelo modelo. | |
| Raises: | |
| HFInferenceError: Em qualquer falha de dependência, rede ou resposta. | |
| """ | |
| try: | |
| from huggingface_hub import InferenceClient # import tardio | |
| except ImportError as exc: # pragma: no cover - depende do ambiente | |
| raise HFInferenceError( | |
| "Dependência ausente. Instale: pip install huggingface_hub" | |
| ) from exc | |
| mensagens: list[dict[str, str]] = [] | |
| if system: | |
| mensagens.append({"role": "system", "content": system}) | |
| mensagens.append({"role": "user", "content": prompt}) | |
| try: | |
| kwargs: dict[str, object] = {"token": self._token} | |
| if self._provider: | |
| kwargs["provider"] = self._provider | |
| cliente = InferenceClient(**kwargs) | |
| resposta = cliente.chat.completions.create( | |
| model=self._model, | |
| messages=mensagens, | |
| max_tokens=self._max_tokens, | |
| temperature=self._temperature, | |
| ) | |
| except Exception as exc: # rede, modelo indisponível, créditos, etc. | |
| # Não vaza o token; apenas o tipo/mensagem do erro. | |
| raise HFInferenceError( | |
| f"Falha na inferência hospedada: {type(exc).__name__}: {exc}" | |
| ) from exc | |
| try: | |
| texto = (resposta.choices[0].message.content or "").strip() | |
| except (AttributeError, IndexError, TypeError) as exc: | |
| raise HFInferenceError("Resposta de inferência sem conteúdo.") from exc | |
| if not texto: | |
| raise HFInferenceError("Inferência hospedada retornou resposta vazia.") | |
| logger.info("Interpretação gerada via HF Inference (model=%s).", self._model) | |
| return texto | |