Danielfonseca1212 commited on
Commit
2744df3
·
verified ·
1 Parent(s): 088f207

Update graph_agent.py

Browse files
Files changed (1) hide show
  1. graph_agent.py +152 -194
graph_agent.py CHANGED
@@ -1,194 +1,152 @@
1
- # graph_knowledge.py — Popula Neo4j com base de conhecimento dos projetos
2
- CYPHER_SCHEMA = """
3
- // ── NÓS ──────────────────────────────────────────────────────
4
-
5
- // Projetos
6
- MERGE (p1:Projeto {nome: 'Sistema Imune Digital'})
7
- SET p1.descricao = 'Sistema de detecção de fraude bancária com Deep RL. Agente DQN Dueling com 3 agentes especialistas orquestrados.',
8
- p1.paradigma = 'Deep Reinforcement Learning',
9
- p1.dado = 'Sintético',
10
- p1.url = 'https://huggingface.co/spaces/Danielfonseca1212/sistema-imune',
11
- p1.emoji = '🛡️',
12
- p1.ano = 2024;
13
-
14
- MERGE (p2:Projeto {nome: 'HetGNN Fraud'})
15
- SET p2.descricao = 'Heterogeneous Graph Neural Network com 5 tipos de nó e 7 tipos de aresta. HGTConv aprende atenção separada por tipo de relação.',
16
- p2.paradigma = 'Supervised GNN',
17
- p2.dado = 'Sintético',
18
- p2.url = 'https://huggingface.co/spaces/Danielfonseca1212/hetgnn-fraud',
19
- p2.emoji = '🕸️',
20
- p2.ano = 2024;
21
-
22
- MERGE (p3:Projeto {nome: 'TGN Fraud Detection'})
23
- SET p3.descricao = 'Temporal Graph Network com memória evolutiva por nó via GRU. Detecta fraude em stream de e-commerce em tempo real.',
24
- p3.paradigma = 'Temporal GNN',
25
- p3.dado = 'Sintético',
26
- p3.url = 'https://huggingface.co/spaces/Danielfonseca1212/tgn-fraud',
27
- p3.emoji = '⏱️',
28
- p3.ano = 2024;
29
-
30
- MERGE (p4:Projeto {nome: 'DOMINANT'})
31
- SET p4.descricao = 'Deep Anomaly Detection on Attributed Networks (IJCAI 2019). Detecta anomalias em grafo sem nenhum label no treino.',
32
- p4.paradigma = 'Unsupervised GNN',
33
- p4.dado = 'Sintético',
34
- p4.url = 'https://huggingface.co/spaces/Danielfonseca1212/dominant-anomaly',
35
- p4.emoji = '🔬',
36
- p4.ano = 2024;
37
-
38
- MERGE (p5:Projeto {nome: 'GraphSAGE Elliptic'})
39
- SET p5.descricao = 'GraphSAGE inductive vs GCN vs MLP no dataset Elliptic Bitcoin real (MIT). 203k transações reais com split temporal.',
40
- p5.paradigma = 'Inductive GNN',
41
- p5.dado = 'Real',
42
- p5.url = 'https://huggingface.co/spaces/Danielfonseca1212/elliptic-graphsage',
43
- p5.emoji = '₿',
44
- p5.ano = 2024;
45
-
46
- // Tecnologias
47
- MERGE (t1:Tecnologia {nome: 'PyTorch'});
48
- MERGE (t2:Tecnologia {nome: 'PyTorch Geometric'});
49
- MERGE (t3:Tecnologia {nome: 'Neo4j Aura'});
50
- MERGE (t4:Tecnologia {nome: 'Streamlit'});
51
- MERGE (t5:Tecnologia {nome: 'DQN Dueling'});
52
- MERGE (t6:Tecnologia {nome: 'HGTConv'});
53
- MERGE (t7:Tecnologia {nome: 'SAGEConv'});
54
- MERGE (t8:Tecnologia {nome: 'GCNConv'});
55
- MERGE (t9:Tecnologia {nome: 'GRU Memory'});
56
- MERGE (t10:Tecnologia {nome: 'Time2Vec'});
57
- MERGE (t11:Tecnologia {nome: 'GCN Encoder'});
58
- MERGE (t12:Tecnologia {nome: 'Autoencoder'});
59
- MERGE (t13:Tecnologia {nome: 'GraphSAGE'});
60
- MERGE (t14:Tecnologia {nome: 'Hugging Face Spaces'});
61
- MERGE (t15:Tecnologia {nome: 'OpenAI GPT'});
62
- MERGE (t16:Tecnologia {nome: 'Cypher'});
63
-
64
- // Conceitos
65
- MERGE (c1:Conceito {nome: 'Detecção de Fraude'})
66
- SET c1.descricao = 'Identificação automática de transações fraudulentas em sistemas financeiros.';
67
- MERGE (c2:Conceito {nome: 'Graph Neural Network'})
68
- SET c2.descricao = 'Redes neurais que operam diretamente em dados estruturados como grafos.';
69
- MERGE (c3:Conceito {nome: 'Aprendizado por Reforço'})
70
- SET c3.descricao = 'Paradigma onde agente aprende por tentativa e erro maximizando recompensa.';
71
- MERGE (c4:Conceito {nome: 'Grafo Heterogêneo'})
72
- SET c4.descricao = 'Grafo com múltiplos tipos de nó e aresta, cada um com semântica diferente.';
73
- MERGE (c5:Conceito {nome: 'Grafo Temporal'})
74
- SET c5.descricao = 'Grafo que evolui no tempo, com eventos ordenados temporalmente.';
75
- MERGE (c6:Conceito {nome: 'Anomaly Detection'})
76
- SET c6.descricao = 'Detecção de padrões incomuns sem necessidade de labels supervisionados.';
77
- MERGE (c7:Conceito {nome: 'Inductive Learning'})
78
- SET c7.descricao = 'Modelo que generaliza para nós/grafos novos sem retreinar.';
79
- MERGE (c8:Conceito {nome: 'Message Passing'})
80
- SET c8.descricao = 'Mecanismo onde nós agregam informação dos vizinhos iterativamente.';
81
- MERGE (c9:Conceito {nome: 'Attention Mechanism'})
82
- SET c9.descricao = 'Pesos aprendidos que determinam a importância de cada vizinho.';
83
- MERGE (c10:Conceito {nome: 'Memory Module'})
84
- SET c10.descricao = 'Vetor de estado por nó que acumula histórico de interações.';
85
- MERGE (c11:Conceito {nome: 'Node Classification'})
86
- SET c11.descricao = 'Tarefa de prever a classe de cada nó no grafo.';
87
- MERGE (c12:Conceito {nome: 'Unsupervised Learning'})
88
- SET c12.descricao = 'Aprendizado sem labels — modelo descobre estrutura nos dados.';
89
-
90
- // Papers
91
- MERGE (pp1:Paper {titulo: 'Human-level control through deep reinforcement learning'})
92
- SET pp1.autores = 'Mnih et al.', pp1.venue = 'Nature 2015', pp1.modelo = 'DQN';
93
- MERGE (pp2:Paper {titulo: 'Heterogeneous Graph Transformer'})
94
- SET pp2.autores = 'Hu et al.', pp2.venue = 'WWW 2020', pp2.modelo = 'HGT';
95
- MERGE (pp3:Paper {titulo: 'Temporal Graph Networks'})
96
- SET pp3.autores = 'Rossi et al.', pp3.venue = 'ICML 2020', pp3.modelo = 'TGN';
97
- MERGE (pp4:Paper {titulo: 'Deep Anomaly Detection on Attributed Networks'})
98
- SET pp4.autores = 'Ding et al.', pp4.venue = 'IJCAI 2019', pp4.modelo = 'DOMINANT';
99
- MERGE (pp5:Paper {titulo: 'Inductive Representation Learning on Large Graphs'})
100
- SET pp5.autores = 'Hamilton et al.', pp5.venue = 'NeurIPS 2017', pp5.modelo = 'GraphSAGE';
101
-
102
- // Métricas (aproximadas baseadas em dados sintéticos)
103
- MERGE (m1:Metrica {projeto: 'HetGNN Fraud', tipo: 'AUC'})
104
- SET m1.valor = 0.89, m1.dataset = 'Sintético';
105
- MERGE (m2:Metrica {projeto: 'TGN Fraud Detection', tipo: 'AUC'})
106
- SET m2.valor = 0.91, m2.dataset = 'Sintético';
107
- MERGE (m3:Metrica {projeto: 'DOMINANT', tipo: 'AUC'})
108
- SET m3.valor = 0.84, m3.dataset = 'Sintético';
109
- MERGE (m4:Metrica {projeto: 'GraphSAGE Elliptic', tipo: 'AUC'})
110
- SET m4.valor = 0.97, m4.dataset = 'Elliptic Bitcoin Real';
111
-
112
- // ── ARESTAS ───────────────────────────────────────────────────
113
-
114
- // Projetos USAM tecnologias
115
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (t:Tecnologia {nome:'PyTorch'}) MERGE (p)-[:USA]->(t);
116
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (t:Tecnologia {nome:'DQN Dueling'}) MERGE (p)-[:USA]->(t);
117
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (t:Tecnologia {nome:'Neo4j Aura'}) MERGE (p)-[:USA]->(t);
118
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (t:Tecnologia {nome:'Streamlit'}) MERGE (p)-[:USA]->(t);
119
-
120
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (t:Tecnologia {nome:'PyTorch Geometric'}) MERGE (p)-[:USA]->(t);
121
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (t:Tecnologia {nome:'HGTConv'}) MERGE (p)-[:USA]->(t);
122
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (t:Tecnologia {nome:'Neo4j Aura'}) MERGE (p)-[:USA]->(t);
123
-
124
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (t:Tecnologia {nome:'GRU Memory'}) MERGE (p)-[:USA]->(t);
125
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (t:Tecnologia {nome:'Time2Vec'}) MERGE (p)-[:USA]->(t);
126
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (t:Tecnologia {nome:'PyTorch'}) MERGE (p)-[:USA]->(t);
127
-
128
- MATCH (p:Projeto {nome:'DOMINANT'}), (t:Tecnologia {nome:'GCN Encoder'}) MERGE (p)-[:USA]->(t);
129
- MATCH (p:Projeto {nome:'DOMINANT'}), (t:Tecnologia {nome:'Autoencoder'}) MERGE (p)-[:USA]->(t);
130
- MATCH (p:Projeto {nome:'DOMINANT'}), (t:Tecnologia {nome:'PyTorch Geometric'}) MERGE (p)-[:USA]->(t);
131
-
132
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (t:Tecnologia {nome:'GraphSAGE'}) MERGE (p)-[:USA]->(t);
133
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (t:Tecnologia {nome:'SAGEConv'}) MERGE (p)-[:USA]->(t);
134
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (t:Tecnologia {nome:'GCNConv'}) MERGE (p)-[:USA]->(t);
135
-
136
- // Projetos IMPLEMENTAM conceitos
137
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (c:Conceito {nome:'Aprendizado por Reforço'}) MERGE (p)-[:IMPLEMENTA]->(c);
138
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (c:Conceito {nome:'Detecção de Fraude'}) MERGE (p)-[:IMPLEMENTA]->(c);
139
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (c:Conceito {nome:'Grafo Heterogêneo'}) MERGE (p)-[:IMPLEMENTA]->(c);
140
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (c:Conceito {nome:'Attention Mechanism'}) MERGE (p)-[:IMPLEMENTA]->(c);
141
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (c:Conceito {nome:'Node Classification'}) MERGE (p)-[:IMPLEMENTA]->(c);
142
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (c:Conceito {nome:'Grafo Temporal'}) MERGE (p)-[:IMPLEMENTA]->(c);
143
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (c:Conceito {nome:'Memory Module'}) MERGE (p)-[:IMPLEMENTA]->(c);
144
- MATCH (p:Projeto {nome:'DOMINANT'}), (c:Conceito {nome:'Anomaly Detection'}) MERGE (p)-[:IMPLEMENTA]->(c);
145
- MATCH (p:Projeto {nome:'DOMINANT'}), (c:Conceito {nome:'Unsupervised Learning'}) MERGE (p)-[:IMPLEMENTA]->(c);
146
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (c:Conceito {nome:'Inductive Learning'}) MERGE (p)-[:IMPLEMENTA]->(c);
147
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (c:Conceito {nome:'Message Passing'}) MERGE (p)-[:IMPLEMENTA]->(c);
148
-
149
- // Projetos REFERENCIAM papers
150
- MATCH (p:Projeto {nome:'Sistema Imune Digital'}), (pp:Paper {modelo:'DQN'}) MERGE (p)-[:REFERENCIA]->(pp);
151
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (pp:Paper {modelo:'HGT'}) MERGE (p)-[:REFERENCIA]->(pp);
152
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (pp:Paper {modelo:'TGN'}) MERGE (p)-[:REFERENCIA]->(pp);
153
- MATCH (p:Projeto {nome:'DOMINANT'}), (pp:Paper {modelo:'DOMINANT'}) MERGE (p)-[:REFERENCIA]->(pp);
154
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (pp:Paper {modelo:'GraphSAGE'}) MERGE (p)-[:REFERENCIA]->(pp);
155
-
156
- // Projetos TEM métricas
157
- MATCH (p:Projeto {nome:'HetGNN Fraud'}), (m:Metrica {projeto:'HetGNN Fraud'}) MERGE (p)-[:TEM_METRICA]->(m);
158
- MATCH (p:Projeto {nome:'TGN Fraud Detection'}), (m:Metrica {projeto:'TGN Fraud Detection'}) MERGE (p)-[:TEM_METRICA]->(m);
159
- MATCH (p:Projeto {nome:'DOMINANT'}), (m:Metrica {projeto:'DOMINANT'}) MERGE (p)-[:TEM_METRICA]->(m);
160
- MATCH (p:Projeto {nome:'GraphSAGE Elliptic'}), (m:Metrica {projeto:'GraphSAGE Elliptic'}) MERGE (p)-[:TEM_METRICA]->(m);
161
-
162
- // DIFERENTE_DE (para comparação)
163
- MATCH (p1:Projeto {nome:'DOMINANT'}), (p2:Projeto {nome:'HetGNN Fraud'})
164
- MERGE (p1)-[:DIFERENTE_DE {motivo: 'DOMINANT não usa labels, HetGNN usa supervisão'}]->(p2);
165
- MATCH (p1:Projeto {nome:'GraphSAGE Elliptic'}), (p2:Projeto {nome:'HetGNN Fraud'})
166
- MERGE (p1)-[:DIFERENTE_DE {motivo: 'GraphSAGE é inductive, HetGNN é transductive'}]->(p2);
167
- """
168
-
169
- def popular_neo4j(driver, database):
170
- """Executa o schema Cypher para popular a base de conhecimento."""
171
- statements = [s.strip() for s in CYPHER_SCHEMA.split(';') if s.strip()]
172
- erros = []
173
- with driver.session(database=database) as session:
174
- for stmt in statements:
175
- try:
176
- session.run(stmt)
177
- except Exception as e:
178
- erros.append(str(e))
179
- return len(statements), erros
180
-
181
- def verificar_schema(driver, database):
182
- """Retorna contagem de nós e arestas por tipo."""
183
- with driver.session(database=database) as session:
184
- nos = session.run("""
185
- MATCH (n)
186
- RETURN labels(n)[0] AS tipo, count(n) AS total
187
- ORDER BY total DESC
188
- """).data()
189
- arestas = session.run("""
190
- MATCH ()-[r]->()
191
- RETURN type(r) AS tipo, count(r) AS total
192
- ORDER BY total DESC
193
- """).data()
194
- return nos, arestas
 
1
+ # graph_agent.py — GraphRAG Agent: GPT-4o-mini + Neo4j Cypher
2
+ from openai import OpenAI
3
+ import re
4
+
5
+ SYSTEM_PROMPT = """Você é um agente especialista em Graph Neural Networks para detecção de fraude.
6
+ Você tem acesso a uma base de conhecimento em grafo Neo4j com 5 projetos de GNN.
7
+
8
+ PROJETOS DISPONÍVEIS:
9
+ 1. Sistema Imune Digital — Deep RL (DQN Dueling), 3 agentes especialistas
10
+ 2. HetGNN Fraud — Grafo heterogêneo, HGTConv, 5 tipos de nó
11
+ 3. TGN Fraud Detection — Temporal GNN, memória GRU, stream e-commerce
12
+ 4. DOMINANT — Anomaly detection sem labels (IJCAI 2019)
13
+ 5. GraphSAGE Elliptic — Dataset real Bitcoin, inductive learning
14
+
15
+ SCHEMA DO GRAFO:
16
+ Nós: Projeto, Tecnologia, Conceito, Paper, Metrica
17
+ Arestas:
18
+ (Projeto)-[:USA]->(Tecnologia)
19
+ (Projeto)-[:IMPLEMENTA]->(Conceito)
20
+ (Projeto)-[:REFERENCIA]->(Paper)
21
+ (Projeto)-[:TEM_METRICA]->(Metrica)
22
+ (Projeto)-[:DIFERENTE_DE]->(Projeto)
23
+
24
+ PROPRIEDADES:
25
+ Projeto: nome, descricao, paradigma, dado, url, emoji, ano
26
+ Tecnologia: nome
27
+ Conceito: nome, descricao
28
+ Paper: titulo, autores, venue, modelo
29
+ Metrica: projeto, tipo, valor, dataset
30
+
31
+ Sua tarefa:
32
+ 1. Gerar uma query Cypher para buscar informação relevante no grafo
33
+ 2. A query deve ser eficiente e específica à pergunta
34
+ 3. Retornar APENAS o Cypher, sem explicação, dentro de ```cypher ... ```
35
+
36
+ Exemplos:
37
+ Pergunta: "Quais projetos usam PyTorch Geometric?"
38
+ ```cypher
39
+ MATCH (p:Projeto)-[:USA]->(t:Tecnologia {nome: 'PyTorch Geometric'})
40
+ RETURN p.nome, p.descricao, p.url
41
+ ```
42
+
43
+ Pergunta: "Qual projeto tem maior AUC?"
44
+ ```cypher
45
+ MATCH (p:Projeto)-[:TEM_METRICA]->(m:Metrica {tipo: 'AUC'})
46
+ RETURN p.nome, m.valor, m.dataset
47
+ ORDER BY m.valor DESC
48
+ ```
49
+
50
+ Pergunta: "Me explique o conceito de Inductive Learning"
51
+ ```cypher
52
+ MATCH (c:Conceito {nome: 'Inductive Learning'})<-[:IMPLEMENTA]-(p:Projeto)
53
+ RETURN c.nome, c.descricao, collect(p.nome) AS projetos
54
+ ```"""
55
+
56
+ ANSWER_PROMPT = """Você é Daniel Fonseca, ML Engineer especialista em Graph Neural Networks para detecção de fraude.
57
+ Responda de forma técnica, clara e entusiasmada sobre seus projetos.
58
+
59
+ Contexto do grafo Neo4j:
60
+ {context}
61
+
62
+ Pergunta do usuário: {question}
63
+
64
+ Instruções:
65
+ - Responda em português
66
+ - Seja específico e técnico
67
+ - Cite os projetos relevantes com seus emojis
68
+ - Se tiver URL de projeto, mencione que pode ser acessado no Hugging Face
69
+ - Máximo 4 parágrafos
70
+ - Finalize com uma frase que convide o usuário a explorar mais"""
71
+
72
+
73
+ class GraphRAGAgent:
74
+ def __init__(self, openai_api_key: str, neo4j_driver, neo4j_database: str):
75
+ self.client = OpenAI(api_key=openai_api_key)
76
+ self.driver = neo4j_driver
77
+ self.database = neo4j_database
78
+ self.model = "gpt-4o-mini"
79
+
80
+ def gerar_cypher(self, pergunta: str) -> str:
81
+ """GPT gera Cypher a partir da pergunta em linguagem natural."""
82
+ resp = self.client.chat.completions.create(
83
+ model=self.model,
84
+ messages=[
85
+ {"role": "system", "content": SYSTEM_PROMPT},
86
+ {"role": "user", "content": pergunta}
87
+ ],
88
+ temperature=0.1,
89
+ max_tokens=300,
90
+ )
91
+ texto = resp.choices[0].message.content
92
+ # Extrai o Cypher do bloco de código
93
+ match = re.search(r'```cypher\s*(.*?)\s*```', texto, re.DOTALL)
94
+ if match:
95
+ return match.group(1).strip()
96
+ # Fallback: tenta extrair qualquer bloco de código
97
+ match = re.search(r'```\s*(.*?)\s*```', texto, re.DOTALL)
98
+ if match:
99
+ return match.group(1).strip()
100
+ return texto.strip()
101
+
102
+ def executar_cypher(self, cypher: str) -> list:
103
+ """Executa Cypher no Neo4j e retorna resultados."""
104
+ try:
105
+ with self.driver.session(database=self.database) as session:
106
+ result = session.run(cypher)
107
+ return [dict(record) for record in result]
108
+ except Exception as e:
109
+ return [{"erro": str(e)}]
110
+
111
+ def formatar_contexto(self, resultados: list) -> str:
112
+ """Formata resultados do Neo4j em texto para o LLM."""
113
+ if not resultados:
114
+ return "Nenhum resultado encontrado no grafo."
115
+ if len(resultados) == 1 and "erro" in resultados[0]:
116
+ return f"Erro na query: {resultados[0]['erro']}"
117
+ linhas = []
118
+ for r in resultados[:10]: # max 10 resultados
119
+ linha = " | ".join(f"{k}: {v}" for k, v in r.items() if v is not None)
120
+ linhas.append(linha)
121
+ return "\n".join(linhas)
122
+
123
+ def gerar_resposta(self, pergunta: str, contexto: str) -> str:
124
+ """GPT gera resposta final com base no contexto do grafo."""
125
+ prompt = ANSWER_PROMPT.format(context=contexto, question=pergunta)
126
+ resp = self.client.chat.completions.create(
127
+ model=self.model,
128
+ messages=[{"role": "user", "content": prompt}],
129
+ temperature=0.7,
130
+ max_tokens=600,
131
+ )
132
+ return resp.choices[0].message.content
133
+
134
+ def responder(self, pergunta: str) -> dict:
135
+ """
136
+ Pipeline completo:
137
+ 1. Gera Cypher
138
+ 2. Executa no Neo4j
139
+ 3. Formata contexto
140
+ 4. Gera resposta
141
+ """
142
+ cypher = self.gerar_cypher(pergunta)
143
+ resultados = self.executar_cypher(cypher)
144
+ contexto = self.formatar_contexto(resultados)
145
+ resposta = self.gerar_resposta(pergunta, contexto)
146
+
147
+ return {
148
+ "cypher": cypher,
149
+ "resultados": resultados,
150
+ "contexto": contexto,
151
+ "resposta": resposta,
152
+ }