Update readme for separate llm engine executables
This commit is contained in:
@@ -17,7 +17,6 @@ from .web.websockets import Websockets
|
||||
from .web_agent import WebAgent
|
||||
from .web_io_buffer import WebIOBuffer
|
||||
from .working_memory import WorkingMemory
|
||||
from .xml_validator import XMLValidator
|
||||
|
||||
class Main:
|
||||
@classmethod
|
||||
@@ -81,7 +80,6 @@ class Main:
|
||||
working_memory=self._working_memory,
|
||||
metrics=SystemMetrics(),
|
||||
llms=self._llms,
|
||||
validator=XMLValidator(self._action_schema),
|
||||
parser=ResponseParser(config.work_dir, self._io_buffer),
|
||||
iteration_logger=IterationLogger(self._config.iterations_dir, self._system_prompt, self._action_schema),
|
||||
)
|
||||
|
||||
@@ -1,77 +1,74 @@
|
||||
from abc import ABC
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from .llm_engine import LlmEngine
|
||||
from .response_parser import ResponseParser
|
||||
from .system_metrics import SystemMetrics
|
||||
from .util import pretty_print_element
|
||||
from .working_memory import WorkingMemory
|
||||
from .xml_validator import XMLValidator
|
||||
|
||||
class BaseAgent(ABC):
|
||||
"""
|
||||
Abstract base class for SIA agents.
|
||||
|
||||
Provides core functionality for maintaining working memory, system metrics,
|
||||
and coordinating components for LLM inference.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
system_prompt: str,
|
||||
action_schema: str,
|
||||
working_memory: WorkingMemory,
|
||||
metrics: SystemMetrics,
|
||||
validator: XMLValidator,
|
||||
parser: ResponseParser,
|
||||
):
|
||||
"""
|
||||
Initialize agent with required components.
|
||||
"""
|
||||
self._system_prompt = system_prompt
|
||||
self._action_schema = action_schema
|
||||
self._working_memory = working_memory
|
||||
self._metrics = metrics
|
||||
self._validator = validator
|
||||
self._parser = parser
|
||||
|
||||
@property
|
||||
def system_prompt(self) -> str:
|
||||
"""Get the system prompt."""
|
||||
return f"{self._system_prompt}\n{self._action_schema}"
|
||||
|
||||
def _compile_context(self, llmEngine: LlmEngine) -> str:
|
||||
"""
|
||||
Compile the current context for LLM inference.
|
||||
Includes system metrics and working memory entries.
|
||||
|
||||
Returns:
|
||||
str: Complete context as XML string
|
||||
"""
|
||||
memory_context = self._working_memory.generate_context()
|
||||
metrics_data = self._metrics.get_metrics()
|
||||
|
||||
# Create context element
|
||||
context = ET.Element("context")
|
||||
context.set("time", metrics_data["timestamp"])
|
||||
context.set("memory_used", str(metrics_data["memory_used"]))
|
||||
context.set("memory_total", str(metrics_data["memory_total"]))
|
||||
context.set("disk_used", str(metrics_data["disk_used"]))
|
||||
context.set("disk_total", str(metrics_data["disk_total"]))
|
||||
context.set("stdin", str(self._parser.io_buffer.buffer_length()))
|
||||
context.set("context", "100%")
|
||||
|
||||
for entry in memory_context:
|
||||
context.append(entry)
|
||||
|
||||
context_str = pretty_print_element(context)
|
||||
|
||||
# Calculate token usage percentage
|
||||
token_count = llmEngine.token_count(self.system_prompt, context_str)
|
||||
token_limit = llmEngine.token_limit()
|
||||
context_usage = (float(token_count) / float(token_limit)) * 100.0
|
||||
|
||||
# Update context usage metric
|
||||
context.set("context", f"{str(round(context_usage, 2))}%")
|
||||
|
||||
from abc import ABC
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from .llm_engine import LlmEngine
|
||||
from .response_parser import ResponseParser
|
||||
from .system_metrics import SystemMetrics
|
||||
from .util import pretty_print_element
|
||||
from .working_memory import WorkingMemory
|
||||
|
||||
class BaseAgent(ABC):
|
||||
"""
|
||||
Abstract base class for SIA agents.
|
||||
|
||||
Provides core functionality for maintaining working memory, system metrics,
|
||||
and coordinating components for LLM inference.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
system_prompt: str,
|
||||
action_schema: str,
|
||||
working_memory: WorkingMemory,
|
||||
metrics: SystemMetrics,
|
||||
parser: ResponseParser,
|
||||
):
|
||||
"""
|
||||
Initialize agent with required components.
|
||||
"""
|
||||
self._system_prompt = system_prompt
|
||||
self._action_schema = action_schema
|
||||
self._working_memory = working_memory
|
||||
self._metrics = metrics
|
||||
self._parser = parser
|
||||
|
||||
@property
|
||||
def system_prompt(self) -> str:
|
||||
"""Get the system prompt."""
|
||||
return f"{self._system_prompt}\n{self._action_schema}"
|
||||
|
||||
def _compile_context(self, llmEngine: LlmEngine) -> str:
|
||||
"""
|
||||
Compile the current context for LLM inference.
|
||||
Includes system metrics and working memory entries.
|
||||
|
||||
Returns:
|
||||
str: Complete context as XML string
|
||||
"""
|
||||
memory_context = self._working_memory.generate_context()
|
||||
metrics_data = self._metrics.get_metrics()
|
||||
|
||||
# Create context element
|
||||
context = ET.Element("context")
|
||||
context.set("time", metrics_data["timestamp"])
|
||||
context.set("memory_used", str(metrics_data["memory_used"]))
|
||||
context.set("memory_total", str(metrics_data["memory_total"]))
|
||||
context.set("disk_used", str(metrics_data["disk_used"]))
|
||||
context.set("disk_total", str(metrics_data["disk_total"]))
|
||||
context.set("stdin", str(self._parser.io_buffer.buffer_length()))
|
||||
context.set("context", "100%")
|
||||
|
||||
for entry in memory_context:
|
||||
context.append(entry)
|
||||
|
||||
context_str = pretty_print_element(context)
|
||||
|
||||
# Calculate token usage percentage
|
||||
token_count = llmEngine.token_count(self.system_prompt, context_str)
|
||||
token_limit = llmEngine.token_limit()
|
||||
context_usage = (float(token_count) / float(token_limit)) * 100.0
|
||||
|
||||
# Update context usage metric
|
||||
context.set("context", f"{str(round(context_usage, 2))}%")
|
||||
|
||||
return pretty_print_element(context)
|
||||
@@ -14,7 +14,6 @@ from .response_buffer import ResponseBuffer
|
||||
from .response_parser import ResponseParser
|
||||
from .system_metrics import SystemMetrics
|
||||
from .working_memory import WorkingMemory
|
||||
from .xml_validator import XMLValidator
|
||||
|
||||
class LlmState(Enum):
|
||||
IDLE = auto()
|
||||
@@ -28,7 +27,6 @@ class WebAgent(BaseAgent):
|
||||
working_memory: WorkingMemory,
|
||||
metrics: SystemMetrics,
|
||||
llms: Dict[str, LlmEngine],
|
||||
validator: XMLValidator,
|
||||
parser: ResponseParser,
|
||||
iteration_logger: IterationLogger,
|
||||
):
|
||||
@@ -37,7 +35,6 @@ class WebAgent(BaseAgent):
|
||||
action_schema,
|
||||
working_memory,
|
||||
metrics,
|
||||
validator,
|
||||
parser
|
||||
)
|
||||
self._llms = llms
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
import xml.etree.ElementTree as ET
|
||||
from typing import Optional, Set
|
||||
|
||||
class XMLValidator:
|
||||
"""
|
||||
Validates XML content against a schema.
|
||||
|
||||
Attributes:
|
||||
_schema: The parsed XML schema to validate against
|
||||
_valid_root_elements: Set of valid root element names from schema
|
||||
"""
|
||||
|
||||
def __init__(self, schema: str):
|
||||
"""
|
||||
Initialize validator with XML schema.
|
||||
|
||||
Args:
|
||||
schema: XML schema string
|
||||
"""
|
||||
# Register namespace used in schema
|
||||
ET.register_namespace('xs', 'http://www.w3.org/2001/XMLSchema')
|
||||
|
||||
try:
|
||||
# Parse schema
|
||||
self._schema = ET.fromstring(schema.strip())
|
||||
|
||||
# Extract valid root elements
|
||||
ns = {'xs': 'http://www.w3.org/2001/XMLSchema'}
|
||||
elements = self._schema.findall(".//xs:element", ns)
|
||||
self._valid_root_elements = {elem.get('name') for elem in elements if elem.get('name')}
|
||||
|
||||
except ET.ParseError as e:
|
||||
raise ValueError(f"Invalid schema: {e}")
|
||||
|
||||
def validate(self, xml: str) -> Optional[str]:
|
||||
"""
|
||||
Validate XML content against the schema.
|
||||
|
||||
Args:
|
||||
xml: XML string to validate
|
||||
|
||||
Returns:
|
||||
str: Error message if validation fails, None if validation succeeds
|
||||
"""
|
||||
try:
|
||||
# Parse XML
|
||||
root = ET.fromstring(xml.strip())
|
||||
|
||||
# Check root element is valid
|
||||
if root.tag not in self._valid_root_elements:
|
||||
return f"Invalid root element: {root.tag}. Expected one of: {sorted(self._valid_root_elements)}"
|
||||
|
||||
# Get schema definition for this element
|
||||
ns = {'xs': 'http://www.w3.org/2001/XMLSchema'}
|
||||
element_schema = self._schema.find(f".//xs:element[@name='{root.tag}']", ns)
|
||||
if element_schema is None:
|
||||
return f"Schema definition not found for element: {root.tag}"
|
||||
|
||||
# Validate attributes if complex type defined
|
||||
complex_type = element_schema.find('xs:complexType', ns)
|
||||
if complex_type is not None:
|
||||
# Check required attributes
|
||||
for attr in complex_type.findall('.//xs:attribute[@use="required"]', ns):
|
||||
attr_name = attr.get('name')
|
||||
if attr_name not in root.attrib:
|
||||
return f"Missing required attribute '{attr_name}' on element '{root.tag}'"
|
||||
|
||||
# Check attribute types
|
||||
for attr_name, attr_value in root.attrib.items():
|
||||
attr_schema = complex_type.find(f'.//xs:attribute[@name="{attr_name}"]', ns)
|
||||
if attr_schema is None:
|
||||
return f"Unexpected attribute '{attr_name}' on element '{root.tag}'"
|
||||
|
||||
attr_type = attr_schema.get('type')
|
||||
if attr_type == 'xs:string':
|
||||
continue # All string values are valid
|
||||
elif attr_type == 'xs:integer':
|
||||
try:
|
||||
int(attr_value)
|
||||
except ValueError:
|
||||
return f"Invalid integer value '{attr_value}' for attribute '{attr_name}'"
|
||||
|
||||
return None # Validation successful
|
||||
|
||||
except ET.ParseError as e:
|
||||
return f"Invalid XML: {e}"
|
||||
except Exception as e:
|
||||
return f"Validation error: {e}"
|
||||
|
||||
def get_valid_root_elements(self) -> Set[str]:
|
||||
"""
|
||||
Get set of valid root element names from schema.
|
||||
|
||||
Returns:
|
||||
Set[str]: Set of valid root element names
|
||||
"""
|
||||
return self._valid_root_elements.copy()
|
||||
Reference in New Issue
Block a user