world-model-optimizer 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llm_waterfall/LICENSE +21 -0
- llm_waterfall/__init__.py +53 -0
- llm_waterfall/adapters/__init__.py +36 -0
- llm_waterfall/adapters/anthropic.py +105 -0
- llm_waterfall/adapters/aws_mantle.py +47 -0
- llm_waterfall/adapters/azure_openai.py +71 -0
- llm_waterfall/adapters/base.py +51 -0
- llm_waterfall/adapters/bedrock.py +309 -0
- llm_waterfall/adapters/openai.py +130 -0
- llm_waterfall/classify.py +184 -0
- llm_waterfall/pricing.py +110 -0
- llm_waterfall/py.typed +0 -0
- llm_waterfall/types.py +295 -0
- llm_waterfall/waterfall.py +255 -0
- wmo/__init__.py +38 -0
- wmo/agents/__init__.py +7 -0
- wmo/agents/default.py +29 -0
- wmo/agents/meta.py +55 -0
- wmo/agents/optimizer.py +55 -0
- wmo/agents/project.py +928 -0
- wmo/cli/__init__.py +5 -0
- wmo/cli/agent_session.py +1123 -0
- wmo/cli/app.py +2489 -0
- wmo/cli/e2b_cmds.py +212 -0
- wmo/cli/eval_closed_loop.py +207 -0
- wmo/cli/harness_app.py +1147 -0
- wmo/cli/harness_distill.py +659 -0
- wmo/cli/hosted_session.py +880 -0
- wmo/cli/ingest_cmd.py +165 -0
- wmo/cli/model_roles.py +82 -0
- wmo/cli/platform_cmds.py +372 -0
- wmo/cli/route_app.py +274 -0
- wmo/cli/session_state.py +243 -0
- wmo/cli/ui.py +1107 -0
- wmo/cli/workspace_sync.py +504 -0
- wmo/config/__init__.py +60 -0
- wmo/config/card.py +129 -0
- wmo/config/config.py +367 -0
- wmo/config/dotenv.py +67 -0
- wmo/config/settings.py +128 -0
- wmo/config/store.py +177 -0
- wmo/conftest.py +19 -0
- wmo/connect/__init__.py +88 -0
- wmo/connect/apps.py +78 -0
- wmo/connect/brave.py +284 -0
- wmo/connect/connector.py +79 -0
- wmo/connect/credentials.py +164 -0
- wmo/connect/github.py +321 -0
- wmo/connect/google.py +627 -0
- wmo/connect/notion.py +790 -0
- wmo/connect/oauth.py +461 -0
- wmo/connect/slack.py +555 -0
- wmo/connect/store.py +199 -0
- wmo/connect/types.py +156 -0
- wmo/core/__init__.py +21 -0
- wmo/core/parsing.py +281 -0
- wmo/core/render.py +271 -0
- wmo/core/text.py +40 -0
- wmo/core/types.py +116 -0
- wmo/distill/__init__.py +14 -0
- wmo/distill/agents.py +140 -0
- wmo/distill/config.py +1006 -0
- wmo/distill/cost.py +437 -0
- wmo/distill/data.py +921 -0
- wmo/distill/deadlines.py +254 -0
- wmo/distill/fake_tinker.py +734 -0
- wmo/distill/gate.py +122 -0
- wmo/distill/loop.py +3499 -0
- wmo/distill/renderers.py +399 -0
- wmo/distill/rendering.py +620 -0
- wmo/distill/rollouts.py +726 -0
- wmo/distill/samples.py +195 -0
- wmo/distill/store.py +829 -0
- wmo/distill/teacher.py +714 -0
- wmo/distill/tokens.py +535 -0
- wmo/distill/tracking.py +552 -0
- wmo/distill/tripwire.py +411 -0
- wmo/distill/xtoken/byte_offsets.py +152 -0
- wmo/distill/xtoken/chunks.py +457 -0
- wmo/distill/xtoken/prompt_logprobs.py +475 -0
- wmo/distill/xtoken/teacher_render.py +346 -0
- wmo/engine/__init__.py +28 -0
- wmo/engine/autoconfig.py +367 -0
- wmo/engine/build.py +346 -0
- wmo/engine/demo.py +77 -0
- wmo/engine/eval_suites.py +245 -0
- wmo/engine/grounding.py +491 -0
- wmo/engine/knowledge.py +291 -0
- wmo/engine/loader.py +36 -0
- wmo/engine/play.py +92 -0
- wmo/engine/prompts.py +99 -0
- wmo/engine/replay.py +443 -0
- wmo/engine/reporting.py +58 -0
- wmo/engine/workspace.py +468 -0
- wmo/engine/world_model.py +568 -0
- wmo/env/__init__.py +22 -0
- wmo/env/base.py +121 -0
- wmo/env/closed_loop.py +229 -0
- wmo/env/episode.py +107 -0
- wmo/env/llm_agent.py +93 -0
- wmo/env/scenarios.py +73 -0
- wmo/evals/__init__.py +52 -0
- wmo/evals/agreement.py +110 -0
- wmo/evals/base.py +45 -0
- wmo/evals/closed_loop.py +480 -0
- wmo/evals/failover.py +96 -0
- wmo/evals/gold.py +127 -0
- wmo/evals/grid.py +394 -0
- wmo/evals/grid_plot.py +205 -0
- wmo/evals/harbor/__init__.py +27 -0
- wmo/evals/harbor/agent.py +573 -0
- wmo/evals/harbor/ctrf.py +171 -0
- wmo/evals/harbor/e2b_environment.py +587 -0
- wmo/evals/harbor/e2b_template_policy.py +144 -0
- wmo/evals/harbor/scorer.py +875 -0
- wmo/evals/harbor/tasks.py +140 -0
- wmo/evals/open_loop.py +194 -0
- wmo/evals/tasks.py +53 -0
- wmo/harness/__init__.py +51 -0
- wmo/harness/code_runtime.py +288 -0
- wmo/harness/create.py +1191 -0
- wmo/harness/delta.py +220 -0
- wmo/harness/doc.py +556 -0
- wmo/harness/e2b_ledger.py +342 -0
- wmo/harness/e2b_reap.py +476 -0
- wmo/harness/e2b_sandbox.py +350 -0
- wmo/harness/environment.py +35 -0
- wmo/harness/live_session.py +543 -0
- wmo/harness/mutate.py +343 -0
- wmo/harness/pi_e2b.py +1710 -0
- wmo/harness/pi_entry/entry.ts +268 -0
- wmo/harness/pi_entry/runner_frames.ts +92 -0
- wmo/harness/pi_entry/runner_live.ts +587 -0
- wmo/harness/pi_entry/runner_service.ts +270 -0
- wmo/harness/pi_entry/runner_stdio.ts +374 -0
- wmo/harness/pi_entry/runner_termination.ts +142 -0
- wmo/harness/pi_local.py +262 -0
- wmo/harness/pi_runtime.py +495 -0
- wmo/harness/pi_vendor.py +65 -0
- wmo/harness/population.py +509 -0
- wmo/harness/project_proposer.py +569 -0
- wmo/harness/proposer.py +977 -0
- wmo/harness/runner_link.py +619 -0
- wmo/harness/runtime.py +389 -0
- wmo/harness/scoring.py +247 -0
- wmo/harness/skills.py +116 -0
- wmo/harness/source_tree.py +319 -0
- wmo/harness/store.py +176 -0
- wmo/harness/tools.py +105 -0
- wmo/harness/vendor/manifest.sha256 +58 -0
- wmo/harness/vendor/pi-agent/CHANGELOG.md +556 -0
- wmo/harness/vendor/pi-agent/LICENSE +21 -0
- wmo/harness/vendor/pi-agent/README.md +488 -0
- wmo/harness/vendor/pi-agent/VENDOR.md +39 -0
- wmo/harness/vendor/pi-agent/docs/agent-harness.md +486 -0
- wmo/harness/vendor/pi-agent/docs/durable-harness.md +212 -0
- wmo/harness/vendor/pi-agent/docs/hooks.md +445 -0
- wmo/harness/vendor/pi-agent/docs/models.md +966 -0
- wmo/harness/vendor/pi-agent/docs/observability.md +376 -0
- wmo/harness/vendor/pi-agent/package.json +60 -0
- wmo/harness/vendor/pi-agent/src/agent-loop.ts +748 -0
- wmo/harness/vendor/pi-agent/src/agent.ts +575 -0
- wmo/harness/vendor/pi-agent/src/harness/agent-harness.ts +1029 -0
- wmo/harness/vendor/pi-agent/src/harness/compaction/branch-summarization.ts +261 -0
- wmo/harness/vendor/pi-agent/src/harness/compaction/compaction.ts +747 -0
- wmo/harness/vendor/pi-agent/src/harness/compaction/utils.ts +144 -0
- wmo/harness/vendor/pi-agent/src/harness/env/nodejs.ts +550 -0
- wmo/harness/vendor/pi-agent/src/harness/messages.ts +164 -0
- wmo/harness/vendor/pi-agent/src/harness/prompt-templates.ts +267 -0
- wmo/harness/vendor/pi-agent/src/harness/session/jsonl-repo.ts +177 -0
- wmo/harness/vendor/pi-agent/src/harness/session/jsonl-storage.ts +293 -0
- wmo/harness/vendor/pi-agent/src/harness/session/memory-repo.ts +50 -0
- wmo/harness/vendor/pi-agent/src/harness/session/memory-storage.ts +131 -0
- wmo/harness/vendor/pi-agent/src/harness/session/repo-utils.ts +51 -0
- wmo/harness/vendor/pi-agent/src/harness/session/session.ts +267 -0
- wmo/harness/vendor/pi-agent/src/harness/session/uuid.ts +54 -0
- wmo/harness/vendor/pi-agent/src/harness/skills.ts +375 -0
- wmo/harness/vendor/pi-agent/src/harness/system-prompt.ts +34 -0
- wmo/harness/vendor/pi-agent/src/harness/types.ts +836 -0
- wmo/harness/vendor/pi-agent/src/harness/utils/shell-output.ts +135 -0
- wmo/harness/vendor/pi-agent/src/harness/utils/truncate.ts +344 -0
- wmo/harness/vendor/pi-agent/src/index.ts +44 -0
- wmo/harness/vendor/pi-agent/src/node.ts +2 -0
- wmo/harness/vendor/pi-agent/src/proxy.ts +367 -0
- wmo/harness/vendor/pi-agent/src/types.ts +428 -0
- wmo/harness/vendor/pi-agent/test/agent-loop.test.ts +1351 -0
- wmo/harness/vendor/pi-agent/test/agent.test.ts +699 -0
- wmo/harness/vendor/pi-agent/test/e2e.test.ts +404 -0
- wmo/harness/vendor/pi-agent/test/harness/agent-harness-stream.test.ts +213 -0
- wmo/harness/vendor/pi-agent/test/harness/agent-harness.test.ts +608 -0
- wmo/harness/vendor/pi-agent/test/harness/compaction.test.ts +655 -0
- wmo/harness/vendor/pi-agent/test/harness/nodejs-env.test.ts +321 -0
- wmo/harness/vendor/pi-agent/test/harness/prompt-templates.test.ts +90 -0
- wmo/harness/vendor/pi-agent/test/harness/repo.test.ts +68 -0
- wmo/harness/vendor/pi-agent/test/harness/resource-formatting.test.ts +24 -0
- wmo/harness/vendor/pi-agent/test/harness/session-test-utils.ts +55 -0
- wmo/harness/vendor/pi-agent/test/harness/session-uuid.test.ts +50 -0
- wmo/harness/vendor/pi-agent/test/harness/session.test.ts +156 -0
- wmo/harness/vendor/pi-agent/test/harness/skills.test.ts +116 -0
- wmo/harness/vendor/pi-agent/test/harness/storage.test.ts +299 -0
- wmo/harness/vendor/pi-agent/test/harness/system-prompt.test.ts +66 -0
- wmo/harness/vendor/pi-agent/test/harness/truncate.test.ts +169 -0
- wmo/harness/vendor/pi-agent/test/scratch/simple.ts +72 -0
- wmo/harness/vendor/pi-agent/test/utils/calculate.ts +32 -0
- wmo/harness/vendor/pi-agent/test/utils/get-current-time.ts +46 -0
- wmo/harness/vendor/pi-agent/tsconfig.build.json +13 -0
- wmo/harness/vendor/pi-agent/vitest.config.ts +19 -0
- wmo/harness/vendor/pi-agent/vitest.harness.config.ts +28 -0
- wmo/harness/vendor/vendor_pi.sh +59 -0
- wmo/harness/workspace_patch.py +270 -0
- wmo/ingest/__init__.py +47 -0
- wmo/ingest/adapter.py +72 -0
- wmo/ingest/base.py +114 -0
- wmo/ingest/braintrust.py +339 -0
- wmo/ingest/detect.py +126 -0
- wmo/ingest/langfuse.py +291 -0
- wmo/ingest/langsmith.py +444 -0
- wmo/ingest/mastra.py +330 -0
- wmo/ingest/messages.py +170 -0
- wmo/ingest/normalize.py +679 -0
- wmo/ingest/otel_genai.py +69 -0
- wmo/ingest/otel_writer.py +100 -0
- wmo/ingest/phoenix.py +150 -0
- wmo/ingest/postgres.py +246 -0
- wmo/ingest/posthog.py +320 -0
- wmo/ingest/quality.py +28 -0
- wmo/ingest/stream.py +209 -0
- wmo/ingest/testdata/sample_otlp.json +60 -0
- wmo/ingest/testdata/sample_spans.jsonl +3 -0
- wmo/optimize/__init__.py +25 -0
- wmo/optimize/base.py +143 -0
- wmo/optimize/gepa.py +806 -0
- wmo/optimize/judge.py +262 -0
- wmo/optimize/judge_quality.py +359 -0
- wmo/optimize/knn.py +468 -0
- wmo/optimize/numeric.py +152 -0
- wmo/optimize/outcomes.py +103 -0
- wmo/optimize/policy.py +669 -0
- wmo/optimize/report.py +231 -0
- wmo/optimize/reward.py +129 -0
- wmo/optimize/routing.py +373 -0
- wmo/platform/__init__.py +6 -0
- wmo/platform/auth.py +115 -0
- wmo/platform/client.py +551 -0
- wmo/platform/credentials.py +126 -0
- wmo/platform/transfer.py +158 -0
- wmo/providers/__init__.py +40 -0
- wmo/providers/_bedrock_chat.py +155 -0
- wmo/providers/_openai_common.py +182 -0
- wmo/providers/_responses_common.py +472 -0
- wmo/providers/anthropic.py +134 -0
- wmo/providers/azure_openai.py +296 -0
- wmo/providers/base.py +300 -0
- wmo/providers/bedrock.py +312 -0
- wmo/providers/models.py +205 -0
- wmo/providers/openai.py +143 -0
- wmo/providers/openai_responses.py +240 -0
- wmo/providers/pool.py +170 -0
- wmo/providers/registry.py +73 -0
- wmo/providers/retry.py +151 -0
- wmo/providers/tinker.py +936 -0
- wmo/providers/waterfall.py +336 -0
- wmo/research/__init__.py +81 -0
- wmo/research/ablation.py +133 -0
- wmo/research/concurrency_plot.py +523 -0
- wmo/research/concurrency_run.py +240 -0
- wmo/research/concurrency_scaling.py +270 -0
- wmo/research/gepa_scaling.py +274 -0
- wmo/research/pipeline.py +198 -0
- wmo/research/scaling_split.py +82 -0
- wmo/research/scenario_fidelity.py +198 -0
- wmo/research/scenario_recovery.py +92 -0
- wmo/research/seed_stability.py +90 -0
- wmo/research/trace_scaling.py +348 -0
- wmo/retrieval/__init__.py +6 -0
- wmo/retrieval/embedders.py +105 -0
- wmo/retrieval/leakfree.py +52 -0
- wmo/retrieval/retriever.py +173 -0
- wmo/scenarios/__init__.py +58 -0
- wmo/scenarios/builder.py +152 -0
- wmo/scenarios/mining/__init__.py +27 -0
- wmo/scenarios/mining/clustering.py +171 -0
- wmo/scenarios/mining/facets.py +226 -0
- wmo/scenarios/mining/selection.py +220 -0
- wmo/scenarios/synthesis/__init__.py +6 -0
- wmo/scenarios/synthesis/scenario_set.py +63 -0
- wmo/scenarios/synthesis/synthesizer.py +85 -0
- wmo/scenarios/verification/__init__.py +17 -0
- wmo/scenarios/verification/judge.py +97 -0
- wmo/scenarios/verification/verify.py +135 -0
- wmo/serving/__init__.py +5 -0
- wmo/serving/builds.py +451 -0
- wmo/serving/chat.py +878 -0
- wmo/serving/endpoint_config.py +64 -0
- wmo/serving/savings.py +250 -0
- wmo/serving/server.py +553 -0
- wmo/serving/traces_source.py +206 -0
- wmo/telemetry.py +213 -0
- wmo/tracking/__init__.py +36 -0
- wmo/tracking/clock.py +24 -0
- wmo/tracking/metered.py +125 -0
- wmo/tracking/pricing.py +99 -0
- wmo/tracking/store.py +31 -0
- wmo/tracking/tracker.py +149 -0
- world_model_optimizer-0.2.0.dist-info/METADATA +203 -0
- world_model_optimizer-0.2.0.dist-info/RECORD +308 -0
- world_model_optimizer-0.2.0.dist-info/WHEEL +4 -0
- world_model_optimizer-0.2.0.dist-info/entry_points.txt +2 -0
wmo/evals/grid_plot.py
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Render a `GridResult` as the World-Model Optimizer fidelity bar chart.
|
|
2
|
+
|
|
3
|
+
One vertical bar per (model x condition) cell, sorted ASCENDING by fidelity left->right, each
|
|
4
|
+
labeled with its fidelity and (when priced) its target-side cost. Matplotlib/seaborn live behind
|
|
5
|
+
the `viz` extra, so this module imports them lazily inside the function - the only sanctioned lazy
|
|
6
|
+
import here (the engine must import without the plotting deps installed).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from wmo.evals.grid import CONDITIONS, GridResult
|
|
14
|
+
|
|
15
|
+
_TITLE = "World-Model Optimizer Fidelity"
|
|
16
|
+
|
|
17
|
+
# Brand palette (AGENTS.md rule 15) - no ad-hoc colors. Ink for text/lines, a light gridline, and
|
|
18
|
+
# one brand hue per condition so a bar's color reads its condition regardless of sorted position.
|
|
19
|
+
_INK = "#0a0a0a"
|
|
20
|
+
_GRIDLINE = "#ececec"
|
|
21
|
+
_BRAND_BY_CONDITION = {
|
|
22
|
+
"base": _INK, # baseline is neutral; the wmo conditions carry the brand hues
|
|
23
|
+
"base_rag": "#0070f3", # blue
|
|
24
|
+
"gepa": "#7928ca", # purple
|
|
25
|
+
"gepa_rag": "#f5a623", # amber
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def plot_grid(
|
|
30
|
+
result: GridResult,
|
|
31
|
+
out_path: str | Path,
|
|
32
|
+
*,
|
|
33
|
+
dataset_label: str,
|
|
34
|
+
n_test_traces: int,
|
|
35
|
+
) -> Path:
|
|
36
|
+
"""Write the fidelity barplot for `result` to `out_path` (PNG). Returns the path.
|
|
37
|
+
|
|
38
|
+
`dataset_label`/`n_test_traces` populate the subtitle, e.g.
|
|
39
|
+
"armand0e/qwen3.7-max-pi-traces | 8 held-out test traces | 225 judged steps".
|
|
40
|
+
"""
|
|
41
|
+
import matplotlib
|
|
42
|
+
|
|
43
|
+
matplotlib.use("Agg") # headless: write a file, never open a window
|
|
44
|
+
import matplotlib.pyplot as plt
|
|
45
|
+
import seaborn as sns
|
|
46
|
+
|
|
47
|
+
cells = sorted(result.cells, key=lambda c: c.fidelity) # ascending performance, left -> right
|
|
48
|
+
if not cells:
|
|
49
|
+
raise ValueError("grid result has no cells to plot")
|
|
50
|
+
labels = [c.bar_label for c in cells]
|
|
51
|
+
heights = [c.fidelity for c in cells]
|
|
52
|
+
colors = [_BRAND_BY_CONDITION.get(c.condition, _INK) for c in cells]
|
|
53
|
+
|
|
54
|
+
sns.set_theme(style="whitegrid", context="talk")
|
|
55
|
+
fig, ax = plt.subplots(figsize=(max(8, 1.6 * len(cells)), 6.5))
|
|
56
|
+
ax.grid(axis="y", color=_GRIDLINE)
|
|
57
|
+
ax.set_axisbelow(True)
|
|
58
|
+
bars = ax.bar(range(len(cells)), heights, color=colors, edgecolor="white", linewidth=0.8)
|
|
59
|
+
|
|
60
|
+
# Per-bar text: fidelity on top, target cost above it (omit the $ line when cost is None).
|
|
61
|
+
for bar, cell in zip(bars, cells, strict=True):
|
|
62
|
+
x = bar.get_x() + bar.get_width() / 2
|
|
63
|
+
top = bar.get_height()
|
|
64
|
+
ax.text(x, top + 0.012, f"{cell.fidelity:.3f}", ha="center", va="bottom", fontsize=11)
|
|
65
|
+
if cell.cost_usd is not None and cell.cost_usd > 0:
|
|
66
|
+
ax.text(
|
|
67
|
+
x,
|
|
68
|
+
top + 0.052,
|
|
69
|
+
f"${cell.cost_usd:.2f}",
|
|
70
|
+
ha="center",
|
|
71
|
+
va="bottom",
|
|
72
|
+
fontsize=10,
|
|
73
|
+
color=_INK,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# One legend entry per condition present, in canonical order, using the same brand hues.
|
|
77
|
+
seen = {c.condition: c.condition_label for c in cells}
|
|
78
|
+
handles = [
|
|
79
|
+
plt.Rectangle((0, 0), 1, 1, color=_BRAND_BY_CONDITION.get(cond, _INK))
|
|
80
|
+
for cond in CONDITIONS
|
|
81
|
+
if cond in seen
|
|
82
|
+
]
|
|
83
|
+
ax.legend(
|
|
84
|
+
handles,
|
|
85
|
+
[seen[cond] for cond in CONDITIONS if cond in seen],
|
|
86
|
+
title="condition",
|
|
87
|
+
frameon=False,
|
|
88
|
+
fontsize=10,
|
|
89
|
+
title_fontsize=10,
|
|
90
|
+
loc="upper left",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
ax.set_xticks(range(len(cells)))
|
|
94
|
+
ax.set_xticklabels(labels, fontsize=10)
|
|
95
|
+
ax.set_ylabel("Mean fidelity")
|
|
96
|
+
# Headroom above the tallest bar so the fidelity + cost labels never collide with the subtitle
|
|
97
|
+
# (near-ceiling bars at ~0.97 would otherwise push the $ label past y=1.0).
|
|
98
|
+
ax.set_ylim(0, max(1.0, max(heights) + 0.14))
|
|
99
|
+
ax.set_title(_TITLE, fontsize=17, fontweight="bold", pad=28)
|
|
100
|
+
subtitle = (
|
|
101
|
+
f"{dataset_label} | {n_test_traces} held-out test traces | "
|
|
102
|
+
f"{result.total_test_steps} judged steps | judge {result.judge_version}"
|
|
103
|
+
)
|
|
104
|
+
ax.text(
|
|
105
|
+
0.5,
|
|
106
|
+
1.02,
|
|
107
|
+
subtitle,
|
|
108
|
+
transform=ax.transAxes,
|
|
109
|
+
ha="center",
|
|
110
|
+
va="bottom",
|
|
111
|
+
fontsize=12,
|
|
112
|
+
color=_INK,
|
|
113
|
+
alpha=0.7,
|
|
114
|
+
)
|
|
115
|
+
sns.despine(ax=ax)
|
|
116
|
+
fig.tight_layout()
|
|
117
|
+
out = Path(out_path)
|
|
118
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
119
|
+
fig.savefig(out, dpi=150, bbox_inches="tight")
|
|
120
|
+
plt.close(fig)
|
|
121
|
+
return out
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def plot_grid_heatmap(
|
|
125
|
+
results: dict[str, GridResult],
|
|
126
|
+
out_path: str | Path,
|
|
127
|
+
*,
|
|
128
|
+
benchmark_order: list[str] | None = None,
|
|
129
|
+
) -> Path:
|
|
130
|
+
"""Render the whole grid as one heatmap: rows = model x condition, columns = benchmark.
|
|
131
|
+
|
|
132
|
+
`results` maps a benchmark label to its merged `GridResult` (all 5 models x 4 conditions). Each
|
|
133
|
+
cell is the mean fidelity, annotated and colored on a shared 0..1 scale so every benchmark reads
|
|
134
|
+
on the same footing. A model x condition with no cell for a benchmark is left blank (NaN).
|
|
135
|
+
Columns follow `benchmark_order` when given, else the dict's insertion order.
|
|
136
|
+
"""
|
|
137
|
+
import matplotlib
|
|
138
|
+
|
|
139
|
+
matplotlib.use("Agg") # headless
|
|
140
|
+
import matplotlib.pyplot as plt
|
|
141
|
+
import numpy as np
|
|
142
|
+
import seaborn as sns
|
|
143
|
+
from matplotlib.colors import LinearSegmentedColormap
|
|
144
|
+
|
|
145
|
+
if not results:
|
|
146
|
+
raise ValueError("no grid results to plot")
|
|
147
|
+
# Sequential brand ramp (light gridline -> brand blue -> brand purple) so higher fidelity reads
|
|
148
|
+
# darker/brand-er; seaborn auto-picks light/dark annotation text per cell luminance.
|
|
149
|
+
brand_cmap = LinearSegmentedColormap.from_list("wmo-brand", [_GRIDLINE, "#0070f3", "#7928ca"])
|
|
150
|
+
benchmarks = benchmark_order or list(results)
|
|
151
|
+
|
|
152
|
+
# Row order: models in first-seen order, each followed by its four conditions.
|
|
153
|
+
models: list[str] = []
|
|
154
|
+
labels: dict[str, str] = {}
|
|
155
|
+
for res in results.values():
|
|
156
|
+
for cell in res.cells:
|
|
157
|
+
if cell.model_label not in models:
|
|
158
|
+
models.append(cell.model_label)
|
|
159
|
+
labels.setdefault(cell.condition, cell.condition_label)
|
|
160
|
+
rows = [(m, c) for m in models for c in CONDITIONS]
|
|
161
|
+
|
|
162
|
+
# (model, condition, benchmark) -> fidelity lookup.
|
|
163
|
+
fid: dict[tuple[str, str, str], float] = {}
|
|
164
|
+
for bench, res in results.items():
|
|
165
|
+
for cell in res.cells:
|
|
166
|
+
fid[(cell.model_label, cell.condition, bench)] = cell.fidelity
|
|
167
|
+
|
|
168
|
+
matrix = np.full((len(rows), len(benchmarks)), np.nan)
|
|
169
|
+
for r, (model, cond) in enumerate(rows):
|
|
170
|
+
for c, bench in enumerate(benchmarks):
|
|
171
|
+
if (model, cond, bench) in fid:
|
|
172
|
+
matrix[r, c] = fid[(model, cond, bench)]
|
|
173
|
+
row_labels = [f"{m} · {labels.get(c, c)}" for m, c in rows]
|
|
174
|
+
|
|
175
|
+
sns.set_theme(style="white", context="talk")
|
|
176
|
+
fig, ax = plt.subplots(figsize=(1.7 * len(benchmarks) + 4, 0.42 * len(rows) + 2.2))
|
|
177
|
+
sns.heatmap(
|
|
178
|
+
matrix,
|
|
179
|
+
ax=ax,
|
|
180
|
+
cmap=brand_cmap,
|
|
181
|
+
vmin=0.0,
|
|
182
|
+
vmax=1.0,
|
|
183
|
+
annot=True,
|
|
184
|
+
fmt=".2f",
|
|
185
|
+
annot_kws={"fontsize": 9},
|
|
186
|
+
linewidths=0.6,
|
|
187
|
+
linecolor="white",
|
|
188
|
+
cbar_kws={"label": "Mean fidelity", "shrink": 0.6},
|
|
189
|
+
xticklabels=benchmarks,
|
|
190
|
+
yticklabels=row_labels,
|
|
191
|
+
)
|
|
192
|
+
# Separator lines between models (every 4 conditions) so the model blocks read as groups.
|
|
193
|
+
for i in range(len(CONDITIONS), len(rows), len(CONDITIONS)):
|
|
194
|
+
ax.axhline(i, color=_INK, linewidth=1.4)
|
|
195
|
+
judge_versions = sorted({r.judge_version for r in results.values()})
|
|
196
|
+
judge_tag = judge_versions[0] if len(judge_versions) == 1 else "/".join(judge_versions)
|
|
197
|
+
ax.set_title(f"{_TITLE}: full grid (judge {judge_tag})", fontsize=17, fontweight="bold", pad=16)
|
|
198
|
+
ax.tick_params(axis="y", labelsize=9, rotation=0)
|
|
199
|
+
ax.tick_params(axis="x", labelsize=11)
|
|
200
|
+
fig.tight_layout()
|
|
201
|
+
out = Path(out_path)
|
|
202
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
203
|
+
fig.savefig(out, dpi=150, bbox_inches="tight")
|
|
204
|
+
plt.close(fig)
|
|
205
|
+
return out
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Ground-truth harness evaluation through Harbor (optional `harbor` extra).
|
|
2
|
+
|
|
3
|
+
This subpackage imports the `harbor` PyPI package at module scope and is therefore imported
|
|
4
|
+
lazily by its consumers, exactly like the e2b extra: `import wmo` (and `wmo.evals`) must succeed
|
|
5
|
+
without it. The E2B task-environment path additionally needs the e2b extra and is itself only
|
|
6
|
+
imported through harbor's environment factory (`wmo.evals.harbor.e2b_environment`).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from wmo.evals.harbor.agent import WmoHarborAgent
|
|
10
|
+
from wmo.evals.harbor.scorer import (
|
|
11
|
+
HarborJobRunner,
|
|
12
|
+
HarborRewardMissingError,
|
|
13
|
+
HarborRun,
|
|
14
|
+
HarborRunner,
|
|
15
|
+
HarborScorer,
|
|
16
|
+
)
|
|
17
|
+
from wmo.evals.harbor.tasks import resolve_harbor_tasks
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"HarborJobRunner",
|
|
21
|
+
"HarborRewardMissingError",
|
|
22
|
+
"HarborRun",
|
|
23
|
+
"HarborRunner",
|
|
24
|
+
"HarborScorer",
|
|
25
|
+
"WmoHarborAgent",
|
|
26
|
+
"resolve_harbor_tasks",
|
|
27
|
+
]
|