Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d949c9a
feat(eval): add agent-based iterative format optimization framework a…
gspencergoog Jul 24, 2026
ef7b1ac
feat(eval): parameterize history run metadata with model and thinking…
gspencergoog Jul 24, 2026
b403b36
refactor(eval): consolidate thinking budget baselines under eval/base…
gspencergoog Jul 24, 2026
819d5ef
refactor(eval): remove one-off run_thinking_baselines.py script
gspencergoog Jul 24, 2026
70471dc
refactor(eval): remove redundant baselines directory inside inference…
gspencergoog Jul 24, 2026
4a9cb3f
refactor(eval): apply code review cleanup suggestions to inference-fo…
gspencergoog Jul 24, 2026
1c8f17f
refactor(eval): remove misplaced express runs from atom history and u…
gspencergoog Jul 24, 2026
0315708
refactor(eval): remove individual run_XXX history directories while k…
gspencergoog Jul 24, 2026
7c8eba6
refactor(eval): consolidate iterative format optimizer assets and his…
gspencergoog Jul 28, 2026
4082a70
Merge branch 'main' into iterative_optimization
gspencergoog Jul 28, 2026
4670275
Merge branch 'main' into iterative_optimization
gspencergoog Jul 30, 2026
39a9907
refactor(eval): flatten baselines into iterative_format_optimizer and…
gspencergoog Jul 28, 2026
8623f47
fix(eval): direct ephemeral optimizer logs to iterative_format_optimi…
gspencergoog Jul 28, 2026
3cabced
refactor(eval): streamline history index generation to single master …
gspencergoog Jul 28, 2026
c7503a9
feat(eval): add --temperature and --epochs options to optimizer CLI a…
gspencergoog Jul 28, 2026
fec5f40
refactor(eval): apply code review recommendations to compare_results …
gspencergoog Jul 28, 2026
ad995ba
test(optimizer): Expand unit test suite to achieve 90.2% code coverage
gspencergoog Jul 28, 2026
d9398c7
fix(ci): fix format-check and build_and_deploy CI failures
gspencergoog Jul 30, 2026
f95a18d
fix(eval): fix mypy type checking errors and exclude test path in pyp…
gspencergoog Jul 30, 2026
76c6349
fix(ci): exclude eval directory from mypy type checking
gspencergoog Jul 30, 2026
d7e94e8
refactor(eval): include traceback in subprocess evaluation exception …
gspencergoog Jul 30, 2026
1d409a4
refactor(eval): wrap blocking timeout parse in asyncio.to_thread and …
gspencergoog Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,8 @@ app.*.map.json

# SwiftPM
Package.resolved

# Evaluation & Optimizer temporary logs
eval/logs/
eval/iterative_format_optimizer/logs/
eval/iterative_format_optimizer/skills/inference-format-optimizer/logs/
5 changes: 4 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ renderers/lit/a2ui_explorer/src/generated/**
.next
**/.next

# Evaluation logs
# Evaluation logs and history
eval/logs
**/eval/logs
eval/history
**/history
**/history_summary.md
6 changes: 5 additions & 1 deletion eval/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Each sample in a dataset YAML file defines:

## Running Evaluations

Make sure you are in the `eval/` directory.
Make sure your working directory is `eval/`.

### Prerequisites

Expand Down Expand Up @@ -121,3 +121,7 @@ To run the unit tests and validate all dataset files against `datasets/dataset_s
```bash
uv run python -m pytest
```

## Iterative Format Optimization Framework

For benchmarking, testing, and optimizing alternative A2UI inference formats (Atom, Express, Elemental), see the [Iterative Format Optimization Guide](iterative_format_optimizer/skills/inference-format-optimizer/SKILL.md).
142 changes: 111 additions & 31 deletions eval/a2ui_eval/strategies/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import asyncio
import json
import re
from inspect_ai.solver import Solver, solver, TaskState, Generate
Expand Down Expand Up @@ -108,6 +109,107 @@ async def solve(state: TaskState, generate: Generate) -> TaskState:
return solve


import multiprocessing


def _parse_and_validate_in_process(
format_name: str,
version: str,
resolved_catalog_path: str,
surface_id: str,
completion: str,
) -> list:
catalog_config = CatalogConfig.from_path("basic_catalog", resolved_catalog_path)
strategy = _get_strategy(
format_name,
version,
catalog_config,
surface_id=surface_id,
)
catalog = (
strategy.get_selected_catalog()
if isinstance(strategy, TransportFormat)
else getattr(strategy, "catalog")
)
Comment thread
gspencergoog marked this conversation as resolved.
validator = catalog.validator

parts = strategy.parser.parse_response(completion)
compiled_jsons = []
for p in parts:
a2ui_json = getattr(p, "a2ui_json", None)
if a2ui_json:
if isinstance(a2ui_json, list):
compiled_jsons.extend(a2ui_json)
else:
compiled_jsons.append(a2ui_json)

if not compiled_jsons:
raise ValueError(
f"No compiled A2UI {format_name} user interface found in parsed parts."
)

validator.validate(compiled_jsons)
return compiled_jsons


import traceback


def _process_target_wrapper(
format_name: str,
version: str,
resolved_catalog_path: str,
surface_id: str,
completion: str,
return_dict: dict,
):
try:
res = _parse_and_validate_in_process(
format_name, version, resolved_catalog_path, surface_id, completion
)
return_dict["result"] = res
except Exception as e:
return_dict["error"] = f"{e}\n{traceback.format_exc()}"


def parse_with_hard_kill_timeout(
format_name: str,
version: str,
resolved_catalog_path: str,
surface_id: str,
completion: str,
timeout_sec: float = 5.0,
) -> list:
with multiprocessing.Manager() as manager:
return_dict = manager.dict()
p = multiprocessing.Process(
target=_process_target_wrapper,
args=(
format_name,
version,
resolved_catalog_path,
surface_id,
completion,
return_dict,
),
)
p.start()
p.join(timeout=timeout_sec)
if p.is_alive():
p.kill()
p.join()
raise TimeoutError(
f"Format compilation timed out after {timeout_sec}s and process was"
" killed."
)

if "error" in return_dict:
raise ValueError(return_dict["error"])
if "result" not in return_dict:
raise ValueError("Compilation produced no output.")
return return_dict["result"]


@solver
def compile_format_payload(format_name: str, version: str) -> Solver:
"""Solver to compile format-specific output back to standard A2UI JSON."""
Expand All @@ -119,7 +221,6 @@ async def solve(state: TaskState, generate: Generate) -> TaskState:
catalog_path = state.metadata["catalog"]
resolved_catalog_path = str(GIT_ROOT / catalog_path)

catalog_config = CatalogConfig.from_path("basic_catalog", resolved_catalog_path)
completion = state.output.completion.strip()

allowed_surface_ids = state.metadata.get("allowed_surface_ids", ["main"])
Expand All @@ -136,37 +237,16 @@ async def solve(state: TaskState, generate: Generate) -> TaskState:
if found_id in allowed_surface_ids:
surface_id = found_id

strategy = _get_strategy(
format_name,
version,
catalog_config,
surface_id=surface_id,
)
catalog = (
strategy.get_selected_catalog()
if isinstance(strategy, TransportFormat)
else getattr(strategy, "catalog")
)
validator = catalog.validator

try:
parts = strategy.parser.parse_response(completion)
compiled_jsons = []
for p in parts:
a2ui_json = getattr(p, "a2ui_json", None)
if a2ui_json:
if isinstance(a2ui_json, list):
compiled_jsons.extend(a2ui_json)
else:
compiled_jsons.append(a2ui_json)

if not compiled_jsons:
raise ValueError(
f"No compiled A2UI {format_name} user interface found "
"in parsed parts."
)

validator.validate(compiled_jsons)
compiled_jsons = await asyncio.to_thread(
parse_with_hard_kill_timeout,
format_name,
version,
resolved_catalog_path,
surface_id,
completion,
timeout_sec=5.0,
)

formatted = (
f"<a2ui-json>\n{json.dumps(compiled_jsons, indent=2)}\n</a2ui-json>"
Expand Down
62 changes: 0 additions & 62 deletions eval/baselines/atom/run_meta.json

This file was deleted.

Loading
Loading