update: 优化剧情分析与章节规划算法,集成伏笔上下文追踪;完善章节删除时的级联清理逻辑

This commit is contained in:
xiamuceer-j
2026-01-19 17:23:50 +08:00
parent dc3dbaaf2c
commit 927072d16f
3 changed files with 308 additions and 31 deletions
+58 -13
View File
@@ -163,7 +163,7 @@ class PlotExpansionService:
batch_size: int,
progress_callback: Optional[callable]
) -> List[Dict[str, Any]]:
"""分批生成章节规划"""
"""分批生成章节规划(增强差异化版本)"""
# 计算批次数
total_batches = (target_chapter_count + batch_size - 1) // batch_size
logger.info(f"分批生成计划: 总共{target_chapter_count}章,分{total_batches}批,每批{batch_size}")
@@ -184,6 +184,9 @@ class PlotExpansionService:
all_chapter_plans = []
# 🔧 收集所有已使用的关键事件,用于防止重复
used_key_events = set()
for batch_num in range(total_batches):
# 计算当前批次的章节数
remaining_chapters = target_chapter_count - len(all_chapter_plans)
@@ -196,20 +199,41 @@ class PlotExpansionService:
if progress_callback:
await progress_callback(batch_num + 1, total_batches, current_start_index, current_batch_size)
# 构建当前批次的提示词(包含已生成章节的上下文
# 🔧 增强的上下文构建(包含完整的差异化信息
previous_context = ""
if all_chapter_plans:
# 构建完整的已生成章节摘要(包含关键事件)
previous_summaries = []
for ch in all_chapter_plans[-3:]: # 显示最近3章
for ch in all_chapter_plans: # 显示所有已生成章节
key_events_str = "".join(ch.get('key_events', [])[:3]) if ch.get('key_events') else ""
previous_summaries.append(
f"{ch['sub_index']}节《{ch['title']}》: {ch['plot_summary'][:100]}..."
f"{ch['sub_index']}节《{ch['title']}》:\n"
f" - 剧情:{ch.get('plot_summary', '')[:150]}\n"
f" - 关键事件:{key_events_str}\n"
f" - 结尾方式:{ch.get('ending_type', '未知')}"
)
# 提取所有已使用的关键事件
all_used_events = []
for ch in all_chapter_plans:
all_used_events.extend(ch.get('key_events', []))
used_events_str = "".join(all_used_events[-20:]) if all_used_events else "暂无"
previous_context = f"""
【已生成章节概要】(接续生成,注意衔接)
{chr(10).join(previous_summaries)}
⚠️ 当前是第{current_start_index}-{current_start_index + current_batch_size - 1}节(共{target_chapter_count}节中的一部分)
"""
【🔴 已生成章节完整信息(必须参考以确保差异化)】
{chr(10).join(previous_summaries)}
【🔴 已使用的关键事件(本批次不可重复使用)】
{used_events_str}
【🔴 差异化强制要求】
⚠️ 当前是第{current_start_index}-{current_start_index + current_batch_size - 1}节(共{target_chapter_count}节中的第{batch_num + 1}批)
⚠️ 每个新章节必须有完全不同的:
1. 开场场景(不同地点/时间/人物状态)
2. 核心事件(不与已生成章节的关键事件重复)
3. 结尾悬念(不同类型的钩子)
⚠️ 新章节的key_events不得与上面【已使用的关键事件】中的任何事件相同或相似
"""
# 获取自定义提示词模板
template = await PromptService.get_template("OUTLINE_EXPAND_MULTI", project.user_id, db)
# 格式化提示词
@@ -501,7 +525,7 @@ class PlotExpansionService:
ai_response: str,
outline_id: str
) -> List[Dict[str, Any]]:
"""解析AI的展开响应(使用统一的JSON清洗方法)"""
"""解析AI的展开响应(使用统一的JSON清洗方法,增强差异化字段"""
try:
# 使用统一的JSON清洗方法
cleaned_text = self.ai_service._clean_json_response(ai_response)
@@ -513,11 +537,30 @@ class PlotExpansionService:
if not isinstance(chapter_plans, list):
chapter_plans = [chapter_plans]
# 为每个章节规划添加outline_id
for plan in chapter_plans:
# 为每个章节规划添加outline_id和差异化标识
for idx, plan in enumerate(chapter_plans):
plan["outline_id"] = outline_id
# 🔧 确保有 ending_type 字段(用于差异化追踪)
if "ending_type" not in plan:
# 根据叙事目标推断结尾类型
narrative_goal = plan.get("narrative_goal", "")
if "悬念" in narrative_goal or "疑问" in narrative_goal:
plan["ending_type"] = "悬念"
elif "冲突" in narrative_goal or "对抗" in narrative_goal:
plan["ending_type"] = "冲突升级"
elif "转折" in narrative_goal:
plan["ending_type"] = "情节转折"
elif "情感" in narrative_goal or "情绪" in narrative_goal:
plan["ending_type"] = "情感收尾"
else:
plan["ending_type"] = f"自然过渡-{idx + 1}"
# 🔧 确保 key_events 是列表且非空
if not plan.get("key_events"):
plan["key_events"] = [f"章节{idx + 1}核心事件"]
logger.info(f"✅ 成功解析 {len(chapter_plans)} 个章节规划")
logger.info(f"✅ 成功解析 {len(chapter_plans)} 个章节规划(含差异化标识)")
return chapter_plans
except json.JSONDecodeError as e:
@@ -533,6 +576,7 @@ class PlotExpansionService:
"emotional_tone": "未知",
"narrative_goal": "需要重新生成",
"conflict_type": "未知",
"ending_type": "未知",
"estimated_words": 3000
}]
except Exception as e:
@@ -547,6 +591,7 @@ class PlotExpansionService:
"emotional_tone": "未知",
"narrative_goal": "需要重新生成",
"conflict_type": "未知",
"ending_type": "未知",
"estimated_words": 3000
}]