File size: 2,419 Bytes
384bf14
6db3a98
 
 
384bf14
6db3a98
384bf14
 
 
 
 
 
6db3a98
384bf14
 
6db3a98
 
384bf14
 
6db3a98
 
384bf14
 
 
 
 
6db3a98
384bf14
6db3a98
384bf14
6db3a98
384bf14
 
6db3a98
384bf14
 
 
 
 
6db3a98
 
 
 
 
 
 
 
 
 
384bf14
 
 
 
 
6db3a98
384bf14
6db3a98
384bf14
 
6db3a98
 
384bf14
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
"""
MODULE: SCHEMA EXTRACTOR (TYPE AWARE)
=====================================
Responsabilité : Extraire le schéma réel DU GRAPHE pour informer l'Agent des types de données disponibles.
"""
from rdflib import Graph

class SchemaExtractor:
    def __init__(self, rdf_store):
        self.rdf_store = rdf_store

    def get_real_schema(self):
        """Récupère les classes, les propriétés et leurs types de données observés"""
        g = self.rdf_store.g
        schema = {
            "classes": {}, 
            "predicates": [], 
            "properties_by_class": {}
        }
        
        # 1. Compter les entités par classe
        q_classes = "SELECT ?type (COUNT(?s) as ?count) WHERE { ?s a ?type } GROUP BY ?type"
        for row in g.query(q_classes):
            cls_name = str(row[0]).split('#')[-1]
            schema["classes"][cls_name] = int(row[1])

        # 2. Extraire les propriétés et deviner leur type
        for cls in schema["classes"]:
            # Cette requête regarde la donnée réelle (?o) et demande son type (datatype(?o))
            q_props = f"""
            SELECT DISTINCT ?p ?datatype WHERE {{
                ?s a vortex:{cls} .
                ?s ?p ?o .
                BIND(datatype(?o) AS ?datatype)
                FILTER(STRSTARTS(STR(?p), "http://vortex.ai/ontology#"))
            }}
            """
            props = []
            for row in g.query(q_props):
                pred = str(row[0]).split('#')[-1]
                # Si datatype est vide, c'est probablement un String ou une Relation
                dtype = str(row[1]).split('#')[-1] if row[1] else "string/obj"
                
                # On ajoute le prédicat à la liste globale
                if pred not in schema["predicates"]:
                    schema["predicates"].append(pred)
                
                props.append(f"{pred} ({dtype})")
            
            schema["properties_by_class"][cls] = props

        return schema

    def generate_prompt_schema(self):
        """Génère le texte de contexte pour le LLM"""
        schema = self.get_real_schema()
        lines = ["--- RÉALITÉ DU GRAPH RDF (TYPÉE) ---"]
        for cls, count in schema["classes"].items():
            props = ", ".join(schema["properties_by_class"].get(cls, []))
            lines.append(f"📦 {cls} ({count} items) : {props}")
        
        return "\n".join(lines)