update:1.更新mcp插件功能,目前只支持remote调用
This commit is contained in:
+255
-23
@@ -404,8 +404,8 @@ async def _generate_new_outline(
|
||||
db: AsyncSession,
|
||||
user_ai_service: AIService
|
||||
) -> OutlineListResponse:
|
||||
"""全新生成大纲"""
|
||||
logger.info(f"全新生成大纲 - 项目: {project.id}, keep_existing: {request.keep_existing}")
|
||||
"""全新生成大纲(MCP增强版)"""
|
||||
logger.info(f"全新生成大纲 - 项目: {project.id}, enable_mcp: {request.enable_mcp}")
|
||||
|
||||
# 获取角色信息
|
||||
characters_result = await db.execute(
|
||||
@@ -418,7 +418,59 @@ async def _generate_new_outline(
|
||||
for char in characters
|
||||
])
|
||||
|
||||
# 使用完整提示词
|
||||
# 🔍 MCP工具增强:收集情节设计参考资料
|
||||
mcp_reference_materials = ""
|
||||
if request.enable_mcp:
|
||||
try:
|
||||
logger.info(f"🔍 尝试使用MCP工具收集大纲设计参考资料...")
|
||||
|
||||
# 构建资料收集查询
|
||||
planning_query = f"""你正在为小说《{project.title}》设计完整大纲。
|
||||
项目信息:
|
||||
- 主题:{request.theme or project.theme}
|
||||
- 类型:{request.genre or project.genre}
|
||||
- 章节数:{request.chapter_count}
|
||||
- 叙事视角:{request.narrative_perspective}
|
||||
- 目标字数:{request.target_words}
|
||||
|
||||
世界观设定:
|
||||
- 时间背景:{project.world_time_period or '未设定'}
|
||||
- 地理位置:{project.world_location or '未设定'}
|
||||
- 氛围基调:{project.world_atmosphere or '未设定'}
|
||||
|
||||
角色信息:
|
||||
{characters_info or '暂无角色'}
|
||||
|
||||
请搜索:
|
||||
1. 该类型小说的经典情节结构和套路
|
||||
2. 适合该主题的冲突设计思路
|
||||
3. 符合世界观的情节元素和场景设计灵感
|
||||
|
||||
请有针对性地查询1-2个最关键的问题。"""
|
||||
|
||||
# 调用MCP增强的AI(非流式,最多2轮工具调用)
|
||||
planning_result = await user_ai_service.generate_text_with_mcp(
|
||||
prompt=planning_query,
|
||||
user_id="system", # 全新生成时可能没有用户上下文
|
||||
db_session=db,
|
||||
enable_mcp=True,
|
||||
max_tool_rounds=2,
|
||||
tool_choice="auto",
|
||||
provider=None,
|
||||
model=None
|
||||
)
|
||||
|
||||
# 提取参考资料
|
||||
if planning_result.get("tool_calls_made", 0) > 0:
|
||||
mcp_reference_materials = planning_result.get("content", "")
|
||||
logger.info(f"📚 MCP工具收集参考资料:{len(mcp_reference_materials)} 字符")
|
||||
else:
|
||||
logger.info(f"ℹ️ MCP工具未进行调用,继续正常生成")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ MCP工具调用失败,继续使用常规模式: {str(e)}")
|
||||
mcp_reference_materials = ""
|
||||
|
||||
# 使用完整提示词(插入MCP参考资料)
|
||||
prompt = prompt_service.get_complete_outline_prompt(
|
||||
title=project.title,
|
||||
theme=request.theme or project.theme or "未设定",
|
||||
@@ -431,18 +483,22 @@ async def _generate_new_outline(
|
||||
atmosphere=project.world_atmosphere or "未设定",
|
||||
rules=project.world_rules or "未设定",
|
||||
characters_info=characters_info or "暂无角色信息",
|
||||
requirements=request.requirements or ""
|
||||
requirements=request.requirements or "",
|
||||
mcp_references=mcp_reference_materials
|
||||
)
|
||||
|
||||
# 调用AI
|
||||
# 调用AI生成大纲
|
||||
ai_response = await user_ai_service.generate_text(
|
||||
prompt=prompt,
|
||||
provider=request.provider,
|
||||
model=request.model
|
||||
)
|
||||
|
||||
# 提取内容(generate_text返回字典)
|
||||
ai_content = ai_response.get("content", "") if isinstance(ai_response, dict) else ai_response
|
||||
|
||||
# 解析响应
|
||||
outline_data = _parse_ai_response(ai_response)
|
||||
outline_data = _parse_ai_response(ai_content)
|
||||
|
||||
# 全新生成模式:必须删除旧大纲和章节
|
||||
# 注意:这是"new"模式的核心逻辑,应该始终删除旧数据
|
||||
@@ -463,7 +519,7 @@ async def _generate_new_outline(
|
||||
history = GenerationHistory(
|
||||
project_id=project.id,
|
||||
prompt=prompt,
|
||||
generated_content=ai_response,
|
||||
generated_content=json.dumps(ai_response, ensure_ascii=False) if isinstance(ai_response, dict) else ai_response,
|
||||
model=request.model or "default"
|
||||
)
|
||||
db.add(history)
|
||||
@@ -571,8 +627,8 @@ async def _continue_outline(
|
||||
user_ai_service: AIService,
|
||||
user_id: str = "system"
|
||||
) -> OutlineListResponse:
|
||||
"""续写大纲 - 分批生成,每批5章(记忆增强版)"""
|
||||
logger.info(f"续写大纲 - 项目: {project.id}, 已有: {len(existing_outlines)} 章")
|
||||
"""续写大纲 - 分批生成,每批5章(记忆+MCP增强版)"""
|
||||
logger.info(f"续写大纲 - 项目: {project.id}, 已有: {len(existing_outlines)} 章, enable_mcp: {request.enable_mcp}")
|
||||
|
||||
# 分析已有大纲
|
||||
current_chapter_count = len(existing_outlines)
|
||||
@@ -664,7 +720,57 @@ async def _continue_outline(
|
||||
logger.warning(f"⚠️ 记忆上下文构建失败,继续不使用记忆: {str(e)}")
|
||||
memory_context = None
|
||||
|
||||
# 使用标准续写提示词模板(支持记忆增强)
|
||||
# 🔍 MCP工具增强:收集续写参考资料
|
||||
mcp_reference_materials = ""
|
||||
if request.enable_mcp:
|
||||
try:
|
||||
logger.info(f"🔍 第{batch_num + 1}批:尝试使用MCP工具收集续写参考资料...")
|
||||
|
||||
# 构建资料收集查询
|
||||
latest_summary = latest_outlines[-1].content if latest_outlines else ""
|
||||
planning_query = f"""你正在为小说《{project.title}》续写大纲。
|
||||
当前进度:已有{len(latest_outlines)}章,即将续写第{current_start_chapter}-{current_start_chapter + current_batch_size - 1}章
|
||||
|
||||
项目信息:
|
||||
- 主题:{request.theme or project.theme}
|
||||
- 类型:{request.genre or project.genre}
|
||||
- 叙事视角:{request.narrative_perspective}
|
||||
- 情节阶段:{request.plot_stage}
|
||||
- 故事发展方向:{request.story_direction or '自然延续'}
|
||||
|
||||
最近章节概要:
|
||||
{latest_summary[:200]}
|
||||
|
||||
请搜索:
|
||||
1. 该情节阶段的经典处理手法和技巧
|
||||
2. 适合该发展方向的情节转折和冲突设计
|
||||
3. 符合类型特点的场景设计和剧情元素
|
||||
|
||||
请有针对性地查询1-2个最关键的问题。"""
|
||||
|
||||
# 调用MCP增强的AI(非流式,最多2轮工具调用)
|
||||
planning_result = await user_ai_service.generate_text_with_mcp(
|
||||
prompt=planning_query,
|
||||
user_id=user_id,
|
||||
db_session=db,
|
||||
enable_mcp=True,
|
||||
max_tool_rounds=2,
|
||||
tool_choice="auto",
|
||||
provider=None,
|
||||
model=None
|
||||
)
|
||||
|
||||
# 提取参考资料
|
||||
if planning_result.get("tool_calls_made", 0) > 0:
|
||||
mcp_reference_materials = planning_result.get("content", "")
|
||||
logger.info(f"📚 第{batch_num + 1}批MCP工具收集参考资料:{len(mcp_reference_materials)} 字符")
|
||||
else:
|
||||
logger.info(f"ℹ️ 第{batch_num + 1}批MCP工具未进行调用,继续正常生成")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ 第{batch_num + 1}批MCP工具调用失败,继续使用常规模式: {str(e)}")
|
||||
mcp_reference_materials = ""
|
||||
|
||||
# 使用标准续写提示词模板(支持记忆+MCP增强)
|
||||
prompt = prompt_service.get_outline_continue_prompt(
|
||||
title=project.title,
|
||||
theme=request.theme or project.theme or "未设定",
|
||||
@@ -683,7 +789,8 @@ async def _continue_outline(
|
||||
start_chapter=current_start_chapter,
|
||||
story_direction=request.story_direction or "自然延续",
|
||||
requirements=request.requirements or "",
|
||||
memory_context=memory_context
|
||||
memory_context=memory_context,
|
||||
mcp_references=mcp_reference_materials
|
||||
)
|
||||
|
||||
# 调用AI生成当前批次
|
||||
@@ -694,8 +801,11 @@ async def _continue_outline(
|
||||
model=request.model
|
||||
)
|
||||
|
||||
# 提取内容(generate_text返回字典)
|
||||
ai_content = ai_response.get("content", "") if isinstance(ai_response, dict) else ai_response
|
||||
|
||||
# 解析响应
|
||||
outline_data = _parse_ai_response(ai_response)
|
||||
outline_data = _parse_ai_response(ai_content)
|
||||
|
||||
# 保存当前批次的大纲
|
||||
batch_outlines = await _save_outlines(
|
||||
@@ -706,7 +816,7 @@ async def _continue_outline(
|
||||
history = GenerationHistory(
|
||||
project_id=project.id,
|
||||
prompt=f"[批次{batch_num + 1}/{total_batches}] {str(prompt)[:500]}",
|
||||
generated_content=ai_response,
|
||||
generated_content=json.dumps(ai_response, ensure_ascii=False) if isinstance(ai_response, dict) else ai_response,
|
||||
model=request.model or "default"
|
||||
)
|
||||
db.add(history)
|
||||
@@ -820,7 +930,7 @@ async def new_outline_generator(
|
||||
db: AsyncSession,
|
||||
user_ai_service: AIService
|
||||
) -> AsyncGenerator[str, None]:
|
||||
"""全新生成大纲SSE生成器"""
|
||||
"""全新生成大纲SSE生成器(MCP增强版)"""
|
||||
db_committed = False
|
||||
try:
|
||||
yield await SSEResponse.send_progress("开始生成大纲...", 5)
|
||||
@@ -828,6 +938,7 @@ async def new_outline_generator(
|
||||
project_id = data.get("project_id")
|
||||
# 确保chapter_count是整数(前端可能传字符串)
|
||||
chapter_count = int(data.get("chapter_count", 10))
|
||||
enable_mcp = data.get("enable_mcp", True)
|
||||
|
||||
# 验证项目
|
||||
yield await SSEResponse.send_progress("加载项目信息...", 10)
|
||||
@@ -852,7 +963,61 @@ async def new_outline_generator(
|
||||
for char in characters
|
||||
])
|
||||
|
||||
# 使用完整提示词
|
||||
# 🔍 MCP工具增强:收集情节设计参考资料
|
||||
mcp_reference_materials = ""
|
||||
if enable_mcp:
|
||||
try:
|
||||
yield await SSEResponse.send_progress("🔍 使用MCP工具收集参考资料...", 18)
|
||||
logger.info(f"🔍 尝试使用MCP工具收集大纲设计参考资料...")
|
||||
|
||||
# 构建资料收集查询
|
||||
planning_query = f"""你正在为小说《{project.title}》设计完整大纲。
|
||||
项目信息:
|
||||
- 主题:{data.get('theme') or project.theme}
|
||||
- 类型:{data.get('genre') or project.genre}
|
||||
- 章节数:{chapter_count}
|
||||
- 叙事视角:{data.get('narrative_perspective') or '第三人称'}
|
||||
- 目标字数:{data.get('target_words') or project.target_words or 100000}
|
||||
|
||||
世界观设定:
|
||||
- 时间背景:{project.world_time_period or '未设定'}
|
||||
- 地理位置:{project.world_location or '未设定'}
|
||||
- 氛围基调:{project.world_atmosphere or '未设定'}
|
||||
|
||||
角色信息:
|
||||
{characters_info or '暂无角色'}
|
||||
|
||||
请搜索:
|
||||
1. 该类型小说的经典情节结构和套路
|
||||
2. 适合该主题的冲突设计思路
|
||||
3. 符合世界观的情节元素和场景设计灵感
|
||||
|
||||
请有针对性地查询1-2个最关键的问题。"""
|
||||
|
||||
# 调用MCP增强的AI(非流式,最多2轮工具调用)
|
||||
planning_result = await user_ai_service.generate_text_with_mcp(
|
||||
prompt=planning_query,
|
||||
user_id="system",
|
||||
db_session=db,
|
||||
enable_mcp=True,
|
||||
max_tool_rounds=2,
|
||||
tool_choice="auto",
|
||||
provider=None,
|
||||
model=None
|
||||
)
|
||||
|
||||
# 提取参考资料
|
||||
if planning_result.get("tool_calls_made", 0) > 0:
|
||||
mcp_reference_materials = planning_result.get("content", "")
|
||||
logger.info(f"📚 MCP工具收集参考资料:{len(mcp_reference_materials)} 字符")
|
||||
yield await SSEResponse.send_progress(f"📚 MCP收集到参考资料 ({len(mcp_reference_materials)}字符)", 19)
|
||||
else:
|
||||
logger.info(f"ℹ️ MCP工具未进行调用,继续正常生成")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ MCP工具调用失败,继续使用常规模式: {str(e)}")
|
||||
mcp_reference_materials = ""
|
||||
|
||||
# 使用完整提示词(插入MCP参考资料)
|
||||
yield await SSEResponse.send_progress("准备AI提示词...", 20)
|
||||
prompt = prompt_service.get_complete_outline_prompt(
|
||||
title=project.title,
|
||||
@@ -866,7 +1031,8 @@ async def new_outline_generator(
|
||||
atmosphere=project.world_atmosphere or "未设定",
|
||||
rules=project.world_rules or "未设定",
|
||||
characters_info=characters_info or "暂无角色信息",
|
||||
requirements=data.get("requirements") or ""
|
||||
requirements=data.get("requirements") or "",
|
||||
mcp_references=mcp_reference_materials
|
||||
)
|
||||
|
||||
# 调用AI
|
||||
@@ -879,8 +1045,11 @@ async def new_outline_generator(
|
||||
|
||||
yield await SSEResponse.send_progress("✅ AI生成完成,正在解析...", 70)
|
||||
|
||||
# 提取内容(generate_text返回字典)
|
||||
ai_content = ai_response.get("content", "") if isinstance(ai_response, dict) else ai_response
|
||||
|
||||
# 解析响应
|
||||
outline_data = _parse_ai_response(ai_response)
|
||||
outline_data = _parse_ai_response(ai_content)
|
||||
|
||||
# 删除旧大纲和章节
|
||||
yield await SSEResponse.send_progress("清理旧数据...", 75)
|
||||
@@ -902,7 +1071,7 @@ async def new_outline_generator(
|
||||
history = GenerationHistory(
|
||||
project_id=project_id,
|
||||
prompt=prompt,
|
||||
generated_content=ai_response,
|
||||
generated_content=json.dumps(ai_response, ensure_ascii=False) if isinstance(ai_response, dict) else ai_response,
|
||||
model=data.get("model") or "default"
|
||||
)
|
||||
db.add(history)
|
||||
@@ -957,7 +1126,7 @@ async def continue_outline_generator(
|
||||
user_ai_service: AIService,
|
||||
user_id: str = "system"
|
||||
) -> AsyncGenerator[str, None]:
|
||||
"""大纲续写SSE生成器 - 分批生成,推送进度(记忆增强版)"""
|
||||
"""大纲续写SSE生成器 - 分批生成,推送进度(记忆+MCP增强版)"""
|
||||
db_committed = False
|
||||
try:
|
||||
yield await SSEResponse.send_progress("开始续写大纲...", 5)
|
||||
@@ -1090,13 +1259,72 @@ async def continue_outline_generator(
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ 记忆上下文构建失败: {str(e)}")
|
||||
memory_context = None
|
||||
# 🔍 MCP工具增强:收集续写参考资料
|
||||
mcp_reference_materials = ""
|
||||
enable_mcp = data.get("enable_mcp", True)
|
||||
if enable_mcp:
|
||||
try:
|
||||
yield await SSEResponse.send_progress(
|
||||
f"🔍 第{str(batch_num + 1)}批:使用MCP工具收集参考资料...",
|
||||
batch_progress + 4
|
||||
)
|
||||
logger.info(f"🔍 第{batch_num + 1}批:尝试使用MCP工具收集续写参考资料...")
|
||||
|
||||
# 构建资料收集查询
|
||||
latest_summary = latest_outlines[-1].content if latest_outlines else ""
|
||||
planning_query = f"""你正在为小说《{project.title}》续写大纲。
|
||||
当前进度:已有{len(latest_outlines)}章,即将续写第{current_start_chapter}-{current_start_chapter + current_batch_size - 1}章
|
||||
|
||||
项目信息:
|
||||
- 主题:{data.get('theme') or project.theme}
|
||||
- 类型:{data.get('genre') or project.genre}
|
||||
- 叙事视角:{data.get('narrative_perspective') or project.narrative_perspective or '第三人称'}
|
||||
- 情节阶段:{data.get('plot_stage', 'development')}
|
||||
- 故事发展方向:{data.get('story_direction', '自然延续')}
|
||||
|
||||
最近章节概要:
|
||||
{latest_summary[:200]}
|
||||
|
||||
请搜索:
|
||||
1. 该情节阶段的经典处理手法和技巧
|
||||
2. 适合该发展方向的情节转折和冲突设计
|
||||
3. 符合类型特点的场景设计和剧情元素
|
||||
|
||||
请有针对性地查询1-2个最关键的问题。"""
|
||||
|
||||
# 调用MCP增强的AI(非流式,最多2轮工具调用)
|
||||
planning_result = await user_ai_service.generate_text_with_mcp(
|
||||
prompt=planning_query,
|
||||
user_id=user_id,
|
||||
db_session=db,
|
||||
enable_mcp=True,
|
||||
max_tool_rounds=2,
|
||||
tool_choice="auto",
|
||||
provider=None,
|
||||
model=None
|
||||
)
|
||||
|
||||
# 提取参考资料
|
||||
if planning_result.get("tool_calls_made", 0) > 0:
|
||||
mcp_reference_materials = planning_result.get("content", "")
|
||||
logger.info(f"📚 第{batch_num + 1}批MCP工具收集参考资料:{len(mcp_reference_materials)} 字符")
|
||||
yield await SSEResponse.send_progress(
|
||||
f"📚 第{str(batch_num + 1)}批收集到参考资料 ({len(mcp_reference_materials)}字符)",
|
||||
batch_progress + 4.5
|
||||
)
|
||||
else:
|
||||
logger.info(f"ℹ️ 第{batch_num + 1}批MCP工具未进行调用,继续正常生成")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ 第{batch_num + 1}批MCP工具调用失败,继续使用常规模式: {str(e)}")
|
||||
mcp_reference_materials = ""
|
||||
|
||||
|
||||
yield await SSEResponse.send_progress(
|
||||
f" 调用AI生成第{str(batch_num + 1)}批...",
|
||||
batch_progress + 5
|
||||
)
|
||||
|
||||
# 使用标准续写提示词模板(支持记忆增强)
|
||||
# 使用标准续写提示词模板(支持记忆+MCP增强)
|
||||
prompt = prompt_service.get_outline_continue_prompt(
|
||||
title=project.title,
|
||||
theme=data.get("theme") or project.theme or "未设定",
|
||||
@@ -1115,7 +1343,8 @@ async def continue_outline_generator(
|
||||
start_chapter=current_start_chapter,
|
||||
story_direction=data.get("story_direction", "自然延续"),
|
||||
requirements=data.get("requirements", ""),
|
||||
memory_context=memory_context
|
||||
memory_context=memory_context,
|
||||
mcp_references=mcp_reference_materials
|
||||
)
|
||||
|
||||
# 调用AI生成当前批次
|
||||
@@ -1130,8 +1359,11 @@ async def continue_outline_generator(
|
||||
batch_progress + 10
|
||||
)
|
||||
|
||||
# 提取内容(generate_text返回字典)
|
||||
ai_content = ai_response.get("content", "") if isinstance(ai_response, dict) else ai_response
|
||||
|
||||
# 解析响应
|
||||
outline_data = _parse_ai_response(ai_response)
|
||||
outline_data = _parse_ai_response(ai_content)
|
||||
|
||||
# 保存当前批次的大纲
|
||||
batch_outlines = await _save_outlines(
|
||||
@@ -1142,7 +1374,7 @@ async def continue_outline_generator(
|
||||
history = GenerationHistory(
|
||||
project_id=project_id,
|
||||
prompt=f"[续写批次{batch_num + 1}/{total_batches}] {str(prompt)[:500]}",
|
||||
generated_content=ai_response,
|
||||
generated_content=json.dumps(ai_response, ensure_ascii=False) if isinstance(ai_response, dict) else ai_response,
|
||||
model=data.get("model") or "default"
|
||||
)
|
||||
db.add(history)
|
||||
|
||||
Reference in New Issue
Block a user