fix: MCP插件TimeoutError修复 + 多项Bug修复和性能优化

- fix: MCP插件管理接口改为后台任务,修复TimeoutError
- fix: MCP连接失败后上下文清理的cancel scope错误
- feat: MCP插件后台注册添加重试机制
- fix: 限制每章自动创建伏笔数量上限
- fix: 修复JSON非法转义字符清洗
- fix: SSE流式生成添加心跳保活
- fix: 职业生成改用POST请求避免URL长度限制
- perf: 使用torch CPU版本加速Docker构建
- fix: 自动修复JSON字符串值中的裸换行符
- feat: 集成json5容错解析器
This commit is contained in:
未来
2026-04-26 13:58:15 +08:00
parent 5c22f29bf9
commit 17e78955a9
18 changed files with 559 additions and 179 deletions
+12 -3
View File
@@ -7,7 +7,7 @@ from pydantic import BaseModel, Field
import json
from app.database import get_db
from app.utils.sse_response import SSEResponse, create_sse_response, WizardProgressTracker
from app.utils.sse_response import SSEResponse, create_sse_response, WizardProgressTracker, wrap_stream_with_heartbeat, HEARTBEAT
from app.models.relationship import Organization, OrganizationMember
from app.models.character import Character
from app.models.project import Project
@@ -24,6 +24,7 @@ from app.schemas.relationship import (
)
from app.schemas.character import CharacterResponse
from app.services.ai_service import AIService
from app.services.json_helper import loads_json
from app.services.prompt_service import prompt_service, PromptService
from app.logger import get_logger
from app.api.settings import get_user_ai_service
@@ -500,7 +501,15 @@ async def generate_organization_stream(
chunk_count = 0
estimated_total = max(3000, len(prompt) * 8)
async for chunk in user_ai_service.generate_text_stream(prompt=prompt):
async for chunk in wrap_stream_with_heartbeat(
user_ai_service.generate_text_stream(prompt=prompt),
heartbeat_interval=15.0
):
# 心跳哨兵:发送心跳保活,不混入AI响应
if chunk is HEARTBEAT:
yield await tracker.heartbeat()
continue
chunk_count += 1
ai_content += chunk
@@ -529,7 +538,7 @@ async def generate_organization_stream(
# ✅ 使用统一的 JSON 清洗方法
try:
cleaned_response = user_ai_service._clean_json_response(ai_content)
organization_data = json.loads(cleaned_response)
organization_data = loads_json(cleaned_response)
logger.info(f"✅ 组织JSON解析成功")
except json.JSONDecodeError as e:
logger.error(f"❌ 组织JSON解析失败: {e}")