Spaces:
Running
Running
| """ | |
| MODULE: QUERY PLANNER (OAG) | |
| =========================== | |
| Responsabilité : Analyser la question, vérifier le schéma réel, | |
| et décider de la meilleure stratégie (SPARQL vs FAISS vs Multi-étapes). | |
| """ | |
| import json | |
| import re | |
| class QueryPlanner: | |
| def __init__(self, rdf_store, schema_info): | |
| self.rdf = rdf_store | |
| self.schema = schema_info # Provient de SchemaExtractor.get_real_schema() | |
| def analyze_and_plan(self, user_query): | |
| """ | |
| Détermine si la question est : | |
| 1. Sémantique (Recherche d'un dossier client/prêt spécifique) | |
| 2. Analytique (Comptage, Somme, Croisement global) | |
| 3. Invalide (Donnée absente du schéma) | |
| """ | |
| # 1. ANALYSE DES MOTS CLÉS (Simplifiée) | |
| is_analytical = any(word in user_query.lower() for word in [ | |
| 'combien', 'total', 'somme', 'moyenne', 'liste tous', 'liste les', 'nombre' | |
| ]) | |
| # 2. VÉRIFICATION DU SCHÉMA (Prévention d'hallucination) | |
| # On regarde si les termes de la question match avec nos prédicats réels | |
| available_preds = self.schema.get("predicates", []) | |
| found_preds = [p for p in available_preds if p.lower() in user_query.lower()] | |
| # 3. DÉCISION DE LA STRATÉGIE | |
| # CAS A : Recherche d'un individu ou d'un dossier précis | |
| if not is_analytical and not found_preds: | |
| return { | |
| "strategy": "OG-RAG", | |
| "tool": "search_semantic", | |
| "reason": "La question semble porter sur un individu ou un cas spécifique non défini par un prédicat exact.", | |
| "steps": [f"Rechercher le bloc contextuel pour : {user_query}"] | |
| } | |
| # CAS B : Question de masse ou croisement (Analytique) | |
| if is_analytical: | |
| return { | |
| "strategy": "OAG-SPARQL", | |
| "tool": "execute_sparql", | |
| "reason": "La question nécessite une agrégation ou un filtrage sur l'ensemble de la base.", | |
| "steps": ["Traduire en requête SPARQL optimisée", "Valider les prédicats contre le schéma réel"] | |
| } | |
| # CAS C : Hybride (Par défaut) | |
| return { | |
| "strategy": "HYBRID", | |
| "tool": "execute_sparql", | |
| "reason": "Usage de prédicats identifiés dans le schéma réel.", | |
| "steps": ["Générer SPARQL avec les prédicats validés"] | |
| } | |
| def get_planning_logs(self, plan): | |
| """Génère un affichage propre pour le chat utilisateur""" | |
| log = f"🎯 **Stratégie adoptée** : `{plan['strategy']}`\n" | |
| log += f"🤔 **Raisonnement** : {plan['reason']}\n" | |
| log += "📋 **Plan d'exécution** :\n" | |
| for i, step in enumerate(plan['steps'], 1): | |
| log += f" {i}. {step}\n" | |
| return log |