wiki-speedrun / src /agents /base.py
jwlutz's picture
Initial commit: Wikipedia Speedrun benchmark with Flask dashboard
0e61be5
Raw
History Blame Contribute Delete
2.44 kB
"""
Agent base class and protocol for Wikipedia speedrun players.
All agents must implement choose_link() to decide which link to click next.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from src.game.state import GameState
@dataclass
class AgentContext:
"""
Context passed to agents for decision making.
Attributes:
current_title: Title of the current Wikipedia article
target_title: Title of the target article we're trying to reach
available_links: List of clickable link titles on current page
path_so_far: List of titles visited (including current)
step_count: Number of clicks made so far
"""
current_title: str
target_title: str
available_links: list[str]
path_so_far: list[str]
step_count: int
class Agent(ABC):
"""
Abstract base class for Wikipedia speedrun agents.
Agents receive the current game state and must choose which link to click.
Different agents use different strategies (embeddings, LLMs, BFS, human input).
"""
@property
@abstractmethod
def name(self) -> str:
"""Short identifier for the agent (e.g., 'greedy', 'llm', 'human')."""
...
@property
@abstractmethod
def description(self) -> str:
"""Human-readable description of the agent's strategy."""
...
@property
def requires_visualization(self) -> bool:
"""Whether this agent requires the browser to be visible (e.g., HumanAgent)."""
return False
@abstractmethod
def choose_link(self, context: AgentContext) -> str:
"""
Choose which link to click next.
Args:
context: Current game context with available links
Returns:
The title of the link to click. Must be in context.available_links.
Raises:
ValueError: If returned link is not in available_links
"""
...
def on_game_start(self, start_title: str, target_title: str) -> None:
"""Called when a new game begins. Override for setup."""
pass
def on_game_end(self, won: bool, path: list[str]) -> None:
"""Called when game ends. Override for cleanup/learning."""
pass
def __repr__(self) -> str:
return f"{self.__class__.__name__}(name={self.name!r})"