Commit b8be862

benny-dou <60535774+benny-dou@users.noreply.github.com>
2026-01-19 03:25:20
chore(ai): trim None values from LLM responses
1 parent 9709f8c
Changed files (3)
src/ai/texts/gemini.py
@@ -12,7 +12,7 @@ from pyrogram.parser.markdown import BLOCKQUOTE_EXPANDABLE_DELIM
 from pyrogram.types import Message, ReplyParameters
 
 from ai.texts.contexts import get_gemini_contexts
-from ai.utils import BOT_TIPS, EMOJI_REASONING_BEGIN, EMOJI_TEXT_BOT, beautify_llm_response, literal_eval
+from ai.utils import BOT_TIPS, EMOJI_REASONING_BEGIN, EMOJI_TEXT_BOT, beautify_llm_response, literal_eval, trim_none
 from config import AI, PROXY, TEXT_LENGTH
 from messages.progress import modify_progress
 from messages.utils import blockquote, count_without_entities, smart_split
@@ -204,12 +204,13 @@ async def single_api_generate_content(
 
 def parse_chunk(chunk: types.GenerateContentResponse) -> dict:
     """Parse gemini response, includes texts, image and websearch."""
-    data = chunk.model_dump()
+    data = trim_none(chunk.model_dump())
+    data.pop("sdk_http_response", None)
+    data.pop("usage_metadata", None)
+    logger.trace(data)
     parts = glom(data, "candidates.0.content.parts", default=[]) or []
-
     texts = "".join([p.get("text", "") for p in parts if not p.get("thought")])
     thinking = "".join([p.get("text", "") for p in parts if p.get("thought")])
-    logger.trace(texts or thinking)
     return {
         "texts": beautify_llm_response(texts, newline_level=2),
         "thinking": beautify_llm_response(thinking, newline_level=2),
src/ai/texts/openai_chat.py
@@ -127,8 +127,8 @@ async def single_api_chat_completions(
         is_reasoning = False
         reasoning_chat_flag = None  # 用于指示是否是推理对话
         async for chunk in await openai.chat.completions.create(**params):
-            resp = chunk.model_dump()
-            logger.trace(trim_none(resp))
+            resp = trim_none(chunk.model_dump())
+            logger.trace(resp)
             chunk_answer = glom(resp, "choices.0.delta.content", default="") or ""
             chunk_thinking = glom(resp, "choices.0.delta.reasoning_content", default="") or ""
             tool_name = tool_name or glom(resp, "choices.0.delta.tool_calls.0.function.name", default="")
@@ -184,7 +184,7 @@ async def single_api_chat_completions(
             return {"texts": answers, "thoughts": thoughts, "tool_name": tool_name.strip(), "tool_args": tool_args.strip(), "sent_messages": sent_messages}
         # all chunks are processed
         if not (answers.strip() or thoughts.strip()):  # empty response
-            await modify_progress(message=status_msg, text=resp, force_update=True)
+            await modify_progress(message=status_msg, text=str(resp), force_update=True)
             return await single_api_chat_completions(
                 client,
                 status_msg,
src/ai/texts/openai_response.py
@@ -12,7 +12,7 @@ from pyrogram.parser.markdown import BLOCKQUOTE_EXPANDABLE_DELIM
 from pyrogram.types import Message, ReplyParameters
 
 from ai.texts.contexts import get_openai_response_contexts
-from ai.utils import BOT_TIPS, EMOJI_REASONING_BEGIN, EMOJI_TEXT_BOT, beautify_llm_response, literal_eval
+from ai.utils import BOT_TIPS, EMOJI_REASONING_BEGIN, EMOJI_TEXT_BOT, beautify_llm_response, literal_eval, trim_none
 from config import AI, PROXY, TEXT_LENGTH
 from database.r2 import set_cf_r2
 from messages.parser import get_thread_id
@@ -150,7 +150,7 @@ async def single_api_response(
         tool_calls: list[dict] = []  # tool_call results
         is_reasoning = False
         async for chunk in await openai.responses.create(**params):
-            resp = chunk.model_dump()
+            resp = trim_none(chunk.model_dump())
             error = await parse_error(resp, retry, max_retries, status_msg)
             if error["retry"]:
                 return await single_api_response(