Spaces:
Sleeping
Sleeping
File size: 4,677 Bytes
a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 8e3a425 a1506e1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | # 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 {},
"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
|