mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-11-06 07:51:11 +00:00
revert: pin agentscope to 2.0.4.post1 and drop dual-version compat
This commit is contained in:
parent
e0f23720a1
commit
3291e5a434
5 changed files with 19 additions and 82 deletions
|
|
@ -42,7 +42,7 @@ dependencies = [
|
|||
|
||||
[project.optional-dependencies]
|
||||
core = [
|
||||
"agentscope==2.0.5",
|
||||
"agentscope==2.0.4.post1",
|
||||
"claude-agent-sdk>=0.2.126",
|
||||
"dingtalk-stream>=0.24.3",
|
||||
"openai-codex>=0.144.4",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ from pathlib import Path
|
|||
from typing import Any, TYPE_CHECKING
|
||||
from uuid import uuid4
|
||||
|
||||
import agentscope
|
||||
from agentscope.agent import Agent, ContextConfig, ReActConfig
|
||||
from agentscope.agent._config import ModelConfig
|
||||
from agentscope.event import (
|
||||
|
|
@ -61,20 +60,11 @@ from ..as_llm import BaseAsLLM
|
|||
from ..component_registry import R
|
||||
from ...enumeration import ChunkEnum
|
||||
from ...schema import StreamChunk, TokenUsage
|
||||
from ...utils import AsStateHandler, version_tuple
|
||||
from ...utils import AsStateHandler
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..job.base_job import BaseJob
|
||||
|
||||
# agentscope>=2.0.5 reworked the agent loop: InjectionConfig (runtime-state
|
||||
# injection) was introduced, and token usage moved from per-call
|
||||
# ModelCallEndEvent fields onto the aggregated ``Msg.usage`` of the reply.
|
||||
_AS_GE_2_0_5 = version_tuple(agentscope.__version__) >= (2, 0, 5)
|
||||
if _AS_GE_2_0_5:
|
||||
from agentscope.agent import InjectionConfig
|
||||
else:
|
||||
InjectionConfig = None
|
||||
|
||||
_UUID_RE = re.compile(
|
||||
r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
||||
re.IGNORECASE,
|
||||
|
|
@ -338,28 +328,6 @@ class AsAgentWrapper(BaseAgentWrapper):
|
|||
perm_mode = PermissionMode(kwargs.get("permission_mode", "bypass"))
|
||||
state = await self._load_state(kwargs, perm_mode)
|
||||
|
||||
version_kwargs: dict[str, Any] = {}
|
||||
react_config = dict(kwargs.get("react_config") or {})
|
||||
if _AS_GE_2_0_5:
|
||||
# Default to no runtime-state injection: the injected wall-clock
|
||||
# "ground truth" time conflicts with callers that anchor time
|
||||
# explicitly (benchmarks, historical ingestion). Callers can still
|
||||
# opt back in by passing injection_config explicitly.
|
||||
injection = {"inject_runtime_state": False, **(kwargs.get("injection_config") or {})}
|
||||
version_kwargs["injection_config"] = InjectionConfig(**injection)
|
||||
# agentscope>=2.0.5 counts Reasoning and Acting passes separately,
|
||||
# so one full ReAct round costs two iterations. Callers express
|
||||
# max_iters in reasoning rounds; double it here so the effective
|
||||
# budget matches agentscope<2.0.5 semantics.
|
||||
react_config["max_iters"] = 2 * int(react_config.get("max_iters", ReActConfig().max_iters))
|
||||
elif kwargs.get("injection_config"):
|
||||
# agentscope<2.0.5 has no runtime-state injection at all, so a
|
||||
# request to disable it is already satisfied; other fields cannot
|
||||
# be honored and are dropped.
|
||||
self.logger.debug(
|
||||
f"injection_config requires agentscope>=2.0.5; ignored on {agentscope.__version__}",
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name=self.name,
|
||||
system_prompt=system_prompt,
|
||||
|
|
@ -368,8 +336,7 @@ class AsAgentWrapper(BaseAgentWrapper):
|
|||
state=state,
|
||||
model_config=ModelConfig(**(kwargs.get("model_config") or {})),
|
||||
context_config=ContextConfig(**(kwargs.get("context_config") or {})),
|
||||
react_config=ReActConfig(**react_config),
|
||||
**version_kwargs,
|
||||
react_config=ReActConfig(**(kwargs.get("react_config") or {})),
|
||||
)
|
||||
|
||||
if isinstance(inputs, str):
|
||||
|
|
@ -382,23 +349,8 @@ class AsAgentWrapper(BaseAgentWrapper):
|
|||
agent, inputs = await self._build_agent(inputs, **kwargs)
|
||||
|
||||
await agent.observe(inputs)
|
||||
if _AS_GE_2_0_5:
|
||||
last_msg = await agent.reply()
|
||||
usage = self._agentscope_usage(last_msg.usage) if getattr(last_msg, "usage", None) else None
|
||||
else:
|
||||
# agentscope<2.0.5 reports usage per model call instead of on the
|
||||
# reply message, so accumulate ModelCallEndEvent fields here.
|
||||
usages: list[TokenUsage] = []
|
||||
async for event in agent.reply_stream():
|
||||
if isinstance(event, ModelCallEndEvent):
|
||||
usages.append(
|
||||
TokenUsage(
|
||||
input_tokens=event.input_tokens,
|
||||
output_tokens=event.output_tokens,
|
||||
),
|
||||
)
|
||||
last_msg = agent.state.context[-1]
|
||||
usage = TokenUsage.combine(usages) if usages else None
|
||||
last_msg = await agent.reply()
|
||||
usage = self._agentscope_usage(last_msg.usage) if last_msg.usage is not None else None
|
||||
await self._dump_state(agent.state)
|
||||
|
||||
result = {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from .common_utils import (
|
||||
hash_text,
|
||||
version_tuple,
|
||||
execute_stream_task,
|
||||
mock_reme_server,
|
||||
call_action,
|
||||
|
|
@ -20,7 +19,6 @@ from .counter import global_counter_add, global_counter_get, global_counter_get_
|
|||
|
||||
__all__ = [
|
||||
"hash_text",
|
||||
"version_tuple",
|
||||
"execute_stream_task",
|
||||
"mock_reme_server",
|
||||
"call_action",
|
||||
|
|
|
|||
|
|
@ -22,20 +22,6 @@ def hash_text(text: str, encoding: str = "utf-8") -> str:
|
|||
return hashlib.sha256(text.encode(encoding)).hexdigest()
|
||||
|
||||
|
||||
def version_tuple(version: str) -> tuple[int, ...]:
|
||||
"""Parse the leading numeric parts of a version string into a tuple.
|
||||
|
||||
Non-numeric suffixes are ignored, e.g. "2.0.4.post1" -> (2, 0, 4),
|
||||
so tuples compare correctly across pre/post releases.
|
||||
"""
|
||||
parts: list[int] = []
|
||||
for part in version.split("."):
|
||||
if not part.isdigit():
|
||||
break
|
||||
parts.append(int(part))
|
||||
return tuple(parts)
|
||||
|
||||
|
||||
def _format_chunk(
|
||||
chunk: StreamChunk,
|
||||
output_format: Literal["str", "bytes", "chunk"],
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from types import SimpleNamespace
|
||||
|
||||
from agentscope.event import ModelCallEndEvent
|
||||
from agentscope.model._model_usage import ChatUsage
|
||||
import pytest
|
||||
|
||||
|
|
@ -107,11 +106,12 @@ def test_token_counter_is_a_per_agent_metric_tree(tmp_path):
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_agentscope_reply_records_final_message_usage(tmp_path, monkeypatch):
|
||||
"""Reply usage is recorded: from the final message (>=2.0.5) or model-call events (<2.0.5)."""
|
||||
"""AgentScope 2.0.4.post1 reports aggregate usage on the final message."""
|
||||
context = ApplicationContext(workspace_dir=str(tmp_path))
|
||||
wrapper = AsAgentWrapper(name="research", as_llm="", app_context=context)
|
||||
message = SimpleNamespace(
|
||||
usage=SimpleNamespace(input_tokens=10, output_tokens=4),
|
||||
# Match the AgentScope 2.0.4.post1 accumulation test: 10/20 + 5/8.
|
||||
usage=SimpleNamespace(input_tokens=15, output_tokens=28),
|
||||
model_dump=lambda: {"text": "answer"},
|
||||
get_text_content=lambda: "answer",
|
||||
)
|
||||
|
|
@ -119,9 +119,7 @@ async def test_agentscope_reply_records_final_message_usage(tmp_path, monkeypatc
|
|||
state=SimpleNamespace(session_id="session-1", context=[message]),
|
||||
observe=lambda _inputs: _async_none(),
|
||||
reply=lambda: _async_value(message),
|
||||
reply_stream=lambda: _async_events(
|
||||
[ModelCallEndEvent(reply_id="r1", input_tokens=10, output_tokens=4)],
|
||||
),
|
||||
reply_stream=_unexpected_reply_stream,
|
||||
)
|
||||
|
||||
async def build_agent(inputs, **_kwargs):
|
||||
|
|
@ -132,10 +130,10 @@ async def test_agentscope_reply_records_final_message_usage(tmp_path, monkeypatc
|
|||
|
||||
result = await wrapper.reply("hello")
|
||||
|
||||
assert result["usage"] == {"input_tokens": 10, "output_tokens": 4, "total_tokens": 14}
|
||||
assert result["usage"] == {"input_tokens": 15, "output_tokens": 28, "total_tokens": 43}
|
||||
assert (
|
||||
global_counter_get_all(context.metadata, ["__token_counter", "research"])["children"]["total_tokens"]["value"]
|
||||
== 14
|
||||
== 43
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -144,12 +142,16 @@ async def test_agentscope_reply_without_usage_leaves_token_counters_unset(tmp_pa
|
|||
"""Replies without any usage information remain visibly unavailable."""
|
||||
context = ApplicationContext(workspace_dir=str(tmp_path))
|
||||
wrapper = AsAgentWrapper(name="research", as_llm="", app_context=context)
|
||||
message = SimpleNamespace(model_dump=lambda: {"text": "answer"}, get_text_content=lambda: "answer")
|
||||
message = SimpleNamespace(
|
||||
usage=None,
|
||||
model_dump=lambda: {"text": "answer"},
|
||||
get_text_content=lambda: "answer",
|
||||
)
|
||||
agent = SimpleNamespace(
|
||||
state=SimpleNamespace(session_id="session-1", context=[message]),
|
||||
observe=lambda _inputs: _async_none(),
|
||||
reply=lambda: _async_value(message),
|
||||
reply_stream=lambda: _async_events([]),
|
||||
reply_stream=_unexpected_reply_stream,
|
||||
)
|
||||
|
||||
async def build_agent(inputs, **_kwargs):
|
||||
|
|
@ -172,9 +174,8 @@ async def _async_value(value):
|
|||
return value
|
||||
|
||||
|
||||
async def _async_events(events):
|
||||
for event in events:
|
||||
yield event
|
||||
def _unexpected_reply_stream(*_args, **_kwargs):
|
||||
raise AssertionError("Non-streaming replies must use Agent.reply()")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue