ReMe/tests/unit/test_compressor_step.py
sa-buc db4763aead feat: add CompressorStep and search_v2 dual-mode session compression
- Add CompressorStep (reme/steps/evolve/compressor.py) for direct LLM
  text compression with optional query-guided relevance filtering
- Extend search_v2_step to support query-aware and query-independent
  session transcript compression via _compress injected kwargs
- Refactor _source_format.py: split into render_chunk_entries +
  join_chunk_entries; session chunks now render line-aligned with
  L<n>: prefixes for verbatim/compressed parity
- Add JOB_TOOLS and INJECTED_JOB_KWARGS to BaseAgenticAnswerStep for
  per-subclass tool and parameter injection
- LmeAgenticAnswerStep injects _search._compress payload to enable
  query-aware compression during benchmark evaluation
- Record compression ablation results in result-longmemeval.md
- Add unit tests for CompressorStep and search compression paths
2026-08-04 15:30:38 +08:00

72 lines
2.3 KiB
Python

"""Unit tests for CompressorStep without LLM dependencies."""
import asyncio
from agentscope.message import TextBlock, ThinkingBlock
from agentscope.model import ChatResponse
from reme.steps.evolve.compressor import CompressorStep
def test_response_text_handles_non_streaming_chat_response():
"""A plain ChatResponse must not crash the async-iteration check.
Regression: ``ChatResponse`` inherits agentscope's ``DictMixin`` whose
instance ``__getattr__`` raises ``KeyError``, so ``hasattr(result,
"__aiter__")`` raised instead of returning False and every compression
failed with ``KeyError: '__aiter__'``.
"""
async def run():
result = ChatResponse(
content=[
{"type": "thinking", "thinking": "internal reasoning"},
{"type": "text", "text": "compressed "},
{"type": "text", "text": "output"},
],
is_last=True,
)
text = await CompressorStep._response_text(result) # pylint: disable=protected-access
assert text == "compressed output"
asyncio.run(run())
def test_response_text_handles_pydantic_content_blocks():
"""Real LLM responses carry pydantic block models, not dicts.
Regression: ``block.get(...)`` crashed with ``'ThinkingBlock' object has
no attribute 'get'`` on responses from reasoning models.
"""
async def run():
result = ChatResponse(
content=[
ThinkingBlock(type="thinking", thinking="internal reasoning"),
TextBlock(type="text", text="compressed output"),
],
is_last=True,
)
text = await CompressorStep._response_text(result) # pylint: disable=protected-access
assert text == "compressed output"
asyncio.run(run())
def test_response_text_consumes_streaming_chunks_and_keeps_last():
"""An async generator of ChatResponses is drained and the last chunk wins."""
async def run():
async def stream():
yield ChatResponse(content=[{"type": "text", "text": "partial"}], is_last=False)
yield ChatResponse(content=[{"type": "text", "text": "final text"}], is_last=True)
text = await CompressorStep._response_text(stream()) # pylint: disable=protected-access
assert text == "final text"
asyncio.run(run())