File size: 3,273 Bytes
974902e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# core/fable_engine.py
"""
Moteur Fable — itérations successives avec auto-amélioration.
Production → Capture → Observation → Correction → Livraison
"""
import time
import logging
from typing import Dict, Any

log = logging.getLogger("vortex.fable")


class FableEngine:
    def __init__(self, llm_engine, memory, error_tree):
        self.llm = llm_engine
        self.memory = memory
        self.error_tree = error_tree

    async def run(self, task: str, max_iterations: int = 3) -> Dict[str, Any]:
        log.info(f"[Fable] Démarrage : {task[:80]}... (max {max_iterations} iter)")
        start_time = time.perf_counter()
        best_result = None
        best_score = 0.0
        history = []

        current_task = task
        for i in range(max_iterations):
            log.info(f"[Fable] Itération {i + 1}/{max_iterations}")
            try:
                resp = await self.llm.call(
                    agent="fable",
                    system="Tu es un expert en résolution de problèmes. Améliore ta réponse à chaque itération.",
                    user=f"Tâche : {current_task}\nPropose une solution détaillée.",
                    max_tokens=500,
                    temperature=0.4
                )
                solution = resp.content if hasattr(resp, "content") else str(resp)
            except Exception as e:
                log.error(f"[Fable] Erreur itération {i + 1}: {e}")
                solution = f"[Erreur] {e}"
                try:
                    self.error_tree.add_error(str(e), f"Fable iter={i+1} task={task[:100]}")
                except Exception:
                    pass

            score = min(0.8, len(solution) / 1000) * 0.8 + 0.2
            if "code" in solution.lower() or "api" in solution.lower():
                score = min(0.95, score + 0.1)

            if score > best_score:
                best_score = score
                best_result = solution

            history.append({"iteration": i + 1, "solution": solution[:300], "score": round(score, 3)})

            if score >= 0.85:
                log.info(f"[Fable] Seuil atteint à l'itération {i+1} ({score:.3f})")
                break

            current_task = (
                f"{current_task}\nVoici une solution précédente :\n{solution[:500]}\n"
                f"Améliore-la en corrigeant les éventuelles faiblesses."
            )

        elapsed = time.perf_counter() - start_time
        log.info(f"[Fable] Terminé en {elapsed:.2f}s, meilleur score {best_score:.3f}")

        try:
            from core.memory import MemoryTier
            self.memory.ingest(
                f"Fable: {task[:100]}{best_score:.2f} ({len(history)} iter)",
                MemoryTier.EPISODIC, "fable",
                importance=best_score, confidence=best_score
            )
        except Exception as e:
            log.warning(f"[Fable] Mémorisation échouée: {e}")

        return {
            "task": task,
            "method": "Fable (itératif)",
            "iterations": len(history),
            "elapsed_s": round(elapsed, 2),
            "best_score": round(best_score, 3),
            "best_result": best_result[:1500] if best_result else "Aucun résultat",
            "history": history
        }