Spaces:
Paused
Paused
lojol469-cmd
Initial commit: Kibali AI with RTX 5090 Blackwell support and CUDA 13.0 Nightly
f3a56a5 | import time | |
| from typing import List, Optional | |
| import re | |
| import os | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| def analyze_query_type(prompt: str) -> dict: | |
| """Analyse le type de requête pour adapter la stratégie de réflexion""" | |
| prompt_lower = prompt.lower() | |
| analysis = { | |
| "type": "general", | |
| "needs_web": False, | |
| "needs_memory": False, | |
| "needs_docs": False, | |
| "complexity": "simple", | |
| "temporal": False, | |
| "geographical": False | |
| } | |
| temporal_keywords = ["aujourd'hui", "maintenant", "récent", "actuel", "dernier", "2024", "2025"] | |
| if any(kw in prompt_lower for kw in temporal_keywords): | |
| analysis["temporal"] = True | |
| analysis["needs_web"] = True | |
| geo_keywords = ["gabon", "libreville", "port-gentil", "franceville", "oyem", "où", "localisation"] | |
| if any(kw in prompt_lower for kw in geo_keywords): | |
| analysis["geographical"] = True | |
| doc_keywords = ["selon le document", "d'après le pdf", "dans le fichier", "uploadé"] | |
| if any(kw in prompt_lower for kw in doc_keywords): | |
| analysis["needs_docs"] = True | |
| analysis["type"] = "document_query" | |
| continuation_keywords = ["ils", "elles", "lui", "leur", "donc", "alors", "ensuite", "aussi", "également"] | |
| if any(kw in prompt_lower for kw in continuation_keywords) or len(prompt.split()) < 5: | |
| analysis["needs_memory"] = True | |
| analysis["type"] = "continuation" | |
| if len(prompt.split()) > 15 or (prompt.count("?") > 1): | |
| analysis["complexity"] = "complex" | |
| elif any(kw in prompt_lower for kw in ["pourquoi", "comment", "expliquer"]): | |
| analysis["complexity"] = "medium" | |
| web_keywords = ["actualité", "news", "prix", "cours", "météo", "horaire"] | |
| if any(kw in prompt_lower for kw in web_keywords): | |
| analysis["needs_web"] = True | |
| analysis["type"] = "real_time" | |
| return analysis | |
| def detect_subject_shift(prompt: str, current_subject: str, subject_keywords: List[str]) -> dict: | |
| """Détecte un changement de sujet et évalue la force du changement""" | |
| if not current_subject or not subject_keywords: | |
| return {"shift_detected": False, "shift_strength": 0.0, "new_subject_detected": True, "reason": "Init"} | |
| prompt_lower = prompt.lower() | |
| prompt_words = set(re.findall(r'\b\w{4,}\b', prompt_lower)) | |
| keyword_overlap = len(prompt_words.intersection(set(subject_keywords))) | |
| overlap_ratio = keyword_overlap / max(len(subject_keywords), 1) | |
| shift_markers = ["maintenant", "sinon", "autre chose", "parlons de", "passons à", "nouveau sujet"] | |
| has_shift_marker = any(marker in prompt_lower for marker in shift_markers) | |
| shift_strength = 0.0 | |
| if overlap_ratio < 0.2: shift_strength += 0.5 | |
| if has_shift_marker: shift_strength += 0.3 | |
| return { | |
| "shift_detected": shift_strength > 0.4, | |
| "shift_strength": shift_strength, | |
| "new_subject_detected": shift_strength > 0.6, | |
| "reason": f"Overlap: {overlap_ratio:.1%}" | |
| } | |
| def generate_search_strategy(analysis: dict, subject_keywords: List[str], geo_info: dict) -> dict: | |
| """Génère une stratégie de recherche optimisée""" | |
| strategy = { | |
| "use_rag": analysis["needs_docs"], | |
| "use_memory": analysis["needs_memory"], | |
| "use_web": analysis["needs_web"], | |
| "memory_k": 5, "rag_k": 3, | |
| "web_enhanced": False, "search_query_suffix": "" | |
| } | |
| if analysis["complexity"] == "complex": | |
| strategy.update({"memory_k": 8, "rag_k": 5}) | |
| if analysis["needs_web"]: | |
| strategy["web_enhanced"] = True | |
| suffix = " ".join(subject_keywords[:3]) if subject_keywords else "" | |
| strategy["search_query_suffix"] = f"{suffix} {geo_info.get('city', 'Gabon')}" | |
| return strategy | |
| def execute_reflection_plan( | |
| prompt: str, | |
| geo_info: Optional[dict] = None, | |
| messages: Optional[List] = None, | |
| current_subject: Optional[str] = None, | |
| subject_keywords: Optional[List[str]] = None | |
| ): | |
| """Phase de réflexion structurée compatible FastAPI (sans Streamlit)""" | |
| geo_info = geo_info or {} | |
| subject_keywords = subject_keywords or [] | |
| query_analysis = analyze_query_type(prompt) | |
| subject_shift = detect_subject_shift(prompt, current_subject, subject_keywords) | |
| search_strategy = generate_search_strategy(query_analysis, subject_keywords, geo_info) | |
| # Logs internes (visibles dans Docker) | |
| print(f"🧠 [REFLECTION] Type: {query_analysis['type']} | Web: {search_strategy['use_web']}") | |
| return { | |
| "analysis": query_analysis, | |
| "subject_shift": subject_shift, | |
| "strategy": search_strategy, | |
| "execution_plan_ready": True | |
| } |