fix:修复智能引入角色/组织的生成逻辑,同时添加数据校验

This commit is contained in:
xiamuceer
2026-01-05 21:04:36 +08:00
parent 2fc10d3da0
commit db4695ef42
3 changed files with 61 additions and 36 deletions
+49 -15
View File
@@ -909,7 +909,8 @@ async def _continue_outline(
stage_instruction = stage_instructions.get(request.plot_stage, "")
# 🎭 【方案A】先角色后大纲:在生成大纲前预测并创建角色
if request.enable_auto_characters:
# 🔧 判断:如果confirmed_organizations存在,说明已经是组织确认阶段,跳过角色处理
if request.enable_auto_characters and not request.confirmed_organizations:
# 检查是否有用户确认的角色列表
if request.confirmed_characters:
# 直接使用用户确认的角色列表创建角色
@@ -920,8 +921,18 @@ async def _continue_outline(
auto_char_service = get_auto_character_service(user_ai_service)
# 🔧 去重检查:获取现有角色名称列表,避免重复创建
existing_character_names = {char.name for char in characters}
actually_created_count = 0
for char_data in request.confirmed_characters:
try:
# 检查角色是否已存在
char_name = char_data.get("name") or char_data.get("character_name")
if char_name in existing_character_names:
logger.warning(f"⚠️ 角色 '{char_name}' 已存在,跳过创建")
continue
# 生成角色详细信息
character_data = await auto_char_service._generate_character_details(
spec=char_data,
@@ -951,6 +962,8 @@ async def _continue_outline(
)
characters.append(character)
existing_character_names.add(character.name) # 更新已存在的角色名称集合
actually_created_count += 1
logger.info(f"✅ 创建确认的角色: {character.name}")
except Exception as e:
@@ -958,7 +971,11 @@ async def _continue_outline(
continue
# 提交角色到数据库
await db.commit()
if actually_created_count > 0:
await db.commit()
logger.info(f"✅ 【确认模式】实际创建了 {actually_created_count} 个新角色(跳过了 {len(request.confirmed_characters) - actually_created_count} 个已存在的角色)")
else:
logger.info(f"ℹ️ 【确认模式】所有角色均已存在,无需创建")
# 更新角色信息(供后续大纲生成使用)
characters_info = "\n".join([
@@ -967,8 +984,6 @@ async def _continue_outline(
for char in characters
])
logger.info(f"✅ 【确认模式】成功创建 {len(request.confirmed_characters)} 个用户确认的角色")
except Exception as e:
logger.error(f"⚠️ 【确认模式】创建确认角色失败: {e}", exc_info=True)
else:
@@ -2058,8 +2073,10 @@ async def continue_outline_generator(
# 🎭 【方案A】先角色后大纲:在生成大纲前预测并创建角色
enable_auto_characters = data.get("enable_auto_characters", True)
confirmed_characters = data.get("confirmed_characters")
confirmed_organizations = data.get("confirmed_organizations")
if enable_auto_characters:
# 🔧 判断:如果confirmed_organizations存在,说明已经是组织确认阶段,跳过角色处理
if enable_auto_characters and not confirmed_organizations:
# 检查是否有用户确认的角色列表
if confirmed_characters:
# 直接使用用户确认的角色列表创建角色
@@ -2075,9 +2092,18 @@ async def continue_outline_generator(
auto_char_service = get_auto_character_service(user_ai_service)
created_count = 0
# 🔧 去重检查:获取现有角色名称列表,避免重复创建
existing_character_names = {char.name for char in characters}
actually_created_count = 0
for char_data in confirmed_characters:
try:
# 检查角色是否已存在
char_name = char_data.get("name") or char_data.get("character_name")
if char_name in existing_character_names:
logger.warning(f"⚠️ 角色 '{char_name}' 已存在,跳过创建")
continue
# 生成角色详细信息
character_data = await auto_char_service._generate_character_details(
spec=char_data,
@@ -2107,7 +2133,8 @@ async def continue_outline_generator(
)
characters.append(character)
created_count += 1
existing_character_names.add(character.name) # 更新已存在的角色名称集合
actually_created_count += 1
logger.info(f"✅ 创建确认的角色: {character.name}")
except Exception as e:
@@ -2115,13 +2142,19 @@ async def continue_outline_generator(
continue
# 提交角色到数据库
await db.commit()
yield await SSEResponse.send_progress(
f"✅ 【确认模式】成功创建 {created_count} 个角色",
28
)
logger.info(f"✅ 【确认模式】成功创建 {created_count}用户确认的角色")
if actually_created_count > 0:
await db.commit()
yield await SSEResponse.send_progress(
f"✅ 【确认模式】实际创建 {actually_created_count}角色(跳过 {len(confirmed_characters) - actually_created_count} 个已存在)",
28
)
logger.info(f"✅ 【确认模式】实际创建 {actually_created_count} 个新角色(跳过了 {len(confirmed_characters) - actually_created_count}已存在的角色")
else:
yield await SSEResponse.send_progress(
f"ℹ️ 【确认模式】所有角色均已存在,无需创建",
28
)
logger.info(f"ℹ️ 【确认模式】所有角色均已存在,无需创建")
except Exception as e:
logger.error(f"⚠️ 【确认模式】创建确认角色失败: {e}", exc_info=True)
@@ -2261,7 +2294,8 @@ async def continue_outline_generator(
# 🏛️ 【组织引入】在生成大纲前预测并创建组织
enable_auto_organizations = data.get("enable_auto_organizations", True)
confirmed_organizations = data.get("confirmed_organizations")
# confirmed_organizations在上面已经获取了,这里注释掉避免重复
# confirmed_organizations = data.get("confirmed_organizations")
if enable_auto_organizations:
from app.models.relationship import Organization
+7 -19
View File
@@ -354,26 +354,14 @@ class AutoCharacterService:
mcp_references="" # 暂时不使用MCP增强
)
# 调用AI生成(使用统一的JSON调用方法
# 调用AI生成(禁用MCP,避免累积超时导致卡死
try:
if enable_mcp and user_id:
result = await self.ai_service.generate_text_with_mcp(
prompt=prompt,
user_id=user_id,
db_session=db,
enable_mcp=True,
max_tool_rounds=2
)
content = result.get("content", "")
# 使用统一的JSON清洗方法
cleaned = self.ai_service._clean_json_response(content)
character_data = json.loads(cleaned)
else:
# 非MCP调用:使用带自动重试的JSON调用
character_data = await self.ai_service.call_with_json_retry(
prompt=prompt,
max_retries=3
)
# 🔧 优化:角色详情生成不使用MCP,只在分析阶段使用MCP
# 这样可以减少大量的外部工具调用,避免超时和卡死
character_data = await self.ai_service.call_with_json_retry(
prompt=prompt,
max_retries=2 # 减少重试次数以加快速度
)
char_name = character_data.get('name', '未知')
logger.info(f" ✅ 角色详情生成成功: {char_name}")
+5 -2
View File
@@ -1892,8 +1892,10 @@ export default function Outline() {
setSSEModalVisible(true);
// 准备请求数据,添加确认的组织
// ⚠️ 移除 confirmed_characters,避免重复创建角色
const { confirmed_characters, ...baseData } = pendingGenerateData;
const requestData = {
...pendingGenerateData,
...baseData,
confirmed_organizations: selectedOrganizations
};
@@ -1953,8 +1955,9 @@ export default function Outline() {
setSSEModalVisible(true);
// 准备请求数据,禁用自动组织引入
const { confirmed_characters, ...baseData } = pendingGenerateData;
const requestData = {
...pendingGenerateData,
...baseData,
enable_auto_organizations: false // 禁用自动组织引入
};