From f46aaa2182480d6ac50acf878db430217968f9c4 Mon Sep 17 00:00:00 2001 From: fawney19 Date: Sun, 4 Jan 2026 23:16:01 +0800 Subject: [PATCH] =?UTF-8?q?debug:=20=E6=B7=BB=E5=8A=A0=20streaming=20?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=9B=B4=E6=96=B0=E6=97=B6=20provider=20?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E7=9A=84=E8=B0=83=E8=AF=95=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - base_handler: 更新 streaming 状态时检测并记录 provider 为空的情况 - cli_handler_base: 修复预读数据为空时未更新 streaming 状态的问题 - usage service: 检测状态变为 streaming 但 provider 仍为 pending 的异常 --- src/api/handlers/base/base_handler.py | 7 +++++++ src/api/handlers/base/cli_handler_base.py | 7 +++++++ src/services/usage/service.py | 6 ++++++ 3 files changed, 20 insertions(+) diff --git a/src/api/handlers/base/base_handler.py b/src/api/handlers/base/base_handler.py index cf673fb..87de1b3 100644 --- a/src/api/handlers/base/base_handler.py +++ b/src/api/handlers/base/base_handler.py @@ -423,6 +423,13 @@ class BaseMessageHandler: provider = ctx.provider_name target_model = ctx.mapped_model + # 如果 provider 为空,记录警告(不应该发生,但用于调试) + if not provider: + logger.warning( + f"[{target_request_id}] 更新 streaming 状态时 provider 为空: " + f"ctx.provider_name={ctx.provider_name}, ctx.provider_id={ctx.provider_id}" + ) + async def _do_update() -> None: try: db_gen = get_db() diff --git a/src/api/handlers/base/cli_handler_base.py b/src/api/handlers/base/cli_handler_base.py index eb189e8..5f0f081 100644 --- a/src/api/handlers/base/cli_handler_base.py +++ b/src/api/handlers/base/cli_handler_base.py @@ -834,6 +834,7 @@ class CliMessageHandlerBase(BaseMessageHandler): last_data_time = time.time() buffer = b"" first_yield = True # 标记是否是第一次 yield + streaming_status_updated = False # 标记状态是否已更新 # 使用增量解码器处理跨 chunk 的 UTF-8 字符 decoder = codecs.getincrementaldecoder("utf-8")(errors="replace") @@ -843,6 +844,7 @@ class CliMessageHandlerBase(BaseMessageHandler): # 在第一次输出数据前更新状态为 streaming if prefetched_chunks: self._update_usage_to_streaming_with_ctx(ctx) + streaming_status_updated = True # 先处理预读的字节块 for chunk in prefetched_chunks: @@ -907,6 +909,11 @@ class CliMessageHandlerBase(BaseMessageHandler): # 继续处理剩余的流数据(使用同一个迭代器) async for chunk in byte_iterator: + # 如果预读数据为空,在收到第一个 chunk 时更新状态 + if not streaming_status_updated: + self._update_usage_to_streaming_with_ctx(ctx) + streaming_status_updated = True + buffer += chunk # 处理缓冲区中的完整行 while b"\n" in buffer: diff --git a/src/services/usage/service.py b/src/services/usage/service.py index d2e9ac9..bdb2628 100644 --- a/src/services/usage/service.py +++ b/src/services/usage/service.py @@ -1503,6 +1503,12 @@ class UsageService: usage.error_message = error_message if provider: usage.provider = provider + elif status == "streaming" and usage.provider == "pending": + # 状态变为 streaming 但 provider 仍为 pending,记录警告 + logger.warning( + f"状态更新为 streaming 但 provider 为空: request_id={request_id}, " + f"当前 provider={usage.provider}" + ) if target_model: usage.target_model = target_model if first_byte_time_ms is not None: