# models/llm/chat.py (OpenAI 插件内) from __future__ import annotations # ← 必须是第一条 import 语句 import json import logging from typing import Any, cast # 其余 import 保持插件原文件不动(OpenAI 插件 chat.py 里已有) # ↓↓↓ 新增函数必须写在这里:from __future__ 之后、generate_chat 之前 ↓↓↓ def _text_content(m: "PromptMessage") -> str: """把 System / Developer 消息的内容取成字符串。""" content = getattr(m, "content", "") or "" if isinstance(content, str): return content # PromptMessageContent 可能是 list[TextPromptMessageContent] if isinstance(content, (list, tuple)): return "".join( getattr(part, "data", "") or "" for part in content if getattr(part, "type", "") == "text" ) return str(content) def _ensure_system_first(messages: "list[PromptMessage]") -> "list[PromptMessage]": """收集所有 system / developer 消息,去空后用 \\n\\n 合并成单条 system 置顶。 Qwen3 的 chat template 只接受一条 system 消息且必须在最前; Dify(尤其 Agent 应用)会把多条 system / developer 提示堆在前面, 导致 vLLM 报 400 'System message must be at the beginning.'。 """ system_parts: list[str] = [] rest: list[PromptMessage] = [] for m in messages: if isinstance(m, (SystemPromptMessage, DeveloperPromptMessage)): text = _text_content(m) if text.strip(): system_parts.append(text) else: rest.append(m) if system_parts: rest.insert(0, SystemPromptMessage(content="\n\n".join(system_parts))) return rest # 下方仍是插件原有的 generate_chat 等逻辑,不要删