Spaces:
Sleeping
Sleeping
File size: 5,096 Bytes
e982206 |
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 146 147 148 |
"""
Nó para seleção do tipo de gráfico usando LLM - REFATORADO COMPLETO
"""
import logging
import re
import pandas as pd
from typing import Dict, Any, Optional
from agents.tools import (
generate_graph_type_context,
extract_sql_query_from_response
)
from utils.config import OPENAI_API_KEY
from langchain_openai import ChatOpenAI
from utils.object_manager import get_object_manager
# Mapeamento DIRETO no arquivo para evitar problemas externos
GRAPH_TYPE_MAPPING = {
"1": "line_simple",
"2": "multiline",
"3": "area",
"4": "bar_vertical",
"5": "bar_horizontal",
"6": "bar_grouped",
"7": "bar_stacked",
"8": "pie",
"9": "donut",
"10": "pie_multiple"
}
async def graph_selection_node(state: Dict[str, Any]) -> Dict[str, Any]:
"""
Nó REFATORADO para seleção do tipo de gráfico usando LLM
"""
logging.info("[GRAPH_SELECTION_NEW] 🚀 Iniciando seleção REFATORADA")
try:
# 1. Verificações básicas
if state.get("query_type") != "sql_query_graphic":
logging.info("[GRAPH_SELECTION_NEW] Query não requer gráfico")
return state
# 2. Obter SQL query
sql_query = state.get("sql_query_extracted")
if not sql_query:
sql_query = extract_sql_query_from_response(state.get("response", ""))
if not sql_query:
logging.error("[GRAPH_SELECTION_NEW] ❌ SQL query não encontrada")
state.update({"graph_error": "SQL query não encontrada", "graph_generated": False})
return state
# 3. Obter dados
obj_manager = get_object_manager()
engine = obj_manager.get_engine(state.get("engine_id"))
if not engine:
logging.error("[GRAPH_SELECTION_NEW] ❌ Engine não encontrada")
state.update({"graph_error": "Engine não encontrada", "graph_generated": False})
return state
# 4. Executar query
try:
df_result = pd.read_sql_query(sql_query, engine)
if df_result.empty:
logging.error("[GRAPH_SELECTION_NEW] ❌ Dados vazios")
state.update({"graph_error": "Dados vazios", "graph_generated": False})
return state
except Exception as e:
logging.error(f"[GRAPH_SELECTION_NEW] ❌ Erro na query: {e}")
state.update({"graph_error": f"Erro na query: {e}", "graph_generated": False})
return state
# 5. Preparar contexto
user_query = state.get("user_input", "")
df_sample = df_result.head(3)
graph_context = generate_graph_type_context(user_query, sql_query, df_result.columns.tolist(), df_sample)
# 6. Chamar LLM de forma LIMPA
graph_type = await call_llm_for_graph_selection(graph_context, user_query)
logging.error(f"🎯 [RESULTADO_FINAL] Tipo selecionado: '{graph_type}'")
# 7. Armazenar resultado
graph_data_id = obj_manager.store_object(df_result, "graph_data")
state.update({
"graph_type": graph_type,
"graph_data": {
"data_id": graph_data_id,
"columns": df_result.columns.tolist(),
"rows": len(df_result),
"sample": df_sample.to_dict()
},
"graph_error": None
})
return state
except Exception as e:
logging.error(f"[GRAPH_SELECTION_NEW] ❌ Erro geral: {e}")
state.update({"graph_error": f"Erro geral: {e}", "graph_generated": False})
return state
async def call_llm_for_graph_selection(graph_context: str, user_query: str) -> str:
"""
Função NOVA e LIMPA para chamar LLM sem interferências
"""
logging.error("🔥 [LLM_CALL] Iniciando chamada LIMPA da LLM")
# Verificação básica
if not OPENAI_API_KEY:
logging.error("🔥 [LLM_CALL] OpenAI não configurada")
return "line_simple"
try:
# Criar LLM com configuração limpa
llm = ChatOpenAI(
model="gpt-4o",
temperature=0,
max_tokens=5,
timeout=30
)
# Log do contexto
logging.error("🔥 [LLM_CALL] Contexto enviado:")
logging.error(f"'{graph_context}...'")
# Agora a pergunta real
real_response = llm.invoke(graph_context)
real_content = real_response.content.strip()
logging.error(f"🔥 [LLM_CALL] Resposta REAL: '{real_content}'")
# Extrair número da resposta
number_match = re.search(r'\b([1-9]|10)\b', real_content)
if number_match:
number = number_match.group(0)
graph_type = GRAPH_TYPE_MAPPING.get(number, "line_simple")
logging.error(f"🔥 [LLM_CALL] Número: {number} → Tipo: {graph_type}")
return graph_type
else:
logging.error(f"🔥 [LLM_CALL] Número não encontrado em: '{real_content}'")
return "line_simple"
except Exception as e:
logging.error(f"🔥 [LLM_CALL] ERRO: {e}")
return "line_simple"
|