feat: capture streaming token usage in QwenClient and QwenVLClient

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
wangwei
2026-07-23 13:19:23 +08:00
co-authored by Copilot
parent 81a6d54fff
commit f2bd0deeb3
2 changed files with 61 additions and 6 deletions
@@ -81,3 +81,34 @@ def test_deepseek_stream_chat_without_usage_chunk_returns_none():
assert chunks == ["Hi"]
assert returned_usage is None
from app.services.llm.qwen_client import QwenClient, QwenVLClient
def test_qwen_stream_chat_returns_usage_from_trailing_chunk():
"""QwenClient.stream_chat() must return the trailing usage dict."""
config = LLMConfig(provider=LLMProvider.QWEN, model="qwen3.5-flash", api_key="k", base_url="http://x/v1")
client = QwenClient(config)
usage = {"prompt_tokens": 10, "completion_tokens": 4, "total_tokens": 14}
client._client = _mock_streaming_client(_sse_lines("Bonjour", usage=usage))
chunks, returned_usage = _drain(client.stream_chat([{"role": "user", "content": "hi"}]))
assert chunks == ["Bonjour"]
assert returned_usage == usage
sent_payload = client._client.stream.call_args.kwargs["json"]
assert sent_payload["stream_options"] == {"include_usage": True}
def test_qwen_vl_stream_chat_returns_usage_from_trailing_chunk():
"""QwenVLClient.stream_chat() must return the trailing usage dict."""
config = LLMConfig(provider=LLMProvider.QWEN_VL, model="qwen3-vl-plus", api_key="k", base_url="http://x/v1")
client = QwenVLClient(config)
usage = {"prompt_tokens": 20, "completion_tokens": 6, "total_tokens": 26}
client._client = _mock_streaming_client(_sse_lines("Describing image", usage=usage))
chunks, returned_usage = _drain(client.stream_chat([{"role": "user", "content": "describe"}]))
assert chunks == ["Describing image"]
assert returned_usage == usage