diff --git a/app/services/grok/processer.py b/app/services/grok/processer.py index d8de920..2c51c69 100644 --- a/app/services/grok/processer.py +++ b/app/services/grok/processer.py @@ -210,12 +210,12 @@ class GrokResponseProcessor: last_video_progress = progress if show_thinking: if not video_progress_started: - content = f"视频已生成{progress}%\\n" + content = f"视频已生成{progress}%\n" video_progress_started = True elif progress < 100: - content = f"视频已生成{progress}%\\n" + content = f"视频已生成{progress}%\n" else: - content = f"视频已生成{progress}%\\n" + content = f"视频已生成{progress}%\n" yield make_chunk(content) # 视频URL @@ -252,23 +252,23 @@ class GrokResponseProcessor: # 8KB分块 for i in range(0, len(parts[1]), 8192): yield make_chunk(parts[1][i:i+8192]) - yield make_chunk(")\\n") + yield make_chunk(")\n") else: - yield make_chunk(f"![Generated Image]({base64_str})\\n") + yield make_chunk(f"![Generated Image]({base64_str})\n") else: - yield make_chunk(f"![Generated Image]({base64_str})\\n") + yield make_chunk(f"![Generated Image]({base64_str})\n") else: - yield make_chunk(f"![Generated Image](https://assets.grok.com/{img})\\n") + yield make_chunk(f"![Generated Image](https://assets.grok.com/{img})\n") else: # URL模式 await image_cache_service.download_image(f"/{img}", auth_token) img_path = img.replace('/', '-') base_url = setting.global_config.get("base_url", "") img_url = f"{base_url}/images/{img_path}" if base_url else f"/images/{img_path}" - content += f"![Generated Image]({img_url})\\n" + content += f"![Generated Image]({img_url})\n" except Exception as e: logger.warning(f"[Processor] 处理图片失败: {e}") - content += f"![Generated Image](https://assets.grok.com/{img})\\n" + content += f"![Generated Image](https://assets.grok.com/{img})\n" yield make_chunk(content.strip(), "stop") return @@ -298,9 +298,9 @@ class GrokResponseProcessor: title = result.get("title", "") url = result.get("url", "") preview = result.get("preview", "") - preview_clean = preview.replace("\\n", "") if isinstance(preview, str) else "" - token += f'\\n- [{title}]({url} "{preview_clean}")' - token += "\\n" + preview_clean = preview.replace("\n", "") if isinstance(preview, str) else "" + token += f'\n- [{title}]({url} "{preview_clean}")' + token += "\n" else: continue else: @@ -318,12 +318,12 @@ class GrokResponseProcessor: should_skip = False if not is_thinking and current_is_thinking: if show_thinking: - content = f"\\n{content}" + content = f"\n{content}" else: should_skip = True elif is_thinking and not current_is_thinking: if show_thinking: - content = f"\\n\\n{content}" + content = f"\n\n{content}" thinking_finished = True elif current_is_thinking: if not show_thinking: @@ -369,11 +369,11 @@ class GrokResponseProcessor: video_path = video_url.replace('/', '-') base_url = setting.global_config.get("base_url", "") local_url = f"{base_url}/images/{video_path}" if base_url else f"/images/{video_path}" - return f'\\n' + return f'\n' except Exception as e: logger.warning(f"[Processor] 缓存视频失败: {e}") - return f'\\n' + return f'\n' @staticmethod async def _append_images(content: str, images: list, auth_token: str) -> str: @@ -385,21 +385,21 @@ class GrokResponseProcessor: if image_mode == "base64": base64_str = await image_cache_service.download_base64(f"/{img}", auth_token) if base64_str: - content += f"\\n![Generated Image]({base64_str})" + content += f"\n![Generated Image]({base64_str})" else: - content += f"\\n![Generated Image](https://assets.grok.com/{img})" + content += f"\n![Generated Image](https://assets.grok.com/{img})" else: cache_path = await image_cache_service.download_image(f"/{img}", auth_token) if cache_path: img_path = img.replace('/', '-') base_url = setting.global_config.get("base_url", "") img_url = f"{base_url}/images/{img_path}" if base_url else f"/images/{img_path}" - content += f"\\n![Generated Image]({img_url})" + content += f"\n![Generated Image]({img_url})" else: - content += f"\\n![Generated Image](https://assets.grok.com/{img})" + content += f"\n![Generated Image](https://assets.grok.com/{img})" except Exception as e: logger.warning(f"[Processor] 处理图片失败: {e}") - content += f"\\n![Generated Image](https://assets.grok.com/{img})" + content += f"\n![Generated Image](https://assets.grok.com/{img})" return content diff --git a/app/services/grok/token.py b/app/services/grok/token.py index 1e58008..95aee40 100644 --- a/app/services/grok/token.py +++ b/app/services/grok/token.py @@ -169,8 +169,13 @@ class GrokTokenManager: unused, used = [], [] for key, data in tokens.items(): + # 跳过已失效的token if data.get("status") == "expired": continue + + # 跳过失败次数过多的token(任何错误状态码) + if data.get("failedCount", 0) >= MAX_FAILURES: + continue remaining = int(data.get(field, -1)) if remaining == 0: @@ -312,9 +317,9 @@ class GrokTokenManager: f"次数: {data['failedCount']}/{MAX_FAILURES}, 原因: {msg}" ) - if status == TOKEN_INVALID and data["failedCount"] >= MAX_FAILURES: + if 400 <= status < 500 and data["failedCount"] >= MAX_FAILURES: data["status"] = "expired" - logger.error(f"[Token] 标记失效: {sso[:10]}... (连续401错误{data['failedCount']}次)") + logger.error(f"[Token] 标记失效: {sso[:10]}... (连续{status}错误{data['failedCount']}次)") await self._save_data()