---
title: Web UI
description: Run evals and review results in your browser
---

Start the web UI with `ezvals serve`:

```bash
ezvals serve evals.py
```

<img
  className="block dark:hidden"
  src="/assets/ui-screenshot-light.png"
  alt="EZVals Web UI"
/>
<img
  className="hidden dark:block"
  src="/assets/ui-screenshot-dark.png"
  alt="EZVals Web UI"
/>

## How It Works

The UI discovers all `@eval` decorated functions in your file but doesn't run them until you click **Run**. Results stream in real-time as each evaluation completes.

Results are saved to `.ezvals/sessions/` as JSON files, organized by session subdirectories.

## Results Storage

```
.ezvals/
├── sessions/
│   ├── model-comparison/
│   │   ├── baseline_a1b2c3d4.json
│   │   └── improved_e5f6g7h8.json
│   └── default/
│       └── swift-falcon_i9j0k1l2.json
└── ezvals.json  # Configuration
```

Each run file includes session metadata:

```json
{
  "session_name": "model-upgrade",
  "run_name": "gpt5-baseline",
  "run_id": "2024-01-15T10-30-00Z",
  "total_evaluations": 50,
  "total_passed": 45,
  "results": [...]
}
```

## Run Controls

- **Run Selected**: Check rows, then click play to rerun only those evaluations
- **Run All**: With nothing selected, click play to rerun everything
- **Stop**: Cancel pending and running evaluations mid-run

## Search and Columns

Open the overflow (three-dot) menu, then hover **Columns**:

- **Show** toggles whether a column is visible in the table
- **Search** toggles whether that column is included in global search matches

These controls are independent, so you can keep a column hidden but still searchable (or visible but excluded from search).

## Detail Page

Click a function name to open the full-page detail view with its own URL (`/runs/{run_id}/results/{index}`). Navigate between results with arrow keys (↑/↓) or press Escape to return to the table.

When opening detail from comparison mode, URLs keep repeated `compare_run_id` query params. This makes comparison detail links shareable/bookmarkable and restores the same run set when opened in a new tab:

- `/runs/{run_id}/results/{index}?compare_run_id=runA&compare_run_id=runB`
- `/runs/{run_id}/results/{index}?compare_run_id=runB` (auto-includes the current detail run as base)

When `input`, `output`, `reference`, or trace `messages` contain chat-style message arrays (OpenAI, Anthropic, or similar `{role, content}` variants), the detail view auto-renders them in a chat-style layout. Use the **Pretty**/**Raw** toggle in each section to switch between formatted message boxes and raw JSON.

## Inline Editing

In the detail page, you can edit:
- **Dataset**: Reassign to different dataset
- **Labels**: Add or remove labels
- **Scores**: Adjust scores or add new ones
- **Annotations**: Add notes for review

Changes are saved to the results file.

## Export

Click the overflow (three-dot) menu in the header, then hover **Download** to open the export menu:

| Format | Type | Description |
|--------|------|-------------|
| JSON | Raw | Full results file as-is |
| CSV | Raw | All results in flat CSV format |
| Markdown | Filtered | ASCII bar charts + table with current filters applied |
| PNG | Visual | Chart image with stats bars, metrics, and branding |

**Filtered exports** respect:
- Active search and filters (only visible rows are exported)
- Column visibility (hidden columns are excluded)
- Computed stats from filtered results

PNG export opens a preview modal where you can save or copy the image. Use the options button to edit the title, tune score colors, toggle footer metrics, and in comparison mode rename/reorder runs before exporting.

Markdown uses ASCII progress bars with color indicators:

```
| Metric | Progress | Score |
|--------|----------|-------|
| **accuracy** | ████████████████░░░░ 🟢 | 82% (41/50) |
| **quality** | ██████████████░░░░░░ 🟡 | 70% (avg: 0.70) |
```

## Keyboard Shortcuts

| Key | Action |
|-----|--------|
| `↑/↓` | Navigate results (detail page) |
| `Esc` | Back to table |

## Custom Port

```bash
ezvals serve evals.py --port 3000
```

## Loading Previous Runs

To view or continue a previous run, pass the run JSON file directly:

```bash
ezvals serve .ezvals/sessions/default/sleek-wolf_1705312200.json
```

The UI loads with that run's results. If the original eval file still exists, you can rerun evaluations normally. If the source file was moved or deleted, the UI shows a warning and works in view-only mode.

This is useful for:
- Reviewing historical results
- Continuing an interrupted session
- Sharing runs between machines (copy the JSON file)

## Comparison Mode

Compare results across multiple runs side-by-side. When you have 2+ runs in a session:

1. Click **+ Compare** in the stats bar
2. Select runs from the dropdown (up to 4)
3. View grouped bar charts showing metrics across runs
4. Compare outputs in a table with per-run columns

Each run gets a color-coded chip. The chart shows pass rates and latency for each run. The table aligns results by function name and dataset, making it easy to spot regressions or improvements.

To exit comparison mode, click the × on run chips until only one remains.

Comparison mode also has a shareable URL format based on repeated query params:

`/?compare_run_id=runA&compare_run_id=runB`

## Run Selector

When multiple runs exist in a session, the run name becomes a dropdown. Select past runs to view their results. The dropdown shows run names with timestamps.
