@@ -381,13 +381,22 @@ def _normalize_content(raw_content: Any, strip: bool = True) -> str:
381381 plain string. This method handles both formats.
382382
383383 Args:
384- raw_content: The raw content from LLM response, can be str, list, or other.
384+ raw_content: The raw content from LLM response, can be str, list, dict, or other.
385385 strip: Whether to strip whitespace from the result. Set to False for
386386 streaming chunks to preserve spaces between words.
387387
388388 Returns:
389389 Normalized plain text string.
390390 """
391+ # Handle dict format (e.g., {"type": "text", "text": "..."})
392+ if isinstance (raw_content , dict ):
393+ if "text" in raw_content :
394+ text_val = raw_content .get ("text" , "" )
395+ return str (text_val ) if text_val is not None else ""
396+ # For other dict formats, return empty string and log
397+ logger .warning (f"未预期的 dict 格式 content: { raw_content } " )
398+ return ""
399+
391400 if isinstance (raw_content , list ):
392401 # Check if this looks like OpenAI content-part format
393402 # Only process if at least one item has {'type': 'text', 'text': ...} structure
@@ -450,7 +459,8 @@ def _normalize_content(raw_content: Any, strip: bool = True) -> str:
450459 return "" .join (text_parts )
451460 return content
452461
453- return str (raw_content )
462+ # Fallback for other types (int, float, etc.)
463+ return str (raw_content ) if raw_content is not None else ""
454464
455465 async def _parse_openai_completion (
456466 self , completion : ChatCompletion , tools : ToolSet | None
0 commit comments