""" MODULE INFERENCE ENGINE ======================= Deductions ajoutees au graphe RDF apres ingestion. Chaque regle est EXPLICITE : elle s'appuie sur le predicat que la feuille Ontology associe a une colonne precise, jamais sur une devinette par nom de predicat. - montant_net : montant total du du pret (colonne Montant_Total, version courante — les versions Prets_Update sont deja fusionnees dans Prets_Master). Repli sur Montant_Capital si la feuille ne mappe pas Montant_Total. - statut_risque : "HighValue" quand montant_net depasse SEUIL_HIGH_VALUE. - a_emprunteur : relation inverse de possede_pret, si ce predicat existe. """ from rdflib import Literal, Namespace from rdflib.namespace import RDF, XSD VORTEX = Namespace("http://vortex.ai/ontology#") SEUIL_HIGH_VALUE = 100000 def _predicat_pour_colonne(regles, colonne): """(classe, predicat) de la regle data_property qui lit `colonne`, sinon None.""" for r in regles or []: if str(r.get("ObjectColOrConcept", "")).strip() == colonne and str(r.get("ObjectType", "")).strip().lower() == "data_property": return str(r.get("SubjectClass", "")).strip(), str(r.get("Predicate", "")).strip() return None class InferenceEngine: def __init__(self, rdf_store, regles=None): self.rdf_store = rdf_store self.regles = regles or [] self.journal = [] # [(regle, triplets ajoutes | message)] def run_inference(self): g = self.rdf_store.g source = _predicat_pour_colonne(self.regles, "Montant_Total") or _predicat_pour_colonne(self.regles, "Montant_Capital") if source: classe, predicat = source ajouts = 0 for sujet in g.subjects(RDF.type, VORTEX[classe]): for valeur in g.objects(sujet, VORTEX[predicat]): try: montant = float(valeur) except (TypeError, ValueError): continue g.set((sujet, VORTEX.montant_net, Literal(montant, datatype=XSD.decimal))) ajouts += 1 if montant > SEUIL_HIGH_VALUE: g.set((sujet, VORTEX.statut_risque, Literal("HighValue"))) break self.journal.append((f"montant_net = {classe}.{predicat}", ajouts)) else: self.journal.append(("montant_net", "ignorée : aucune règle Ontology ne lit Montant_Total ni Montant_Capital")) ajouts = 0 for client, pret in list(g.subject_objects(VORTEX.possede_pret)): g.add((pret, VORTEX.a_emprunteur, client)) ajouts += 1 self.journal.append(("a_emprunteur = inverse de possede_pret", ajouts)) return self.journal