Upload app.py
Browse files
app.py
CHANGED
|
@@ -959,4 +959,90 @@ async def entity_graph_api(job_id: str = Form(...)):
|
|
| 959 |
|
| 960 |
except Exception as e:
|
| 961 |
logging.error(f"ERRO EM /entity_graph/: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 962 |
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
| 959 |
|
| 960 |
except Exception as e:
|
| 961 |
logging.error(f"ERRO EM /entity_graph/: {e}", exc_info=True)
|
| 962 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 963 |
+
|
| 964 |
+
|
| 965 |
+
# ==============================================================================
|
| 966 |
+
# ENDPOINT ANÁLISE DO GRAFO COM LLM (SÁBIO)
|
| 967 |
+
# ==============================================================================
|
| 968 |
+
@app.post("/analyze_graph/")
|
| 969 |
+
async def analyze_graph_api(job_id: str = Form(...)):
|
| 970 |
+
"""
|
| 971 |
+
Usa o LLM para analisar o Knowledge Graph e extrair insights semânticos.
|
| 972 |
+
"""
|
| 973 |
+
if job_id not in cache:
|
| 974 |
+
raise HTTPException(status_code=404, detail="Job ID não encontrado.")
|
| 975 |
+
|
| 976 |
+
logging.info(f"Analisando grafo com LLM para Job: {job_id}")
|
| 977 |
+
|
| 978 |
+
try:
|
| 979 |
+
cached_data = cache[job_id]
|
| 980 |
+
df = cached_data["df"]
|
| 981 |
+
textos = df["full_text"].tolist()
|
| 982 |
+
|
| 983 |
+
# Extrair entidades e construir grafo
|
| 984 |
+
entities_by_doc = extract_entities(textos)
|
| 985 |
+
entity_network = build_entity_to_entity_graph(entities_by_doc)
|
| 986 |
+
|
| 987 |
+
# Preparar resumo do grafo para o LLM
|
| 988 |
+
nodes = entity_network.get("nodes", [])[:15]
|
| 989 |
+
edges = entity_network.get("edges", [])[:20]
|
| 990 |
+
hubs = entity_network.get("hubs", [])[:5]
|
| 991 |
+
insights = entity_network.get("insights", {})
|
| 992 |
+
|
| 993 |
+
graph_summary = f"""
|
| 994 |
+
ANÁLISE DE KNOWLEDGE GRAPH
|
| 995 |
+
|
| 996 |
+
## Visão Geral
|
| 997 |
+
- {len(nodes)} entidades principais
|
| 998 |
+
- {insights.get('total_connections', 0)} conexões totais
|
| 999 |
+
- {insights.get('hub_count', 0)} hubs identificados
|
| 1000 |
+
|
| 1001 |
+
## Entidades Principais (por importância):
|
| 1002 |
+
{chr(10).join([f"- {n['entity']} ({n['type']}): {n['docs']} docs, centralidade {n.get('centrality', 0)}" for n in nodes])}
|
| 1003 |
+
|
| 1004 |
+
## Hubs Centrais (entidades mais conectadas):
|
| 1005 |
+
{chr(10).join([f"- {h['entity']} ({h['type']}): {h['degree']} conexões" for h in hubs]) if hubs else "Nenhum hub identificado"}
|
| 1006 |
+
|
| 1007 |
+
## Conexões Mais Fortes:
|
| 1008 |
+
{chr(10).join([f"- {e['source_entity']} ↔ {e['target_entity']}: {e['weight']} co-ocorrências" for e in edges[:10]])}
|
| 1009 |
+
"""
|
| 1010 |
+
|
| 1011 |
+
# Prompt para análise
|
| 1012 |
+
prompt = f"""Você é um analista de inteligência especializado em análise de redes e grafos de conhecimento.
|
| 1013 |
+
|
| 1014 |
+
Analise o seguinte Knowledge Graph extraído de documentos e forneça insights acionáveis:
|
| 1015 |
+
|
| 1016 |
+
{graph_summary}
|
| 1017 |
+
|
| 1018 |
+
Por favor forneça:
|
| 1019 |
+
1. **Narrativa Central**: Qual é a história principal que conecta estas entidades?
|
| 1020 |
+
2. **Atores Chave**: Quem são os principais players e qual seu papel?
|
| 1021 |
+
3. **Relações Ocultas**: Que conexões não-óbvias você identifica?
|
| 1022 |
+
4. **Padrões**: Algum padrão interessante nos tipos de entidades ou conexões?
|
| 1023 |
+
5. **Investigação**: O que valeria a pena investigar mais a fundo?
|
| 1024 |
+
|
| 1025 |
+
Responda de forma concisa e acionável, como um briefing de inteligência."""
|
| 1026 |
+
|
| 1027 |
+
# Chamar LLM
|
| 1028 |
+
completion = groq_client.chat.completions.create(
|
| 1029 |
+
model="llama-3.3-70b-versatile",
|
| 1030 |
+
messages=[{"role": "user", "content": prompt}],
|
| 1031 |
+
temperature=0.7,
|
| 1032 |
+
max_tokens=1500
|
| 1033 |
+
)
|
| 1034 |
+
|
| 1035 |
+
analysis = completion.choices[0].message.content
|
| 1036 |
+
|
| 1037 |
+
return {
|
| 1038 |
+
"analysis": analysis,
|
| 1039 |
+
"graph_summary": {
|
| 1040 |
+
"entities": len(nodes),
|
| 1041 |
+
"connections": insights.get('total_connections', 0),
|
| 1042 |
+
"hubs": len(hubs)
|
| 1043 |
+
}
|
| 1044 |
+
}
|
| 1045 |
+
|
| 1046 |
+
except Exception as e:
|
| 1047 |
+
logging.error(f"ERRO EM /analyze_graph/: {e}", exc_info=True)
|
| 1048 |
raise HTTPException(status_code=500, detail=str(e))
|