techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 3)
92c4ae6 verified
Raw
History Blame Contribute Delete
4.29 kB
"""
Base Learning Engine
Abstract interface for self-improving agent modules. Both MementoEngine
(skill generation) and AlphaEvolverEngine (skill optimization) implement
this interface, enabling a unified lifecycle:
analyze_episode → propose_code_change → validate_change
"""
import logging
from abc import ABC, abstractmethod
from typing import Any, Protocol, runtime_checkable
from sqlalchemy.orm import Session
logger = logging.getLogger(__name__)
@runtime_checkable
class SandboxProtocol(Protocol):
"""
Abstract sandbox interface for executing untrusted code.
Upstream uses ContainerSandbox (Docker).
SaaS implementations can inject SandboxExecutionService (Fly.io).
"""
async def execute_raw_python(
self,
tenant_id: str,
code: str,
input_params: dict[str, Any],
timeout: int = 60,
safety_level: str = "MEDIUM_RISK",
**kwargs,
) -> dict[str, Any]:
"""
Execute raw Python code in an isolated sandbox.
Returns:
{
"status": "success" | "failed",
"output": str,
"execution_seconds": float,
"execution_id": str,
}
"""
...
class BaseLearningEngine(ABC):
"""
Unified interface for self-improving agent modules.
Subclasses must implement three core lifecycle methods:
1. analyze_episode — read and interpret execution data
2. propose_code_change — generate a code modification
3. validate_change — execute in sandbox and assess fitness
"""
def __init__(
self,
db: Session,
llm_service: Any | None = None,
sandbox: SandboxProtocol | None = None,
):
self.db = db
self.llm = llm_service
self.sandbox = sandbox
@abstractmethod
async def analyze_episode(self, episode_id: str, **kwargs) -> dict[str, Any]:
"""
Read and interpret an episode's execution data.
Returns a structured analysis dict containing:
- task_description, error_trace, tool_calls (for failures)
- latency, token_usage, edge_case_signals (for successes)
"""
@abstractmethod
async def propose_code_change(
self, context: dict[str, Any], **kwargs
) -> str:
"""
Generate a code modification proposal via LLM.
Args:
context: Analysis output from analyze_episode()
Returns:
Generated Python code string
"""
@abstractmethod
async def validate_change(
self, code: str, test_inputs: list[dict[str, Any]], tenant_id: str, **kwargs
) -> dict[str, Any]:
"""
Execute proposed code in sandbox and assess fitness.
Returns:
{
"passed": bool,
"proxy_signals": dict,
"execution_result": dict,
}
"""
def _get_llm_service(self):
"""Get LLM service with graceful fallback."""
if self.llm is not None:
return self.llm
try:
from core.llm_service import get_llm_service
self.llm = get_llm_service()
return self.llm
except Exception as e:
logger.warning(
f"LLM service unavailable — Auto-Dev features requiring LLM will be skipped: {e}"
)
return None
def _get_sandbox(self):
"""Get sandbox with graceful fallback to ContainerSandbox."""
if self.sandbox is not None:
return self.sandbox
try:
from core.auto_dev.container_sandbox import ContainerSandbox
self.sandbox = ContainerSandbox()
return self.sandbox
except Exception as e:
logger.warning(f"Sandbox unavailable — validation will be skipped: {e}")
return None
def _strip_markdown_fences(self, code: str) -> str:
"""Strip markdown code fences from LLM output."""
code = code.strip()
if code.startswith("```python"):
code = code[len("```python") :]
elif code.startswith("```"):
code = code[3:]
if code.endswith("```"):
code = code[:-3]
return code.strip()