PARA.AI / api /processors /processor_llm_base.py
caarleexx's picture
Update api/processors/processor_llm_base.py
f504c37 verified
raw
history blame
4.26 kB
"""
Processor Base com integração LLMManager REAL
Classe abstrata para processors que usam LLM
"""
from typing import Dict, Any, Optional
from datetime import datetime
import logging
from abc import ABC, abstractmethod
logger = logging.getLogger(__name__)
class ProcessorLLMBase(ABC):
"""
Processor base que integra com LLM via client (GroqClient, etc).
Substitui hardcoded por prompts e chamadas reais.
"""
def __init__(
self,
specialist_id: int,
specialist_name: str,
llm_client=None
):
"""
Args:
specialist_id: ID do especialista (1-9)
specialist_name: Nome descritivo
llm_client: Cliente LLM (GroqClient, OpenAIClient, etc)
"""
self.specialist_id = specialist_id
self.specialist_name = specialist_name
self.llm_client = llm_client
self.execution_time = 0
self.confidence_score = 0
self.errors = []
self.warnings = []
if not llm_client:
self.add_warning("LLM client não configurado - usando fallback mock")
@abstractmethod
def process(self, acordao_data: Dict[str, Any]) -> Dict[str, Any]:
"""Processa acórdão usando LLM real."""
pass
@abstractmethod
def get_prompt(self, acordao_data: Dict[str, Any]) -> str:
"""Retorna prompt para o LLM."""
pass
@abstractmethod
def validate(self, result: Dict[str, Any]) -> bool:
"""Valida resultado."""
pass
def call_llm(
self,
prompt: str,
max_tokens: int = 2048,
temperature: float = 0.3,
model: Optional[str] = None
) -> str:
"""
Faz chamada ao LLM real via client.
Args:
prompt: Prompt a enviar
max_tokens: Máximo de tokens
temperature: Temperatura (0-1)
model: Modelo específico (opcional)
Returns:
Resposta do LLM (texto)
"""
if not self.llm_client:
self.add_error("LLM client não disponível")
return ""
try:
start_time = datetime.now()
logger.info(
f"[{self.specialist_name}] 🤖 Chamando LLM... "
f"(max_tokens={max_tokens}, temp={temperature})"
)
# Chamada real ao LLM via client
# GroqClient.generate() retorna LLMResponse com .content
response = self.llm_client.generate(
prompt=prompt,
model=model, # Opcional, usa default se None
temperature=temperature,
max_tokens=max_tokens
)
# Extrair conteúdo da resposta
# LLMResponse tem atributo .content
content = response.content if hasattr(response, 'content') else str(response)
elapsed = (datetime.now() - start_time).total_seconds()
self.execution_time += elapsed
logger.info(
f"[{self.specialist_name}] ✅ LLM respondeu em {elapsed:.2f}s "
f"({len(content)} chars)"
)
return content
except Exception as e:
self.add_error(f"Erro ao chamar LLM: {e}")
logger.error(f"[{self.specialist_name}] ❌ Erro LLM: {e}", exc_info=True)
return ""
def add_error(self, error_msg: str):
"""Adiciona erro."""
self.errors.append(error_msg)
def add_warning(self, warning_msg: str):
"""Adiciona aviso."""
self.warnings.append(warning_msg)
def set_confidence(self, score: int):
"""Define score de confiança (0-100)."""
if 0 <= score <= 100:
self.confidence_score = score
def postprocess(self, result: Dict[str, Any]) -> Dict[str, Any]:
"""Pós-processa resultado."""
return {
"specialist_id": self.specialist_id,
"specialist_name": self.specialist_name,
"result": result,
"execution_time": self.execution_time,
"confidence_score": self.confidence_score,
"errors": self.errors,
"warnings": self.warnings,
"timestamp": datetime.now().isoformat()
}