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:
+19
-10
@@ -7,7 +7,7 @@ import json
|
||||
from typing import AsyncGenerator
|
||||
|
||||
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.career import Career, CharacterCareer
|
||||
from app.models.character import Character
|
||||
from app.models.project import Project
|
||||
@@ -25,6 +25,7 @@ from app.schemas.career import (
|
||||
CareerStage
|
||||
)
|
||||
from app.services.ai_service import AIService
|
||||
from app.services.json_helper import loads_json
|
||||
from app.logger import get_logger
|
||||
from app.api.settings import get_user_ai_service
|
||||
from app.api.common import verify_project_access
|
||||
@@ -155,14 +156,10 @@ async def create_career(
|
||||
raise HTTPException(status_code=500, detail=f"创建职业失败: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/generate-system", summary="AI生成新职业(增量式,流式)")
|
||||
@router.post("/generate-system", summary="AI生成新职业(增量式,流式)")
|
||||
async def generate_career_system(
|
||||
project_id: str,
|
||||
main_career_count: int = 3,
|
||||
sub_career_count: int = 6,
|
||||
user_requirements: str = "",
|
||||
enable_mcp: bool = False,
|
||||
http_request: Request = None,
|
||||
request_data: CareerGenerateRequest,
|
||||
http_request: Request,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_ai_service: AIService = Depends(get_user_ai_service)
|
||||
):
|
||||
@@ -176,6 +173,10 @@ async def generate_career_system(
|
||||
try:
|
||||
# 验证用户权限和项目是否存在
|
||||
user_id = getattr(http_request.state, 'user_id', None)
|
||||
project_id = request_data.project_id
|
||||
main_career_count = request_data.main_career_count
|
||||
sub_career_count = request_data.sub_career_count
|
||||
user_requirements = request_data.user_requirements
|
||||
project = await verify_project_access(project_id, user_id, db)
|
||||
|
||||
yield await tracker.start()
|
||||
@@ -316,7 +317,15 @@ async def generate_career_system(
|
||||
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_response += chunk
|
||||
|
||||
@@ -345,7 +354,7 @@ async def generate_career_system(
|
||||
# 清洗并解析JSON
|
||||
try:
|
||||
cleaned_response = user_ai_service._clean_json_response(ai_response)
|
||||
career_data = json.loads(cleaned_response)
|
||||
career_data = loads_json(cleaned_response)
|
||||
logger.info(f"✅ 职业体系JSON解析成功")
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"❌ 职业体系JSON解析失败: {e}")
|
||||
|
||||
Reference in New Issue
Block a user