项目文件夹

文件
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

204 行
7.7 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
"""Track-2 failure-mode analysis over a finished run's per-case artifacts.
Read-only post-hoc analysis of ``run_dir/cases/*.json``. Answers the "where and
why does opensre lose?" questions the headline table can't, so the powered
full-corpus run turns into actionable next levers rather than a single number.
Four breakdowns, all scenario-clustered (seeds within a scenario averaged
first — the scenario is the independent unit):
1. Localization vs labeling — a1 (strict triple) vs object_a1 (right service)
vs partial_a1 (object+root_cause). The a1object_a1 gap is "right place,
wrong label"; the object_a1 deficit is "wrong place" (true mislocalization).
2. Per fault-category a1 — which fault families the agent fails on (the paper
reports Performance/Admission as universally hard).
3. Per system a1 — boutique (10 services) vs train-ticket (40 services); the
pilot showed train-ticket is the hard system (attention degrades at scale).
4. Control contrast — paired (opensre+llm llm_alone) and
(opensre+llm llm_alone_pure) deltas on a1, so any "opensre helps" claim
is attributable to the floor lever vs the full stack. Absent arms are
skipped gracefully (the pilot has only opensre+llm).
Usage:
python -m tests.benchmarks.cloudopsbench.failure_mode_analysis \
.bench-results/cloudopsbench_v1_openai/<run_id>/
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
from typing import Any
from tests.benchmarks._framework.reporting import (
_cell_category,
_cell_mode,
_cells_by_llm_mode,
_load_cells,
_paired_scenario_deltas,
_scenario_means,
)
_PRIMARY_MODE = "opensre+llm"
_CONTROL_MODES = ["llm_alone", "llm_alone_pure"]
def _mean(values: list[float]) -> float | None:
return sum(values) / len(values) if values else None
def _fmt(value: float | None) -> str:
return f"{value:.3f}" if value is not None else " - "
def _metric_by_case(cells: list[dict[str, Any]], metric: str) -> dict[str, list[float]]:
"""Group one metric by case_id (for paired right-place/wrong-label counts)."""
out: dict[str, list[float]] = {}
for cell in cells:
value = cell.get("score", {}).get("metrics", {}).get(metric)
if isinstance(value, (int, float)):
case_id = cell.get("case", {}).get("case_id", "(unknown)")
out.setdefault(case_id, []).append(float(value))
return out
def _cell_system(cell: dict[str, Any]) -> str:
return cell.get("case", {}).get("metadata", {}).get("system", "(unknown)")
def _primary_cells(cells: list[dict[str, Any]]) -> list[dict[str, Any]]:
return [c for c in cells if "_load_error" not in c and _cell_mode(c) == _PRIMARY_MODE]
def _localization_vs_labeling(cells: list[dict[str, Any]], llm: str) -> None:
print(f"\n## Localization vs labeling — {llm} ({_PRIMARY_MODE})")
print(f"{'metric':<12}{'mean':>8} interpretation")
print("-" * 60)
rows = [
("a1", "strict triple match (taxonomy+object+root_cause)"),
("object_a1", "right service localized (object only)"),
("partial_a1", "object + root_cause (taxonomy ignored)"),
]
for metric, desc in rows:
m = _mean(_scenario_means(cells, metric))
print(f"{metric:<12}{_fmt(m):>8} {desc}")
# Right-place / wrong-label: object correct but strict a1 wrong, per scenario.
a1_by_case = _metric_by_case(cells, "a1")
obj_by_case = _metric_by_case(cells, "object_a1")
right_place_wrong_label = 0
wrong_place = 0
total = 0
for case_id in a1_by_case.keys() & obj_by_case.keys():
a1 = sum(a1_by_case[case_id]) / len(a1_by_case[case_id])
obj = sum(obj_by_case[case_id]) / len(obj_by_case[case_id])
total += 1
if obj >= 0.5 and a1 < 0.5:
right_place_wrong_label += 1
elif obj < 0.5:
wrong_place += 1
if total:
print(
f"\n right place / wrong label: {right_place_wrong_label}/{total} scenarios "
f"({right_place_wrong_label / total:.0%}) — fix with a labeling lever"
)
print(
f" wrong place (mislocalized): {wrong_place}/{total} scenarios "
f"({wrong_place / total:.0%}) — fix with an exploration/coverage lever"
)
def _breakdown(cells: list[dict[str, Any]], llm: str, key_fn: Any, title: str) -> None:
print(f"\n## {title}{llm} ({_PRIMARY_MODE})")
groups: dict[str, list[dict[str, Any]]] = {}
for cell in cells:
groups.setdefault(key_fn(cell), []).append(cell)
print(f"{'group':<28}{'n':>5}{'a1':>8}{'object_a1':>11}{'cov':>8}{'steps':>8}")
print("-" * 68)
for name in sorted(groups):
grp = groups[name]
n_scen = len({c.get("case", {}).get("case_id") for c in grp})
a1 = _mean(_scenario_means(grp, "a1"))
obj = _mean(_scenario_means(grp, "object_a1"))
cov = _mean(_scenario_means(grp, "cov"))
steps = _mean(_scenario_means(grp, "steps"))
print(f"{name:<28}{n_scen:>5}{_fmt(a1):>8}{_fmt(obj):>11}{_fmt(cov):>8}{_fmt(steps):>8}")
def _control_contrast(cells: list[dict[str, Any]], llm: str) -> None:
print(f"\n## Control contrast — {llm} (paired scenario deltas on a1)")
modes_present = {_cell_mode(c) for c in cells if c.get("run", {}).get("llm") == llm}
if _PRIMARY_MODE not in modes_present:
print(" (no opensre+llm cells for this LLM — skipping)")
return
any_control = False
for control in _CONTROL_MODES:
if control not in modes_present:
print(f" vs {control:<16}: (arm not run)")
continue
any_control = True
deltas = _paired_scenario_deltas(cells, llm, "a1", _PRIMARY_MODE, control)
delta = _mean(deltas)
sign = "+" if (delta or 0) >= 0 else ""
meaning = {
"llm_alone": "lift from MIN_TOOL_CALLS floor alone",
"llm_alone_pure": "lift from the full opensre stack",
}.get(control, "")
print(
f" vs {control:<16}: {sign}{_fmt(delta)} over {len(deltas)} paired "
f"scenarios — {meaning}"
)
if not any_control:
print(
" (no control arms in this run — single-arm pilot; run the v1 "
"config's llm_alone / llm_alone_pure to attribute the lift)"
)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("run_dir", help="A finished run dir containing cases/.")
args = parser.parse_args(argv)
run_dir = Path(args.run_dir)
cases_dir = run_dir / "cases"
if not cases_dir.is_dir():
print(f" x {cases_dir} not found", file=sys.stderr)
return 1
all_cells = _load_cells(cases_dir)
by_llm_mode = _cells_by_llm_mode(all_cells)
if not by_llm_mode:
print(f" x no scorable cells under {cases_dir}", file=sys.stderr)
return 1
print(f"# Track-2 failure-mode analysis — {run_dir.name}")
print(
f"# {len([c for c in all_cells if '_load_error' not in c])} cells, "
f"{len(by_llm_mode)} LLM(s): {', '.join(sorted(by_llm_mode))}"
)
for llm in sorted(by_llm_mode):
llm_cells = [c for c in all_cells if c.get("run", {}).get("llm") == llm]
primary = _primary_cells(llm_cells)
if primary:
_localization_vs_labeling(primary, llm)
_breakdown(primary, llm, _cell_category, "Per fault-category")
_breakdown(primary, llm, _cell_system, "Per system")
_control_contrast(llm_cells, llm)
print(
"\n# Read: a1object_a1 gap = labeling problem (lever #4 cite/label); "
"low object_a1 = localization problem (coverage/exploration lever)."
)
return 0
if __name__ == "__main__":
sys.exit(main())