Arena Dashboard and Visualization System
Streamlit dashboard with 5 tabs, Plotly charts, and the RunArtifacts streaming system for live tournament monitoring
Arena Dashboard and Visualization System
Overview
The Red Team Arena includes a Streamlit dashboard (dashboard/app.py) and a Plotly chart library (dashboard/charts.py) for visualizing tournament and experiment results. Additionally, the arena/artifacts.py module generates standalone HTML artifacts for every run, enabling offline analysis without running the dashboard.
The visualization system operates at two levels:
- Live artifacts: Each tournament/experiment writes a timestamped folder with streaming
rounds.jsonland finalsummary.json,leaderboard.md, and interactive Plotly HTML charts - Streamlit dashboard: A persistent web app that reads from the SQLite database and renders 5 interactive tabs
Streamlit Dashboard
Launch: streamlit run dashboard/app.py (opens http://localhost:8501)
Page Configuration
- Layout: Wide mode with expanded sidebar
- Theme: Dark mode (Catppuccin-inspired CSS with
#1e1e2ebackground,#cba6f7accent) - Caching:
@st.cache_resourceon the ArenaLogger to avoid re-initializing SQLite on every rerun
Sidebar
The sidebar provides:
- Run selector: Dropdown populated from
experimentstable in SQLite. Options include individual runs and an "All runs (aggregated)" option - Links: Quick links to GitHub, HarmBench, JailbreakBench
Metric Cards
Five top-level metrics are displayed as styled cards:
| Metric | Source | Format |
|---|---|---|
| Total Rounds | COUNT(*) from rounds table | Comma-separated integer |
| Attack Success Rate | AVG(judge_attack_success) | Percentage |
| Defender Accuracy | AVG(judge_defender_correct) | Percentage |
| Avg Harm Severity | AVG(judge_harm_severity) | X.XX/5 |
| Avg Judge Confidence | AVG(judge_confidence) | X.XX |
The 5 Tabs
Tab 1: Leaderboard
Visualizations:
- Attacker Elo bar chart: Horizontal bar chart, red/orange color, sorted by rating ascending
- Defender Elo bar chart: Horizontal bar chart, green color, sorted by rating ascending
- Elo trajectory line chart: Multi-line time series showing all agents' ratings over time, with entity type encoded as line dash (solid for attackers, dashed for defenders)
Data source: Elo ratings are derived from the latest round data in the database (attacker_elo_after, defender_elo_after columns).
Tab 2: Heatmap
Visualization: Attack success rate heatmap -- rows are attackers, columns are defenders, cell values are the fraction of rounds where the attacker bypassed the defender.
Color scale: RdYlGn_r (reversed Red-Yellow-Green) -- red cells mean high attack success (bad for defender), green cells mean low attack success (good for defender).
Data source: get_attack_success_matrix() query that groups by attacker_id and defender_id, computing AVG(judge_attack_success).
Tab 3: Categories
Visualizations:
- Grouped bar chart: Attack success rate, defender accuracy, or average severity broken down by harm category. Selector dropdown lets the user choose the metric.
- Raw data table: Expandable pandas DataFrame showing all category breakdown data with formatted percentages.
Data source: get_category_breakdown() query that groups by seed_category, attacker_id, defender_id.
Tab 4: Round Log
The most detailed tab. Provides:
- Filter controls: Multi-select for attacker, defender, and category. Checkbox for "successful attacks only".
- Severity distribution pie chart: Donut chart showing the distribution of harm severity levels (1-5) in the filtered rounds.
- Rolling win rate chart: 10-round rolling average of attack success for the first selected attacker.
- Round table: DataFrame with columns: Round, Attacker, Defender, Category, Atk Win (checkmark/cross), Severity, Def Flagged (flag/dash), Reasoning.
- Round inspector: Dropdown to select a specific round and view the full attack prompt, judge reasoning, policy violation, harm severity, and defender confidence.
Tab 5: Experiments
Data source: get_all_run_ids() query on the experiments table.
Displays a table of all recorded experiments with: Run ID, Type, Started timestamp, Total Rounds. This is a metadata view; the actual experiment results are in the artifact folders.
Plotly Chart Library
dashboard/charts.py provides six reusable chart builder functions, all returning plotly.graph_objects.Figure objects with the plotly_dark template:
elo_trajectory_chart(trajectories)
- Type: Multi-line time series
- X: Timestamp (converted from epoch seconds to datetime)
- Y: Elo rating
- Color: Entity ID (agent name)
- Dash: Entity type (attacker=solid, defender=dashed)
- Features: Unified hover mode, legend with agent names
attack_success_heatmap(matrix)
- Type: Heatmap (
go.Heatmap) - X: Defender IDs
- Y: Attacker IDs
- Values: Success rates (0.0-1.0)
- Color scale:
RdYlGn_r(reversed) - Features: Text overlay showing percentage values, hover with exact rates
category_bar_chart(breakdown, metric)
- Type: Grouped bar chart (
px.bar) - X: Harm category
- Y: Selected metric (attack_success_rate, defender_accuracy, or avg_severity)
- Color: Defender ID
- Features: -35 degree X-axis labels for readability
elo_leaderboard_bar(leaderboard, entity_type)
- Type: Horizontal bar chart (
go.Bar) - X: Rating
- Y: Display name
- Color: Red-orange for attackers, medium sea green for defenders
- Features: Rating values as text outside bars
severity_distribution(rounds)
- Type: Donut pie chart (
go.Piewithhole=0.4) - Labels: Minimal, Low, Medium, High, Critical
- Colors: Green(1) -> Yellow(2) -> Orange(3) -> Red(4) -> Purple(5)
- Data source: Counter of
judge_harm_severityvalues
attacker_win_rate_over_time(rounds, attacker_id)
- Type: Line chart with markers
- X: Round number
- Y: 10-round rolling average of attack success
- Features:
min_periods=1for the rolling window so the chart starts from round 1
RunArtifacts System
arena/artifacts.py implements a per-run artifact writer that creates a self-contained folder for every tournament or experiment.
Folder Structure
runs/20260611_192241_tournament_6ed3ad0a/
meta.json -- Run config + agents (written at start)
rounds.jsonl -- One JSON line per round (streamed live)
summary.json -- Aggregate stats (written at finalize)
leaderboard.md -- Human-readable Elo table
report.html -- Index linking the charts
chart_*.html -- Interactive Plotly visualizations
Live Streaming: rounds.jsonl
The log_round() method appends one JSON line per round and calls flush() immediately. This means:
rounds.jsonlis always consistent, even if the process crashes mid-run- You can
tail -f rounds.jsonlwhile a tournament is running to watch results in real-time - Each line contains the full round data: attacker/defender IDs, attack prompt, defender verdict, judge verdict, Elo before/after, template used, turn number
Finalization
When finalize() is called (at the end of a tournament or experiment):
- summary.json: Writes aggregate stats (total rounds, attack success rate, severity distribution, judge modes, full Elo leaderboard)
- leaderboard.md: Generates a markdown table with attacker and defender Elo ratings
- Charts: Calls
dashboard/charts.pyfunctions to generate HTML files:chart_elo_trajectory.htmlchart_attack_heatmap.htmlchart_category_breakdown.htmlchart_severity.htmlchart_attacker_elo.htmlchart_defender_elo.html
- report.html: Generates an index HTML page linking all charts with a dark-themed design
Graceful Degradation
If plotly or pandas are not installed, chart generation is skipped and a CHARTS_SKIPPED.txt file is written explaining the situation. The JSON and markdown artifacts are always written regardless.
Artifact Bundle for Experiments
Experiments use a replay pattern: they stream to SQLite during execution, then run_experiments.py replays the logged rounds through a RunArtifacts writer to populate the standard folder structure. The results.json file is added alongside the standard artifacts.
SQLite Database Schema
The arena.db SQLite database uses WAL mode and contains three tables:
rounds
One row per arena round with 28 columns including:
- Run metadata:
run_id,experiment_tag,timestamp,round_number - Agent IDs:
attacker_id,defender_id - Seed info:
seed_prompt_id,seed_category,seed_severity - Attack:
attack_prompt,template_used - Defense:
defender_flagged,defender_confidence,defender_latency_ms - Judge:
policy_violation,harm_severity,attack_success,defender_correct,harm_category,reasoning,confidence,judge_mode,judge_latency_ms - Elo:
attacker_elo_before,attacker_elo_after,defender_elo_before,defender_elo_after - Metadata:
turn_number,metadata(JSON)
Indexes: run_id, attacker_id, defender_id, seed_category, judge_attack_success
elo_snapshots
Periodic snapshots for trajectory analysis:
run_id,timestamp,entity_id,entity_type,rating,games
experiments
High-level experiment metadata:
run_id(unique),experiment_type,config_json,started_at,finished_at,total_rounds,notes
Migration support: The logger checks for the judge_mode column on initialization and adds it via ALTER TABLE if missing, supporting databases created before the judge mode feature was added.
Standalone HTML Artifacts
The report.html generated by RunArtifacts is a self-contained dark-themed page:
<style>
body { font-family: system-ui, sans-serif; background:#111; color:#eee; }
a { color:#ff7a59; }
code { background:#222; padding:2px 6px; border-radius:4px; }
</style>
Each chart is an interactive Plotly HTML file loaded via CDN (plotly.js from jsdelivr). The charts support zoom, pan, hover tooltips, and can be opened in any browser without running the Streamlit app.
Cross-References
- red-team-arena -- Full system overview
- red-team-arena-agents -- Agents whose data feeds the dashboard
- red-team-arena-elo -- Elo system that produces leaderboard data
- red-team-arena-experiments -- Experiments that produce structured results