Files
wehub-resource-sync 426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

192 lines
6.9 KiB
Python

"""Feedback generation for the MINT benchmark.
Two modes:
* ``templated`` : deterministic, no network calls. Used for offline
smoke tests + ablation runs.
* ``llm`` : uses the runtime to call a language model (the paper
uses GPT-4). The prompt template is the same one
shipped with upstream MINT
(``upstream/mint/prompt/templates/template_feedback_agent.txt``)
so the resulting feedback shape matches the paper.
Pass ``use_llm=True`` and a compatible runtime to switch modes. The runtime
must satisfy the ``ModelRuntime`` protocol used elsewhere in this package
(``runtime.use_model(...)``).
"""
from __future__ import annotations
import logging
from pathlib import Path
from typing import Optional, Protocol, runtime_checkable
from benchmarks.mint.types import MINTTask
logger = logging.getLogger(__name__)
_UPSTREAM_TEMPLATE_PATH = (
Path(__file__).resolve().parent
/ "upstream"
/ "mint"
/ "prompt"
/ "templates"
/ "template_feedback_agent.txt"
)
@runtime_checkable
class ModelRuntime(Protocol):
async def use_model(
self,
model_type: object,
params: dict[str, object] | None = None,
**kwargs: object,
) -> object:
...
class FeedbackGenerator:
"""Generate feedback between MINT turns.
Defaults to the templated (offline) path. Pass ``use_llm=True`` together
with a ``runtime`` to use the upstream GPT-4 prompt.
"""
def __init__(
self,
runtime: object | None = None,
use_llm: bool = False,
feedback_model: str = "gpt-4",
mode: Optional[str] = None,
feedback_form: str = "textual",
reveal_ground_truth: bool = False,
) -> None:
self.runtime = runtime if isinstance(runtime, ModelRuntime) else None
if mode is not None:
self.mode = mode
else:
self.mode = "llm" if (use_llm and self.runtime is not None) else "templated"
self.feedback_model = feedback_model
self.feedback_form = feedback_form # "textual" or "binary"
self.reveal_ground_truth = bool(reveal_ground_truth)
self._template: Optional[str] = None
# ------------------------------------------------------------------
@property
def template(self) -> str:
if self._template is None:
try:
self._template = _UPSTREAM_TEMPLATE_PATH.read_text(encoding="utf-8")
except OSError as exc:
logger.warning(
"[FeedbackGenerator] Upstream template missing (%s); "
"falling back to inline template.",
exc,
)
self._template = (
"You are an expert tasked with evaluating and providing "
"feedback on an assistant's performance.\n\n"
"{trajectory}\n\n{correct_solution}\n\n"
"Please provide concise constructive feedback without "
"revealing the answer.\nExpert feedback:"
)
return self._template
# ------------------------------------------------------------------
async def generate(
self,
task: MINTTask,
predicted: str,
turn_num: int,
) -> str:
if self.mode == "llm" and self.runtime is not None:
text = await self._generate_llm(task, predicted, turn_num)
if text:
return text
logger.info(
"[FeedbackGenerator] LLM feedback failed; falling back to template."
)
return self._templated(task)
async def _generate_llm(
self, task: MINTTask, predicted: str, turn_num: int
) -> Optional[str]:
prompt = self._build_llm_prompt(task, predicted, turn_num)
try:
response = await self.runtime.use_model(
self.feedback_model,
{"prompt": prompt, "temperature": 0.0, "max_tokens": 1024},
)
text = (getattr(response, "text", None) or str(response)).strip()
if self.feedback_form == "binary":
# Mirror upstream OpenAIFeedbackAgent: extract GOOD/BAD from
# the first sentence.
first = text.split(".", 1)[0]
if "GOOD" in first.upper():
return "This is GOOD."
if "BAD" in first.upper():
return "This is BAD."
return text or None
except Exception as exc:
logger.warning("[FeedbackGenerator] LLM feedback raised %s", exc)
return None
def _build_llm_prompt(
self, task: MINTTask, predicted: str, turn_num: int
) -> str:
trajectory = (
f"Task:\n{task.initial_prompt}\n\n"
f"Assistant attempt (turn {turn_num + 1}):\n{predicted or '<no answer>'}\n"
)
if self.reveal_ground_truth:
correct = (
"Correct solution (please DO NOT disclose the correct "
f"solution to the assistant): {task.ground_truth}\n"
)
else:
correct = (
"Correct solution (please DO NOT disclose the correct "
"solution to the assistant): NOT GIVEN\n"
)
# ``in_context_example`` and ``tool_desc`` slots are kept empty here
# because the local agent does not yet thread the upstream in-context
# examples through; the template still renders sensibly because both
# slots are documented as optional.
return self.template.format(
in_context_example="",
tool_desc="",
trajectory=trajectory,
correct_solution=correct,
)
def _templated(self, task: MINTTask) -> str:
metric = task.evaluation_metric
if metric == "numeric":
return (
"Check the arithmetic carefully and provide only the final "
"number wrapped in `Final answer:`."
)
if metric in {"code_test", "code_output"}:
return (
"Run or reason through the code path, satisfy the test "
"harness, and provide the exact output."
)
if metric == "multiple_choice":
return (
"Pick the option whose content matches the question; answer "
"with a single letter (a/b/c/d) prefixed with `Final answer:`."
)
if metric == "theoremqa":
return (
"Identify the underlying theorem, compute the requested "
"quantity, and reply with a number, list, or boolean only."
)
if metric == "partial_match":
return (
"Compare the expected format with your answer and include "
"the key expected parts."
)
return "Re-read the question and answer in the requested final format."