|
| 1 | +""" |
| 2 | +Prometheus Training on Modal. |
| 3 | +
|
| 4 | +Runs the Co-Evolution Loop in the cloud to train the agent. |
| 5 | +Persists the learned memory to a Modal Volume. |
| 6 | +""" |
| 7 | + |
| 8 | +import modal |
| 9 | +import os |
| 10 | +import sys |
| 11 | +import asyncio |
| 12 | +from datetime import datetime |
| 13 | + |
| 14 | +# Define the Modal App |
| 15 | +app = modal.App("prometheus-training") |
| 16 | + |
| 17 | +# Define persistence volume for MIRIX memory |
| 18 | +volume = modal.Volume.from_name("prometheus-memory", create_if_missing=True) |
| 19 | + |
| 20 | +# Load .env if present |
| 21 | +from dotenv import load_dotenv |
| 22 | +load_dotenv("/media/juan/DATA/projects/GEMINI-CLI-2/qwen-dev-cli/.env") |
| 23 | + |
| 24 | +# Define the image |
| 25 | +image = ( |
| 26 | + modal.Image.debian_slim() |
| 27 | + .pip_install("google-generativeai", "rich", "tqdm", "python-dotenv", "httpx") |
| 28 | + .env({"GEMINI_API_KEY": os.environ.get("GEMINI_API_KEY", "")}) |
| 29 | + .add_local_dir( |
| 30 | + "/media/juan/DATA/projects/GEMINI-CLI-2/qwen-dev-cli", |
| 31 | + remote_path="/root/qwen-dev-cli", |
| 32 | + ignore=["**/.git", "**/__pycache__", "**/.venv", "**/.env", "**/venv"], |
| 33 | + ) |
| 34 | +) |
| 35 | + |
| 36 | +@app.function( |
| 37 | + image=image, |
| 38 | + volumes={"/data": volume}, |
| 39 | + timeout=3600, # 1 hour max training time |
| 40 | +) |
| 41 | +async def train_prometheus(num_iterations: int = 10): |
| 42 | + """ |
| 43 | + Run the Co-Evolution Loop remotely. |
| 44 | + """ |
| 45 | + print(f"🚀 Starting Prometheus Training ({num_iterations} iterations)...") |
| 46 | + |
| 47 | + # Add project root to path so imports work |
| 48 | + sys.path.append("/root/qwen-dev-cli") |
| 49 | + |
| 50 | + try: |
| 51 | + from prometheus.core.evolution import CoEvolutionLoop |
| 52 | + from prometheus.core.llm_client import GeminiClient |
| 53 | + from prometheus.memory.memory_system import MemorySystem |
| 54 | + from prometheus.core.reflection import ReflectionEngine |
| 55 | + from prometheus.tools.tool_factory import ToolFactory |
| 56 | + from prometheus.sandbox.executor import SandboxExecutor |
| 57 | + except ImportError as e: |
| 58 | + print(f"❌ Import Error: {e}") |
| 59 | + # Debug: list files |
| 60 | + import subprocess |
| 61 | + subprocess.run(["find", "/root/qwen-dev-cli", "-maxdepth", "3"]) |
| 62 | + raise |
| 63 | + |
| 64 | + # Initialize components |
| 65 | + # Note: In a real scenario, we'd load existing memory from /data |
| 66 | + print("🧠 Initializing Cognitive Engines...") |
| 67 | + llm = GeminiClient() |
| 68 | + memory = MemorySystem() |
| 69 | + reflection = ReflectionEngine(llm, memory) |
| 70 | + sandbox = SandboxExecutor() |
| 71 | + tool_factory = ToolFactory(llm, sandbox) |
| 72 | + |
| 73 | + # Initialize Evolution Loop |
| 74 | + evolution = CoEvolutionLoop( |
| 75 | + llm_client=llm, |
| 76 | + tool_factory=tool_factory, |
| 77 | + memory_system=memory, |
| 78 | + reflection_engine=reflection, |
| 79 | + sandbox_executor=sandbox, |
| 80 | + ) |
| 81 | + |
| 82 | + # Run Evolution |
| 83 | + print("🧬 Evolving...") |
| 84 | + stats = await evolution.evolve(num_iterations=num_iterations) |
| 85 | + |
| 86 | + # Export Memory |
| 87 | + print("💾 Persisting Memory...") |
| 88 | + memory_state = memory.export_state() |
| 89 | + |
| 90 | + # Save to Volume |
| 91 | + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| 92 | + filename = f"/data/prometheus_memory_{timestamp}.json" |
| 93 | + |
| 94 | + import json |
| 95 | + with open(filename, "w") as f: |
| 96 | + json.dump(memory_state, f, indent=2) |
| 97 | + |
| 98 | + # Also save as 'latest' |
| 99 | + with open("/data/prometheus_memory_latest.json", "w") as f: |
| 100 | + json.dump(memory_state, f, indent=2) |
| 101 | + |
| 102 | + volume.commit() |
| 103 | + |
| 104 | + print(f"✅ Training Complete! Memory saved to {filename}") |
| 105 | + print(f"📈 Stats: {stats.to_dict()}") |
| 106 | + |
| 107 | + return stats.to_dict() |
| 108 | + |
| 109 | +@app.local_entrypoint() |
| 110 | +def main(iterations: int = 10): |
| 111 | + """ |
| 112 | + Local entrypoint to trigger remote training. |
| 113 | + Usage: modal run prometheus/training/modal_train.py --iterations 20 |
| 114 | + """ |
| 115 | + print(f"Triggering remote training for {iterations} iterations...") |
| 116 | + stats = train_prometheus.remote(num_iterations=iterations) |
| 117 | + print("Remote training finished.") |
| 118 | + print(stats) |
0 commit comments