Spaces:
Configuration error
Configuration error
| # core/fable_engine.py | |
| """ | |
| FableEngine – Optimisation itérative et création automatique de skills. | |
| Utilise BlackBoxAdapter pour interagir avec le LLM. | |
| """ | |
| import asyncio | |
| import logging | |
| import time | |
| from typing import Optional, Dict, Any | |
| from core.skill_schema import Skill, SkillMetadata | |
| from core.vector_memory import VectorMemory | |
| logger = logging.getLogger("vortex.fable_engine") | |
| class FableEngine: | |
| def __init__(self, llm_engine, memory, error_tree, vector_memory: VectorMemory, blackbox=None): | |
| """ | |
| llm_engine : conservé pour compatibilité, mais non utilisé directement pour les appels LLM. | |
| blackbox : instance de BlackBoxAdapter qui expose une méthode async `query(prompt)`. | |
| """ | |
| self.llm = llm_engine | |
| self.memory = memory | |
| self.error_tree = error_tree | |
| self.vm = vector_memory | |
| self.blackbox = blackbox | |
| async def run(self, task: str, max_iter: int = 3, min_score: float = 0.85) -> Dict[str, Any]: | |
| logger.info(f"[Fable] Début optimisation – tâche : {task[:80]} (max {max_iter} itérations)") | |
| best_code = None | |
| best_score = 0.0 | |
| best_skill = None | |
| if not self.blackbox: | |
| raise RuntimeError("FableEngine a besoin d'une instance BlackBoxAdapter (blackbox).") | |
| for i in range(max_iter): | |
| prompt = self._build_prompt(task, best_code, best_score, i) | |
| # Appel via BlackBoxAdapter (même interface que le chat) | |
| response = await self.blackbox.query(prompt) | |
| # Extraire le texte : réponse peut être un objet avec .content ou une chaîne | |
| if hasattr(response, 'content'): | |
| text = response.content | |
| else: | |
| text = str(response) | |
| code = self._extract_code(text) | |
| if not code: | |
| continue | |
| score = await self._evaluate(code, task) | |
| logger.info(f"[Fable] Itération {i+1}/{max_iter} : score {score:.3f}") | |
| if score > best_score: | |
| best_score = score | |
| best_code = code | |
| if score >= min_score: | |
| skill = self._create_skill(task, best_code, best_score) | |
| best_skill = skill | |
| logger.info(f"[Fable] Skill sauvegardé : {skill.metadata.name} (score {best_score:.3f})") | |
| if score >= 0.99: | |
| break | |
| return { | |
| "skill": best_skill.to_dict() if best_skill else None, | |
| "score": best_score, | |
| "iterations": i + 1, | |
| "code": best_code | |
| } | |
| def _build_prompt(self, task: str, current_code: Optional[str], current_score: float, iteration: int) -> str: | |
| if current_code is None: | |
| return f"Écris du code Python pour résoudre cette tâche :\n{task}\nFournis uniquement le code." | |
| return ( | |
| f"Tâche : {task}\n" | |
| f"Code actuel (score {current_score:.3f}) :\n```python\n{current_code}\n```\n" | |
| f"Améliore ce code (itération {iteration+1}). Fournis uniquement le code amélioré." | |
| ) | |
| def _extract_code(self, response: str) -> Optional[str]: | |
| if "```" in response: | |
| parts = response.split("```") | |
| for i, part in enumerate(parts): | |
| if i % 2 == 1: # contenu entre les backticks | |
| if part.startswith("python"): | |
| part = part[6:] | |
| return part.strip() | |
| return response.strip() | |
| async def _evaluate(self, code: str, task: str) -> float: | |
| """Évaluation heuristique simple (à remplacer par un vrai sandbox si besoin).""" | |
| score = 0.5 | |
| if len(code) > 50: score += 0.1 | |
| if len(code) > 100: score += 0.1 | |
| if "def " in code: score += 0.1 | |
| if "return " in code: score += 0.1 | |
| if "import " in code: score += 0.05 | |
| # Bonus mots-clés de la tâche | |
| task_words = set(task.lower().split()) | |
| code_words = set(code.lower().split()) | |
| common = task_words.intersection(code_words) | |
| score += min(0.1, len(common) * 0.02) | |
| return min(score, 1.0) | |
| def _create_skill(self, task: str, code: str, score: float) -> Skill: | |
| name = f"skill_{int(time.time())}" | |
| metadata = SkillMetadata( | |
| name=name, | |
| description=task[:100], | |
| category="auto_fable", | |
| version="1.0", | |
| tags=["fable", "optimized"] | |
| ) | |
| skill = Skill(metadata=metadata, code=code, score=score) | |
| self.vm.add_skill(skill) | |
| return skill |