Files
qwenpaw/tests/unit/agents/utils/test_as_msg_handler.py
agent-radar 1a3a4ccde1
Creator App Tests / PR Spam Gate (push) Skipped
Frontend Tests / PR Spam Gate (push) Skipped
NPM Format (website & console) / PR Spam Gate (push) Skipped
Pre-commit Checks / PR Spam Gate (push) Skipped
QwenPaw Creator Plugin Release / check-version (push) Canceled after 0s
QwenPaw Creator Plugin Release / upload-oss (push) Canceled after 0s
Tests / PR Spam Gate (push) Skipped
CodeQL / CodeQL (python) (push) Canceled after 0s
CodeQL / CodeQL (typescript) (push) Canceled after 0s
Creator App Tests / Creator Backend Tests (push) Canceled after 0s
Creator App Tests / Creator UI Build & Tests (push) Canceled after 0s
E2E Smoke Tests / Playwright UI Smoke (push) Canceled after 0s
Frontend Tests / Detect console changes (push) Canceled after 0s
NPM Format (website & console) / website format check (push) Canceled after 0s
NPM Format (website & console) / console format check (push) Canceled after 0s
Pre-commit Checks / Pre-commit (push) Canceled after 0s
QwenPaw Data Plugin Release / check-version (push) Canceled after 0s
Tests / Detect code changes (push) Canceled after 0s
Frontend Tests / Vitest Unit Tests (push) Canceled after 0s
Frontend Tests / Frontend Summary (push) Canceled after 0s
QwenPaw Data Plugin Release / upload-oss (push) Canceled after 0s
Tests / Maintainer Approval (push) Canceled after 0s
Tests / Unit Tests - py3.11 - macos-latest (push) Canceled after 0s
Tests / Unit Tests - py3.11 - ubuntu-latest (push) Canceled after 0s
Tests / Unit Tests - py3.13 - ubuntu-latest (push) Canceled after 0s
Tests / Unit Tests - py3.11 - windows-latest (push) Canceled after 0s
Tests / Contract Tests - py3.11 - macos-latest (push) Canceled after 0s
Tests / Contract Tests - py3.11 - ubuntu-latest (push) Canceled after 0s
Tests / Contract Tests - py3.13 - ubuntu-latest (push) Canceled after 0s
Tests / Contract Tests - py3.11 - windows-latest (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - macos-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - macos-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - macos-latest - p2 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - fallback (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - p2 (push) Canceled after 0s
Tests / Integrated Tests - py3.13 - ubuntu-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.13 - ubuntu-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.13 - ubuntu-latest - p2 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - windows-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - windows-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - windows-latest - p2 (push) Canceled after 0s
Tests / Coverage Report (push) Canceled after 0s
Tests / Test Summary (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:01:50 +08:00

110 lines
3.1 KiB
Python

# -*- coding: utf-8 -*-
"""Tests for AsMsgHandler media token estimates."""
# pylint: disable=protected-access
import base64
import pytest
from agentscope.message import (
Base64Source,
DataBlock,
Msg,
)
from qwenpaw.agents.utils.as_msg_handler import AsMsgHandler
from qwenpaw.agents.utils.estimate_token_counter import EstimatedTokenCounter
from qwenpaw.agents.utils.media_token_estimate import (
IMAGE_FALLBACK_TOKENS,
VIDEO_FALLBACK_TOKENS,
estimate_inline_media_tokens,
)
@pytest.mark.asyncio
async def test_base64_image_does_not_count_payload_as_text_tokens():
payload = base64.b64encode(b"\x00" * (2 * 1024 * 1024)).decode("ascii")
msg = Msg(
name="user",
role="user",
content=[
DataBlock(
source=Base64Source(media_type="image/png", data=payload),
),
],
)
stat = await AsMsgHandler(EstimatedTokenCounter()).stat_message(msg)
# Old heuristic was len(base64)//4 ≈ 700k and filled the context ring.
assert 0 < stat.total_tokens < 10_000
@pytest.mark.asyncio
async def test_tool_result_blocks_dispatch_by_mime():
payload = base64.b64encode(b"\x00" * 4096).decode("ascii")
handler = AsMsgHandler(EstimatedTokenCounter())
png = await handler._format_tool_result_output(
[
{
"type": "data",
"source": {
"type": "base64",
"media_type": "image/png",
"data": payload,
},
},
],
)
video = await handler._format_tool_result_output(
[
{
"type": "data",
"source": {
"type": "base64",
"media_type": "video/mp4",
"data": payload,
},
},
],
)
pdf = await handler._format_tool_result_output(
[
{
"type": "data",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": payload,
},
},
],
)
assert png[1] == IMAGE_FALLBACK_TOKENS
assert video[1] == VIDEO_FALLBACK_TOKENS
assert pdf[1] != video[1]
assert png[1] != len(payload) // 4
@pytest.mark.asyncio
@pytest.mark.parametrize(
"kind",
("string", "text_block", "scheme_upper", "base64_upper"),
)
async def test_tool_result_text_data_url_not_counted_as_text(kind):
payload = "A" * (1024 * 1024)
if kind == "scheme_upper":
data_url = f"DATA:image/png;base64,{payload}"
elif kind == "base64_upper":
data_url = f"data:image/png;BASE64,{payload}"
else:
data_url = f"data:image/png;base64,{payload}"
handler = AsMsgHandler(EstimatedTokenCounter())
if kind == "text_block":
output = [{"type": "text", "text": data_url}]
else:
output = data_url
_, tokens = await handler._format_tool_result_output(output)
expected = estimate_inline_media_tokens("image/png", payload)
assert tokens == expected
assert tokens < 10_000
assert tokens != len(data_url) // 4