Spaces:
Running
Running
File size: 4,960 Bytes
2d5ea43 f42a19f 2d5ea43 e24277c 1cf9f87 e24277c 1cf9f87 2e8f466 e24277c f42a19f 6cd93a9 fe2acf8 f42a19f 7917848 e24277c fe2acf8 e24277c b1cb831 7917848 f42a19f e24277c 6cd93a9 e24277c 7917848 2d5ea43 e24277c 29a9d9b 6cd93a9 fe2acf8 6cd93a9 f42a19f b90dfde f42a19f b90dfde 1cf9f87 f42a19f e24277c f42a19f e24277c fe2acf8 1cf9f87 fe2acf8 b90dfde 1cf9f87 f42a19f 7917848 b90dfde 29a9d9b e24277c 7917848 6cd93a9 7917848 e24277c 7917848 2d5ea43 7917848 2d5ea43 e24277c b1cb831 1cf9f87 b1cb831 | 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 | """
MODULE: RDF MANAGER (TRACEABILITY ENABLED)
==========================================
"""
import rdflib
from rdflib import Graph, Literal, Namespace
from rdflib.namespace import RDF, RDFS, XSD
import re
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')))
from src.Analytics.pipeline_builder import PipelineBuilder
VORTEX = Namespace("http://vortex.ai/ontology#")
class RDFStore:
def __init__(self):
self.g = Graph()
self.g.bind("vortex", VORTEX)
self.pipeline = PipelineBuilder()
def ingest_networkx_graph(self, G, ontology_manager):
print("⏳ [RDF] Ingestion (Mode Diagnostic)...")
self.g = Graph()
self.g.bind("vortex", VORTEX)
for node_id, data in G.nodes(data=True):
if data.get('group') == 'Prop': continue
# URI sécurisée
safe_id = re.sub(r'[^a-zA-Z0-9_-]', '_', str(node_id))
subject_uri = VORTEX[safe_id]
group = data.get('group', 'Entity')
self.g.add((subject_uri, RDF.type, VORTEX[group]))
self.g.add((subject_uri, RDFS.label, Literal(str(data.get('label', node_id)))))
for key, value in data.items():
if key in ['group', 'label', 'title', 'x', 'y', 'color', 'shape', 'size', 'hidden']: continue
pred_name = ontology_manager.get_predicate_for_column(group, key)
if not pred_name: continue
target_type = ontology_manager.get_type_for_predicate(pred_name)
# --- APPEL DIAGNOSTIC ---
clean_value = self.pipeline.enforce_contract(
value,
target_type,
row_id=str(node_id),
col_name=str(key)
)
if clean_value is not None:
rdf_dtype = getattr(XSD, target_type.split(':')[1]) if ':' in target_type else None
self.g.add((subject_uri, VORTEX[pred_name], Literal(clean_value, datatype=rdf_dtype)))
# Relations (Version simplifiée pour brièveté, appliquez la même logique si besoin)
for u, v, data in G.edges(data=True):
if G.nodes[u].get('group') == 'Prop': continue
safe_u = re.sub(r'[^a-zA-Z0-9_-]', '_', str(u))
rel_label = data.get('label', 'relatedTo')
pred_clean = re.sub(r'[^a-zA-Z0-9_]', '', str(rel_label))
if G.nodes[v].get('group') != 'Prop':
safe_v = re.sub(r'[^a-zA-Z0-9_-]', '_', str(v))
self.g.add((VORTEX[safe_u], VORTEX[pred_clean], VORTEX[safe_v]))
else:
raw_val = G.nodes[v].get('label', str(v))
target_type = ontology_manager.get_type_for_predicate(pred_clean)
clean_val = self.pipeline.enforce_contract(raw_val, target_type, row_id=str(u), col_name=str(rel_label))
if clean_val:
rdf_dtype = getattr(XSD, target_type.split(':')[1]) if ':' in target_type else None
self.g.add((VORTEX[safe_u], VORTEX[pred_clean], Literal(clean_val, datatype=rdf_dtype)))
print(f"✅ [RDF] Ingestion terminée. {len(self.g)} triplets.")
def execute_sparql(self, query):
try:
full_query = f"""
PREFIX vortex: <http://vortex.ai/ontology#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
{query}
"""
results = self.g.query(full_query)
output = []
for row in results:
line = []
for item in row:
val = str(item).replace("http://vortex.ai/ontology#", "")
line.append(val)
output.append(" | ".join(line))
if not output: return "Aucun résultat trouvé."
return "\n".join(output[:100])
except Exception as e:
return f"❌ Erreur SPARQL : {str(e)}"
def get_full_schema(self):
if len(self.g) == 0: return {"classes": {}, "predicates": [], "triples": 0}
schema = {"classes": {}, "predicates": [], "triples": len(self.g)}
q_classes = "SELECT ?type (COUNT(?s) as ?count) WHERE { ?s a ?type } GROUP BY ?type"
for row in self.g.query(q_classes):
cls_name = str(row[0]).split('#')[-1]
schema["classes"][cls_name] = int(row[1])
q_preds = "SELECT DISTINCT ?p WHERE { ?s ?p ?o FILTER(STRSTARTS(STR(?p), 'http://vortex.ai/ontology#')) }"
for row in self.g.query(q_preds):
pred = str(row[0]).split('#')[-1]
schema["predicates"].append(pred)
return schema |