Expand description
§Ai Tournament
A modular Rust crate system for evaluating AI agents via customizable tournaments, supporting sandboxed execution and flexible constraints.
It provides:
- Match scheduling and execution (
Evaluator) - Tournament logic via the
TournamentStrategytrait - Built-in strategies like
SinglePlayerTournament,SwissTournamentandRoundRobin - Resource constraints enforced through Linux cgroups v2 and
taskset
Each match consists of one or more agents, each running as a separate OS process. Process-level isolation applies constraints such as CPU affinity, memory limits, and timeouts.
§Documentation Overview
- For details about the core tournament execution and agent lifecycle, see the
servermodule. - For configuring evaluation behavior, resource limits, and execution environment,
see
Configurationandconstraints. - To understand tournament formats and match scheduling, see the
TournamentStrategytrait and its implementations. - For implementing custom games and agents, check out the [
Game] and [GameFactory] traits.
This crate is designed to be modular and extensible, allowing you to customize agent compilation, match execution, and resource management.
§Usage Example
Below is a minimal example of using the evaluator with a custom game and built-in tournament:
use std::{collections::HashMap, time::Duration};
use anyhow;
use ai_tournament::prelude::*;
fn main() -> anyhow::Result<()> {
// Define per-agent constraints
let constraints = ConstraintsBuilder::new()
.with_ram_per_agent(1000) // in MB
.with_action_timeout(Duration::from_millis(100))
.build()?;
// Create a configuration allowing uncontained execution if cgroup v2 or taskset are not
// available
let config = Configuration::new().with_allow_uncontained(true);
// Your custom game implementing the Game + GameFactory traits
let factory = YourGame::new();
let evaluator = Evaluator::new(factory, config, constraints);
let tournament = SinglePlayerTournament::new(10); // Run 10 games per agent
let (results, errors): (HashMap<String, SinglePlayerScore<_>>, _) =
evaluator.evaluate("path_to_agents_directory", tournament)?;
// Sort and display scores
let mut sorted = results.iter().collect::<Vec<_>>();
sorted.sort_by(|a, b| b.1.cmp(a.1));
for (agent_name, score) in sorted {
println!("{agent_name}: {score:?}");
}
// Print non-compiling agents and the associated error
println!("\nNon-compiling agents:");
for (agent_name, error) in errors.into_iter() {
println!("{agent_name}: {error}");
}
Ok(())
}§Example Agent
Here’s a minimal agent implementation that communicates over TCP:
use std::{
env,
io::{Read, Write},
net::{Ipv4Addr, SocketAddrV4, TcpStream},
str::{self, FromStr},
time::Duration,
};
use anyhow;
use ai_tournament::game_interface::Game;
fn main() -> anyhow::Result<()> {
let mut args = env::args();
let _ = args.next(); // Skip binary name
// Read the port number to connect to
let port = args.next().unwrap().parse()?;
let addr = SocketAddrV4::new(Ipv4Addr::from_str("127.0.0.1")?, port);
let mut stream = TcpStream::connect(addr)?;
// Optionally, reading time_budget and action_timeout from next args
let total_time_budget = Duration::from_micros(args.next().unwrap().parse()?);
let action_timeout = Duration::from_micros(args.next().unwrap().parse()?);
// After the four first arguments (binary name, port number, time budget, and action
// timeout) will follow your arguments defined in your config file
let mut agent = YourAgent::new();
// Interaction loop
loop {
let mut buf = [0; 4096];
let n = stream.read(&mut buf)?;
let string = str::from_utf8(&buf[..n])?;
// Parse game state, compute action, send it back
let game_state = string.parse::<<YourGame as Game>::State>()?;
let action = agent.select_action(game_state);
stream.write_all(action.to_string().as_bytes())?;
}
}§Agent Requirements
Game::StateandGame::Actionmust implementToStringandFromStr- Agent logic must terminate within the configured timeout
- Communication is done over TCP using a basic protocol:
- Server -> Agent : string of Game::State
- Agent -> Server : string of Game::Action
Re-exports§
pub use anyhow;
Modules§
- configuration
- Config for the evaluator behaviors
- constraints
- Defines resource constraints for AI agent execution.
- game_
interface - Module defining traits that need to be implemented to use the evaluator
- prelude
- Commonly used types and traits for quick access.
- server
- Core evaluation logic for running AI tournaments.
- tournament_
strategy - Tournament strategies used by the evaluator to schedule agent matchups.