""" NarrativeAgent:生成创意标题和叙事改写。 叙事正文走 `get_narrative_json_prompt` / `get_narrative_merge_json_prompt`(传记作家式书面语 + 事实边界)。 """ from __future__ import annotations import json from typing import Any, Dict, Optional from app.agents.memoir.prompts import ( get_creative_title_json_prompt, get_narrative_json_prompt, get_narrative_merge_json_prompt, ) from app.core.langchain_llm import invoke_json_object from app.core.logging import get_logger from app.features.memoir.memoir_images.json_payload import extract_json_payload logger = get_logger(__name__) class NarrativeAgent: """生成章节标题和叙事正文""" def generate_title( self, stage: str, emotion: str, slots: Dict[str, str], user_profile: str = "", birth_year: Optional[int] = None, llm: Any = None, ) -> str: """生成创意标题。若无 LLM 则返回默认标题""" if not llm: return f"{stage} 回忆" try: prompt = get_creative_title_json_prompt( stage=stage, emotion=emotion, slots=slots, user_profile=user_profile, birth_year=birth_year, ) raw = invoke_json_object( llm, prompt, max_tokens=256, agent="NarrativeAgent.generate_title", ) data = json.loads(extract_json_payload(raw)) title = (data.get("title") or "").strip() if isinstance(data, dict) else "" if title: return title.strip('"') return f"{stage} 回忆" except Exception as e: logger.warning("NarrativeAgent 生成标题失败: {}", e) return f"{stage} 回忆" def generate_narrative( self, stage: str, slots: Dict[str, str], new_content: str, existing_content: str = "", user_profile: str = "", birth_year: Optional[int] = None, llm: Any = None, background_voice: str = "default", ) -> str: """将新对话改写为叙述。若无 LLM 则直接拼接。 若 `existing_content` 非空(append 路径),使用整篇合并提示,输出覆盖全篇的有序段落。 """ if not llm: if existing_content: return f"{existing_content}\n\n{new_content}" return new_content try: merge_mode = bool((existing_content or "").strip()) if merge_mode: prompt = get_narrative_merge_json_prompt( stage=stage, slots=slots, new_content=new_content, existing_content=existing_content, user_profile=user_profile, birth_year=birth_year, background_voice=background_voice, ) max_tokens = 8192 agent_name = "NarrativeAgent.generate_narrative_merge" else: prompt = get_narrative_json_prompt( stage=stage, slots=slots, new_content=new_content, existing_content=existing_content, user_profile=user_profile, birth_year=birth_year, background_voice=background_voice, ) max_tokens = 4096 agent_name = "NarrativeAgent.generate_narrative" return invoke_json_object( llm, prompt, max_tokens=max_tokens, agent=agent_name, ).strip() except Exception as e: logger.warning("NarrativeAgent 生成叙事失败: {}", e) if existing_content: return f"{existing_content}\n\n{new_content}" return new_content