Spaces:
Running
Running
Download src/core/schema_extractor.py from klydekushy/Vortex-Flux: direct link, hf CLI and curl.
- Browser
- Download file 3.63 kB
-
https://huggingface.co/spaces/klydekushy/Vortex-Flux/resolve/main/src/core/schema_extractor.py
- Command line
-
hf download hf://spaces/klydekushy/Vortex-Flux/src/core/schema_extractor.py
-
curl -L -o schema_extractor.py https://huggingface.co/spaces/klydekushy/Vortex-Flux/resolve/main/src/core/schema_extractor.py
3.63 kB
| """ | |
| MODULE: SCHEMA EXTRACTOR (TYPE AWARE) | |
| ===================================== | |
| Responsabilité : Extraire le schéma réel DU GRAPHE pour informer l'Agent des types de données disponibles. | |
| """ | |
| 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, ontology_rules=None): | |
| """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"[LOT] {cls} ({count} items) : {props}") | |
| if ontology_rules: | |
| lines.append("\n--- DICTIONNAIRE MÉTIER DE LA FEUILLE ONTOLOGY ---") | |
| for rule in ontology_rules: | |
| subject = str(rule.get("SubjectClass", "")).strip() | |
| predicate = str(rule.get("Predicate", "")).strip() | |
| if not subject or not predicate: | |
| continue | |
| description = str(rule.get("Description_Metier", "")).strip() | |
| description = "" if description.lower() in {"nan", "none"} else description | |
| details = [ | |
| f"feuille={str(rule.get('Sheet', '')).strip()}", | |
| f"colonne_sujet={str(rule.get('SubjectCol', '')).strip()}", | |
| f"colonne_objet={str(rule.get('ObjectColOrConcept', '')).strip()}", | |
| f"type={str(rule.get('ObjectType', '')).strip()}", | |
| f"range={str(rule.get('Range', '')).strip()}", | |
| f"cardinalité={str(rule.get('Cardinality', '')).strip()}", | |
| ] | |
| if description: | |
| details.append(f"sens_métier={description}") | |
| lines.append(f"- {subject}.{predicate} ({'; '.join(details)})") | |
| return "\n".join(lines) |