mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-08-28 05:25:04 +00:00
Some checks are pending
Pre-commit / run (ubuntu-latest) (push) Waiting to run
Tests ReMe / Unit Tests - py3.11 (push) Waiting to run
Tests ReMe / Unit Tests - py3.12 (push) Waiting to run
Tests ReMe / Unit Tests - py3.13 (push) Waiting to run
Windows Smoke / CLI smoke - py3.11 (push) Waiting to run
* feat(counter): extend counter tree utils and record job call statistics - replace global_counter_next with fetch-and-add style global_counter_add/inc, plus read-only global_counter_get and global_counter_get_all - record per-job call counts in app_context.metadata via BaseJob._record_call, covering background/cron/stream jobs - update agentic_answer step and utils exports; add unit tests for job counting and counter utils * feat(evaluation): add check_job_count interface and report search calls in benchmarks - Extract _counter_key from BaseJob._record_call for reusable counter lookup - Add reme.utils.evaluation_interface.check_job_count read-only helper - Track and report average search calls per query in beam and longmemeval benchmarks * job counter * token消耗量统计 * benchmark输出完整token消耗统计 * benchmark统计输出改用标准差 - beam/longmemeval 的工具调用与 token 统计由方差改为标准差输出 - 修复 lint: 局部变量遮蔽 importlib.metadata、补充测试 docstring - black 格式化 * fix(evaluation): preserve complete token usage metrics * fix: exclude stream replies from token accounting * Revert "fix: exclude stream replies from token accounting" This reverts commit85bf32064d. * Reapply "fix: exclude stream replies from token accounting" This reverts commit6722c24dc5. * support agent scope 2.0.5 * feat: support injection_config to disable runtime state injection in benchmarks - Add InjectionConfig passthrough in AsAgentWrapper.reply() - Disable inject_runtime_state in BaseAgenticAnswerStep to avoid wall-clock time conflicting with benchmark query_time anchors - Disable inject_runtime_state in beam/lme llm_judge calls * feat: agentscope dual-version compat & benchmark improvements - Add version_tuple utility for semantic version comparison - AsAgentWrapper: version-aware InjectionConfig, max_iters doubling, and token usage collection (reply vs reply_stream) for AS>=2.0.5/<2.0.5 - Default inject_runtime_state=False in wrapper to avoid benchmark time-anchor conflicts; remove per-callsite injection_config overrides - longmemeval run.py: support question_ids filter in dataset config - Fix unused import in test_evaluation_interface; format fixes * chore: remove temporary flip-test benchmark config * revert: pin agentscope to 2.0.4.post1 and drop dual-version compat * fix(evaluation): clarify usage semantics and atomic counters --------- Co-authored-by: sa-buc <jiangniurou.xyf@dail-algo011164204033.ET135> Co-authored-by: jinli.yl <jinli.yl@alibaba-inc.com>
142 lines
4.6 KiB
Python
142 lines
4.6 KiB
Python
"""Tests for read-only job execution count evaluation helpers."""
|
|
|
|
import asyncio
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from reme.components.job import BaseJob, StreamJob
|
|
from reme.utils import global_counter_add
|
|
from reme.utils.evaluation_interface import (
|
|
check_agent_token_count,
|
|
check_job_count,
|
|
track_agent_token_usage,
|
|
track_agent_token_counts,
|
|
track_job_counts,
|
|
)
|
|
|
|
|
|
def test_check_job_count_reads_registered_base_job_count():
|
|
"""check_job_count returns the number of completed BaseJob invocations."""
|
|
|
|
async def run():
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
job = BaseJob(name="search", app_context=app_context)
|
|
app_context.jobs[job.name] = job
|
|
|
|
await job()
|
|
await job()
|
|
|
|
assert check_job_count("search", app_context) == 2
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
def test_check_job_count_reads_custom_job_by_name():
|
|
"""check_job_count reads subclassed job counters without depending on inheritance."""
|
|
|
|
async def run():
|
|
class ProjectStreamJob(StreamJob):
|
|
"""Project-specific StreamJob subclass used to exercise MRO lookup."""
|
|
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
job = ProjectStreamJob(name="chat", app_context=app_context)
|
|
app_context.jobs[job.name] = job
|
|
|
|
await job(stream_queue=asyncio.Queue())
|
|
|
|
assert check_job_count("chat", app_context) == 1
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
def test_check_job_count_rejects_unknown_job_name():
|
|
"""Unknown job names raise KeyError, matching Application.run_job."""
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
|
|
with pytest.raises(KeyError, match="Job 'missing' not found"):
|
|
check_job_count("missing", app_context)
|
|
|
|
|
|
def test_track_job_counts_returns_calls_made_inside_context():
|
|
"""The context manager reports only the calls made in its body."""
|
|
|
|
async def run():
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
search = BaseJob(name="search", app_context=app_context)
|
|
app_context.jobs[search.name] = search
|
|
|
|
await search()
|
|
with track_job_counts(["search"], app_context) as counts:
|
|
await search()
|
|
await search()
|
|
|
|
assert counts == {"search": 2}
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
def test_track_job_counts_updates_results_when_body_raises():
|
|
"""Calls made before an exception are still included in the delta."""
|
|
|
|
async def run():
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
search = BaseJob(name="search", app_context=app_context)
|
|
app_context.jobs[search.name] = search
|
|
counts = {}
|
|
|
|
with pytest.raises(RuntimeError, match="boom"):
|
|
with track_job_counts(["search"], app_context) as counts:
|
|
await search()
|
|
raise RuntimeError("boom")
|
|
|
|
assert counts == {"search": 1}
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
def test_track_agent_token_counts_returns_delta_for_one_agent():
|
|
"""Token tracking mirrors job-count tracking over the token counter tree."""
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
global_counter_add(app_context.metadata, ["__token_counter", "bench", "total_tokens"], 10)
|
|
|
|
with track_agent_token_counts(["bench"], app_context) as counts:
|
|
global_counter_add(app_context.metadata, ["__token_counter", "bench", "total_tokens"], 25)
|
|
|
|
assert counts == {"bench": 25}
|
|
assert check_agent_token_count("bench", app_context) == 35
|
|
|
|
|
|
def test_track_agent_token_usage_reports_only_supported_metrics():
|
|
"""Detailed usage tracking reports the shared input/output contract."""
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
for metric, value in (("input_tokens", 10), ("output_tokens", 5), ("total_tokens", 15)):
|
|
global_counter_add(app_context.metadata, ["__token_counter", "bench", metric], value)
|
|
|
|
with track_agent_token_usage(["bench"], app_context) as usages:
|
|
for metric, value in (("input_tokens", 20), ("output_tokens", 7), ("total_tokens", 27)):
|
|
global_counter_add(app_context.metadata, ["__token_counter", "bench", metric], value)
|
|
|
|
assert usages == {
|
|
"bench": {
|
|
"input_tokens": 20,
|
|
"output_tokens": 7,
|
|
"total_tokens": 27,
|
|
},
|
|
}
|
|
|
|
|
|
def test_track_agent_token_usage_keeps_unavailable_usage_as_none():
|
|
"""A backend that reports no usage remains unavailable to benchmarks."""
|
|
app_context = SimpleNamespace(metadata={}, jobs={})
|
|
|
|
with track_agent_token_usage(["bench"], app_context) as usages:
|
|
pass
|
|
|
|
assert usages == {
|
|
"bench": {
|
|
"input_tokens": None,
|
|
"output_tokens": None,
|
|
"total_tokens": None,
|
|
},
|
|
}
|