Spaces:
Configuration error
Configuration error
| # core/error_tree.py | |
| """ | |
| Harbor — Arbre d'erreurs sémantique. | |
| Mémorise les échecs, leurs causes, leçons et correctifs. | |
| """ | |
| import hashlib | |
| import time | |
| import json | |
| import logging | |
| from pathlib import Path | |
| from typing import Dict, List | |
| log = logging.getLogger("vortex.harbor") | |
| class ErrorTree: | |
| def __init__(self, storage_path: str = "data/error_tree.json"): | |
| self.storage_path = Path(storage_path) | |
| self.nodes: Dict[str, Dict] = {} | |
| self.load() | |
| def add_error(self, error_msg: str, context: str) -> str: | |
| node_id = hashlib.sha256(f"{error_msg}{time.time()}".encode()).hexdigest()[:8] | |
| self.nodes[node_id] = { | |
| "error": error_msg, | |
| "context": context[:500], | |
| "lesson": None, | |
| "fix": None, | |
| "timestamp": time.time() | |
| } | |
| self.save() | |
| log.info(f"[Harbor] Erreur enregistrée : {node_id} — {error_msg[:50]}") | |
| return node_id | |
| def add_lesson(self, node_id: str, lesson: str, fix: str): | |
| if node_id in self.nodes: | |
| self.nodes[node_id]["lesson"] = lesson | |
| self.nodes[node_id]["fix"] = fix | |
| self.save() | |
| log.info(f"[Harbor] Leçon ajoutée à {node_id}") | |
| def search_similar(self, query: str) -> List[Dict]: | |
| results = [] | |
| query_words = set(query.lower().split()) | |
| for nid, data in self.nodes.items(): | |
| error_words = set(data["error"].lower().split()) | |
| overlap = len(query_words & error_words) | |
| if overlap > 0: | |
| sim = overlap / max(len(query_words), 1) | |
| results.append({ | |
| "id": nid, | |
| "error": data["error"], | |
| "lesson": data.get("lesson") or "Aucune leçon", | |
| "fix": data.get("fix") or "Aucun correctif", | |
| "similarity": round(sim, 3) | |
| }) | |
| results.sort(key=lambda x: x["similarity"], reverse=True) | |
| return results[:5] | |
| def stats(self) -> Dict: | |
| with_lessons = sum(1 for n in self.nodes.values() if n.get("lesson")) | |
| return { | |
| "total_errors": len(self.nodes), | |
| "with_lessons": with_lessons | |
| } | |
| def save(self): | |
| try: | |
| self.storage_path.parent.mkdir(parents=True, exist_ok=True) | |
| with open(self.storage_path, "w", encoding="utf-8") as f: | |
| json.dump(self.nodes, f, indent=2, default=str, ensure_ascii=False) | |
| except Exception as e: | |
| log.error(f"[Harbor] Échec sauvegarde: {e}") | |
| def load(self): | |
| if self.storage_path.exists(): | |
| try: | |
| with open(self.storage_path, "r", encoding="utf-8") as f: | |
| self.nodes = json.load(f) | |
| log.info(f"[Harbor] Chargé {len(self.nodes)} erreurs") | |
| except Exception as e: | |
| log.error(f"[Harbor] Échec chargement: {e}") | |
| self.nodes = {} | |
| else: | |
| self.nodes = {} | |