diff --git a/app/api/v1/chat.py b/app/api/v1/chat.py index 7069670..6aa5fef 100644 --- a/app/api/v1/chat.py +++ b/app/api/v1/chat.py @@ -16,8 +16,8 @@ from app.core.exceptions import ValidationException router = APIRouter(tags=["Chat"]) -VALID_ROLES = ["developer", "system", "user", "assistant", "tool", "function"] -# 角色别名映射 (OpenAI 兼容) +VALID_ROLES = ["developer", "system", "user", "assistant", "tool"] +# 角色别名映射 (OpenAI 兼容: function -> tool) ROLE_ALIASES = {"function": "tool"} USER_CONTENT_TYPES = ["text", "image_url", "input_audio", "file"] @@ -123,8 +123,14 @@ class ChatCompletionRequest(BaseModel): return True if v.lower() in ("false", "0", "no"): return False - # 其他情况尝试转换 - return bool(v) + # 未识别的字符串值抛出错误 + raise ValueError( + f"Invalid stream value '{v}'. Must be a boolean or one of: true, false, 1, 0, yes, no" + ) + # 非布尔非字符串类型抛出错误 + raise ValueError( + f"Invalid stream value type '{type(v).__name__}'. Must be a boolean or string." + ) model_config = { "extra": "ignore" diff --git a/app/services/grok/processor.py b/app/services/grok/processor.py index 4b3d42f..5493ea1 100644 --- a/app/services/grok/processor.py +++ b/app/services/grok/processor.py @@ -179,14 +179,19 @@ class StreamProcessor(BaseProcessor): self._tag_buffer += char # 检查是否到达结束标签 if char == '>': - # 检查是否是自闭合标签或结束标签 - if '/>' in self._tag_buffer or '' in self._tag_buffer: + # 检查是否是自闭合标签 + if '/>' in self._tag_buffer: self._in_filter_tag = False self._tag_buffer = "" - # 检查是否是开始标签结束(非自闭合) - elif self._tag_buffer.startswith('' in self._tag_buffer: + else: + # 检查是否是结束标签 + for tag in self.filter_tags: + if f'' in self._tag_buffer: + self._in_filter_tag = False + self._tag_buffer = "" + break + # 如果不是结束标签,检查是否是开始标签结束(非自闭合) # 继续等待结束标签 - pass i += 1 continue diff --git a/app/services/grok/retry.py b/app/services/grok/retry.py index c828e7c..c9d6862 100644 --- a/app/services/grok/retry.py +++ b/app/services/grok/retry.py @@ -188,7 +188,10 @@ async def retry_on_status( if extract_status is None: def extract_status(e: Exception) -> Optional[int]: if isinstance(e, UpstreamException): - return e.details.get("status") if e.details else None + # 优先从 details 获取,回退到 status_code 属性 + if e.details and "status" in e.details: + return e.details["status"] + return getattr(e, "status_code", None) return None while ctx.attempt <= ctx.max_retry: