Spaces:
Runtime error
Runtime error
Upload processor_base.py
Browse files- processors/processor_base.py +64 -27
processors/processor_base.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
"""
|
| 2 |
Classe Base Refatorada - Com Schema Injection automático
|
|
|
|
| 3 |
"""
|
| 4 |
from abc import ABC
|
| 5 |
from typing import Dict, Any, Optional
|
|
@@ -21,7 +22,7 @@ class ProcessorBase(ABC):
|
|
| 21 |
FEATURES:
|
| 22 |
- Carrega configuração do YAML
|
| 23 |
- Schema injection automático no system_prompt
|
| 24 |
-
-
|
| 25 |
"""
|
| 26 |
|
| 27 |
def __init__(
|
|
@@ -131,7 +132,7 @@ REGRAS CRÍTICAS:
|
|
| 131 |
|
| 132 |
async def process(self, acordao_data: Dict[str, Any]) -> Dict[str, Any]:
|
| 133 |
"""
|
| 134 |
-
Processa acórdão usando LLM REAL
|
| 135 |
|
| 136 |
Args:
|
| 137 |
acordao_data: Dados do acórdão
|
|
@@ -164,21 +165,25 @@ REGRAS CRÍTICAS:
|
|
| 164 |
max_tokens=self.config.llm_config.max_tokens
|
| 165 |
)
|
| 166 |
|
| 167 |
-
# 3.
|
| 168 |
if response['status'] == 'success':
|
| 169 |
-
|
|
|
|
| 170 |
|
| 171 |
-
#
|
| 172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
try:
|
| 174 |
-
result = json.loads(
|
| 175 |
-
except json.JSONDecodeError:
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
raise ValueError("Resposta não é JSON válido")
|
| 182 |
|
| 183 |
# Validar
|
| 184 |
if not self.validate(result):
|
|
@@ -188,7 +193,9 @@ REGRAS CRÍTICAS:
|
|
| 188 |
self.confidence_score = self._calculate_confidence(result)
|
| 189 |
|
| 190 |
else:
|
| 191 |
-
|
|
|
|
|
|
|
| 192 |
|
| 193 |
# 4. Pós-processar
|
| 194 |
self.execution_time = (datetime.now() - start_time).total_seconds()
|
|
@@ -210,7 +217,7 @@ REGRAS CRÍTICAS:
|
|
| 210 |
|
| 211 |
def validate(self, result: Dict[str, Any]) -> bool:
|
| 212 |
"""
|
| 213 |
-
Valida resultado contra schema
|
| 214 |
|
| 215 |
Args:
|
| 216 |
result: Resultado a validar
|
|
@@ -221,12 +228,31 @@ REGRAS CRÍTICAS:
|
|
| 221 |
try:
|
| 222 |
# Validação básica: verificar campos required do schema
|
| 223 |
schema = self.config.schema
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
required_fields = schema.get('required', [])
|
|
|
|
|
|
|
|
|
|
| 225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
for field in required_fields:
|
| 227 |
if field not in result:
|
| 228 |
-
|
| 229 |
-
|
|
|
|
|
|
|
|
|
|
| 230 |
|
| 231 |
return True
|
| 232 |
|
|
@@ -236,22 +262,33 @@ REGRAS CRÍTICAS:
|
|
| 236 |
|
| 237 |
def _calculate_confidence(self, result: Dict[str, Any]) -> int:
|
| 238 |
"""
|
| 239 |
-
Calcula score de confiança baseado no resultado
|
| 240 |
|
| 241 |
Returns:
|
| 242 |
Score 0-100
|
| 243 |
"""
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
|
| 248 |
-
|
| 249 |
-
|
| 250 |
|
| 251 |
-
|
| 252 |
-
confidence = int((filled / len(required_fields)) * 100)
|
| 253 |
|
| 254 |
-
|
|
|
|
| 255 |
|
| 256 |
def post_process(self, result: Dict[str, Any]) -> Dict[str, Any]:
|
| 257 |
"""Pós-processa resultado"""
|
|
|
|
| 1 |
"""
|
| 2 |
Classe Base Refatorada - Com Schema Injection automático
|
| 3 |
+
Compatível com LLMManager do PARA.AI
|
| 4 |
"""
|
| 5 |
from abc import ABC
|
| 6 |
from typing import Dict, Any, Optional
|
|
|
|
| 22 |
FEATURES:
|
| 23 |
- Carrega configuração do YAML
|
| 24 |
- Schema injection automático no system_prompt
|
| 25 |
+
- Compatível com LLMManager (await llm_manager.generate())
|
| 26 |
"""
|
| 27 |
|
| 28 |
def __init__(
|
|
|
|
| 132 |
|
| 133 |
async def process(self, acordao_data: Dict[str, Any]) -> Dict[str, Any]:
|
| 134 |
"""
|
| 135 |
+
Processa acórdão usando LLM REAL via LLMManager.
|
| 136 |
|
| 137 |
Args:
|
| 138 |
acordao_data: Dados do acórdão
|
|
|
|
| 165 |
max_tokens=self.config.llm_config.max_tokens
|
| 166 |
)
|
| 167 |
|
| 168 |
+
# 3. Processar resposta do LLMManager
|
| 169 |
if response['status'] == 'success':
|
| 170 |
+
# response['result'] contém o dict do client: {'content': ..., 'tokens_input': ...}
|
| 171 |
+
llm_result = response['result']
|
| 172 |
|
| 173 |
+
# Extrair content e tokens
|
| 174 |
+
content = llm_result.get('content', '{}')
|
| 175 |
+
tokens_total = llm_result.get('total_tokens', 0)
|
| 176 |
+
|
| 177 |
+
# Parse JSON se for string
|
| 178 |
+
if isinstance(content, str):
|
| 179 |
try:
|
| 180 |
+
result = json.loads(content)
|
| 181 |
+
except json.JSONDecodeError as e:
|
| 182 |
+
logger.error(f"❌ JSON inválido: {e}")
|
| 183 |
+
logger.debug(f"Content recebido: {content[:500]}")
|
| 184 |
+
raise ValueError(f"Resposta não é JSON válido: {e}")
|
| 185 |
+
else:
|
| 186 |
+
result = content
|
|
|
|
| 187 |
|
| 188 |
# Validar
|
| 189 |
if not self.validate(result):
|
|
|
|
| 193 |
self.confidence_score = self._calculate_confidence(result)
|
| 194 |
|
| 195 |
else:
|
| 196 |
+
# Erro na chamada LLM
|
| 197 |
+
error_msg = response.get('error', 'Erro desconhecido')
|
| 198 |
+
raise ValueError(f"Erro na chamada LLM: {error_msg}")
|
| 199 |
|
| 200 |
# 4. Pós-processar
|
| 201 |
self.execution_time = (datetime.now() - start_time).total_seconds()
|
|
|
|
| 217 |
|
| 218 |
def validate(self, result: Dict[str, Any]) -> bool:
|
| 219 |
"""
|
| 220 |
+
Valida resultado contra schema.
|
| 221 |
|
| 222 |
Args:
|
| 223 |
result: Resultado a validar
|
|
|
|
| 228 |
try:
|
| 229 |
# Validação básica: verificar campos required do schema
|
| 230 |
schema = self.config.schema
|
| 231 |
+
|
| 232 |
+
# Verifica se schema existe e tem required fields
|
| 233 |
+
if not isinstance(schema, dict):
|
| 234 |
+
logger.warning(f"⚠️ Schema não é um dict para {self.specialist_name}")
|
| 235 |
+
return True
|
| 236 |
+
|
| 237 |
required_fields = schema.get('required', [])
|
| 238 |
+
if not required_fields:
|
| 239 |
+
logger.debug(f"✓ Schema sem campos required para {self.specialist_name}")
|
| 240 |
+
return True
|
| 241 |
|
| 242 |
+
# Verifica se result é dict
|
| 243 |
+
if not isinstance(result, dict):
|
| 244 |
+
self.add_warning(f"Resultado não é um dict: {type(result)}")
|
| 245 |
+
return False
|
| 246 |
+
|
| 247 |
+
# Verifica campos required
|
| 248 |
+
missing_fields = []
|
| 249 |
for field in required_fields:
|
| 250 |
if field not in result:
|
| 251 |
+
missing_fields.append(field)
|
| 252 |
+
|
| 253 |
+
if missing_fields:
|
| 254 |
+
self.add_warning(f"Campos obrigatórios ausentes: {', '.join(missing_fields)}")
|
| 255 |
+
return False
|
| 256 |
|
| 257 |
return True
|
| 258 |
|
|
|
|
| 262 |
|
| 263 |
def _calculate_confidence(self, result: Dict[str, Any]) -> int:
|
| 264 |
"""
|
| 265 |
+
Calcula score de confiança baseado no resultado.
|
| 266 |
|
| 267 |
Returns:
|
| 268 |
Score 0-100
|
| 269 |
"""
|
| 270 |
+
try:
|
| 271 |
+
# Lógica simples: quanto mais campos preenchidos, maior confiança
|
| 272 |
+
schema = self.config.schema
|
| 273 |
+
|
| 274 |
+
if not isinstance(schema, dict):
|
| 275 |
+
return 85 # Padrão se schema inválido
|
| 276 |
+
|
| 277 |
+
required_fields = schema.get('required', [])
|
| 278 |
+
|
| 279 |
+
if not required_fields:
|
| 280 |
+
return 85 # Padrão
|
| 281 |
+
|
| 282 |
+
if not isinstance(result, dict):
|
| 283 |
+
return 0
|
| 284 |
|
| 285 |
+
filled = sum(1 for field in required_fields if result.get(field))
|
| 286 |
+
confidence = int((filled / len(required_fields)) * 100)
|
| 287 |
|
| 288 |
+
return min(confidence, 100)
|
|
|
|
| 289 |
|
| 290 |
+
except Exception:
|
| 291 |
+
return 85
|
| 292 |
|
| 293 |
def post_process(self, result: Dict[str, Any]) -> Dict[str, Any]:
|
| 294 |
"""Pós-processa resultado"""
|