agent_m/agentm/views/training.py
mscrnt 4500bfd388 Refactor agent management views and styles
- Removed commented-out header styles from styles.base.tcss and styles.tcss.
- Added new styles for danger buttons and agent selection views in styles.base.tcss and styles.tcss.
- Implemented AgentHomeView to manage agent actions and display metadata.
- Created AgentSelectView for selecting agents with a new layout and functionality.
- Added CreateAgentView for creating new agents with input validation.
- Removed obsolete eval.py and replaced it with evaluation.py.
- Developed GameSelectView for selecting games with a dynamic loading interface.
- Introduced ModelSelectView for selecting models associated with agents.
- Created SelectRunView for managing runs associated with agents.
- Added SubmissionView and TrainingView for handling model training and submission processes.
- Updated requirements.txt to include pyfiglet for ASCII art rendering.
2025-05-26 07:55:58 -07:00

107 lines
4.3 KiB
Python

from textual.screen import Screen
from textual.widgets import Static, Input, Button
from textual.containers import Vertical, Horizontal
from agentm.theme.palette import get_theme
from agentm.utils.logger import log_with_caller
from agentm.logic.db_functions import insert_model, update_run_pending
from datetime import datetime
palette = get_theme()
class TrainingView(Screen):
BINDINGS = [
("escape", "app.pop_screen", "Back")
]
def __init__(self, agent: dict, model: dict | None, run: dict):
super().__init__()
self.agent_metadata = agent
self.model_metadata = model
self.run_metadata = run
self.is_pending_run = run.get("pending", True)
def compose(self):
log_with_caller("info", f"Opening TrainingView for agent='{self.agent_metadata['name']}', run='{self.run_metadata['name']}', pending={self.is_pending_run}")
yield Static(f"[{palette.ACCENT} bold]Training: {self.agent_metadata['name']}[/]", classes="header")
if self.is_pending_run:
yield self.render_pending_setup()
else:
yield self.render_resume_options()
def render_pending_setup(self):
yield Static("[b]Initial Model Setup[/b]", classes="subheader")
self.name_input = Input(placeholder="Model Name", id="model_name")
self.steps_input = Input(placeholder="Total Training Steps", id="total_steps")
self.lr_input = Input(placeholder="Initial Learning Rate", id="learning_rate")
self.clip_input = Input(placeholder="Initial Clip Range", id="clip_range")
self.notes_input = Input(placeholder="Notes", id="notes")
self.confirm_button = Button("✅ Create & Start Training", id="confirm_model_btn", classes="confirm_button")
return Vertical(
self.name_input,
self.steps_input,
self.lr_input,
self.clip_input,
self.notes_input,
self.confirm_button,
classes="centered_layout"
)
def render_resume_options(self):
model = self.model_metadata
from rich.table import Table
from rich.panel import Panel
table = Table.grid(padding=(0, 1))
table.add_column("Key", style="bold underline")
table.add_column("Value", style=palette.ACCENT, overflow="fold")
table.add_row("Name", model["name"])
table.add_row("Steps", f"{model['total_steps_completed']} / {model['total_steps_planned']}")
table.add_row("Reward", str(model.get("average_reward", "")))
table.add_row("Learning Rate", str(model.get("current_learning_rate", "")))
table.add_row("Clip Range", str(model.get("current_clip_range", "")))
table.add_row("Created", model.get("created_at", ""))
return Vertical(
Static(Panel(table, title="Model Info", border_style=palette.BORDER), classes="agent_info_box"),
Button("⏯️ Resume Training", id="resume_training_btn", classes="confirm_button"),
classes="centered_layout"
)
async def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "confirm_model_btn":
try:
name = self.name_input.value.strip()
total_steps = int(self.steps_input.value)
learning_rate = float(self.lr_input.value)
clip_range = float(self.clip_input.value)
notes = self.notes_input.value.strip()
log_with_caller("info", f"Creating new model: {name} for agent_id={self.agent_metadata['id']}")
insert_model(
agent_id=self.agent_metadata["id"],
name=name,
total_steps_planned=total_steps,
current_learning_rate=learning_rate,
current_clip_range=clip_range,
notes=notes
)
update_run_pending(self.run_metadata["id"], False)
log_with_caller("info", f"Model '{name}' created and run marked as not pending")
await self.app.pop_screen()
except Exception as e:
log_with_caller("error", f"Failed to create model: {e}")
elif event.button.id == "resume_training_btn":
log_with_caller("info", f"Resuming training for model: {self.model_metadata['name']}")
await self.app.pop_screen()