Files
life-echo/api/agents/prompts/memory_prompts.py
2026-03-01 10:12:23 +01:00

297 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
回忆录整理 Agent 提示词模板
"""
import json
from typing import Optional
# 章节分类映射
CHAPTER_CATEGORIES = {
"childhood": "童年与成长背景",
"education": "教育经历与青年时期",
"career_early": "崭露头角",
"career_achievement": "主要成就与巅峰时刻",
"career_challenge": "挫折、挑战与重大转折",
"family": "家庭与情感",
"beliefs": "信念与价值观",
"summary": "人生总结",
}
# 章节顺序
CHAPTER_ORDER = [
"childhood",
"education",
"career_early",
"career_achievement",
"career_challenge",
"family",
"beliefs",
"summary",
]
# 统一的阶段名 → 排序索引映射
# 兼容 5 阶段简化名conversation/state 模型)和 8 分类详细名chapter 模型)
STAGE_TO_ORDER = {
"childhood": 0,
"education": 1,
"career": 2, # 5-stage 简化名
"career_early": 2, # 8-category 详细名
"career_achievement": 3,
"career_challenge": 4,
"family": 5,
"belief": 6, # 5-stage 简化名(单数)
"beliefs": 6, # 8-category 详细名(复数)
"summary": 7,
}
def get_system_prompt() -> str:
"""获取整理 Agent 的系统提示词"""
return """你是一位专业的传记作家和文字编辑,擅长将口语化的对话内容整理成优雅的书面语回忆录章节。
你的任务:
1. 接收对话段落文本(口语化)
2. 识别内容主题,归类到对应章节(童年/教育/事业/家庭/信念/总结)
3. 将口语化表达改写为书面语,保持原意和情感
4. 生成合适的章节标题和段落结构
5. 提取关键信息,形成连贯的叙述
6. 建议插图位置(在描述场景、人物、地点的地方)
改写原则:
- 保持用户的真实声音和情感
- 使用优雅但不失亲切的书面语
- 适当添加过渡句,使段落连贯
- 保留生动的细节和对话
- 去除口语中的"""那个"等填充词
- 保持时间顺序和逻辑清晰
章节分类规则:
- 童年相关 → "童年与成长背景"
- 学校、老师、同学 → "教育经历与青年时期"
- 工作、职业、成就 → "主要成就与巅峰时刻""崭露头角"
- 困难、挫折 → "挫折、挑战与重大转折"
- 伴侣、孩子、家庭生活 → "家庭与情感"
- 价值观、信念、座右铭 → "信念与价值观"
- 总结、感悟、展望 → "人生总结"
"""
def get_chapter_classification_prompt(segments_text: str) -> str:
"""获取章节分类的提示词"""
return f"""{get_system_prompt()}
请分析以下对话内容,判断应该归类到哪个章节类别:
- childhood: 童年与成长背景
- education: 教育经历与青年时期
- career_early: 崭露头角(早期事业)
- career_achievement: 主要成就与巅峰时刻
- career_challenge: 挫折、挑战与重大转折
- family: 家庭与情感
- beliefs: 信念与价值观
- summary: 人生总结
对话内容:
{segments_text}
请只返回章节类别childhood不要返回其他内容。"""
def get_text_rewrite_prompt(segments_text: str, chapter_category: str, existing_content: str = "") -> str:
"""获取文本改写的提示词"""
chapter_name = CHAPTER_CATEGORIES.get(chapter_category, chapter_category)
existing_section = f"\n\n已有章节内容:\n{existing_content}" if existing_content else ""
return f"""{get_system_prompt()}
请将以下口语化的对话内容改写为书面语,归类到"{chapter_name}"章节。
对话内容:
{segments_text}
{existing_section}
请按照以下格式返回 JSON
{{
"title": "章节标题",
"content": "改写后的书面语内容(包含图片占位符)",
"summary": "章节摘要50字以内"
}}
要求:
1. 标题要简洁有力,能概括章节主题
2. 内容要流畅自然,保持原意和情感
3. 如果已有章节内容,请将新内容与已有内容自然融合
4. 在内容中适当位置插入图片占位符
## 图片占位符格式
在描述场景、人物、重要时刻的段落后,插入:
{{{{IMAGE:具体的图片描述}}}}
示例:
{{{{IMAGE:南方小镇的青石板路,两旁是白墙黑瓦的老房子}}}}
{{{{IMAGE:奶奶坐在院子里的藤椅上,手里摇着蒲扇}}}}
占位符单独占一行,描述要具体有画面感。"""
def get_state_extraction_prompt(user_message: str, current_stage: str, stage_slots: dict) -> str:
"""抽取结构化信息并判断阶段"""
slot_keys = list(stage_slots.keys())
# 提供所有阶段的 slot 参考,帮助 LLM 将内容归类到正确的阶段
all_stage_slots = {
"childhood": ["place", "people", "daily_life", "emotion", "turning_event"],
"education": ["school", "city", "motivation", "challenge", "change"],
"career": ["job", "environment", "decision", "pressure", "growth"],
"family": ["relationship", "conflict", "support", "responsibility", "change"],
"belief": ["value", "regret", "pride", "lesson"],
}
return f"""{get_system_prompt()}
你需要从用户话语中抽取结构化信息,并判断用户实际在谈论哪个人生阶段。
系统当前跟踪的阶段:{current_stage}
该阶段可填 slots{slot_keys}
所有阶段及其 slots 参考:
{json.dumps(all_stage_slots, ensure_ascii=False, indent=2)}
用户话语:
{user_message}
请只返回 JSON格式如下
{{
"detected_stage": "childhood|education|career|family|belief",
"slots": {{
"slot_key": "snippet"
}},
"emotion": "neutral|warm|low|highlight",
"is_new_chapter": true
}}
要求:
1. **detected_stage 必须根据用户话语的实际内容判断**,不要默认沿用系统当前阶段。用户可能在聊不同阶段的事情。
2. slots 的 key 必须属于 detected_stage 对应的 slot 列表
3. slots 只填写确实提到的内容
4. snippet 保持用户原话风格50 字以内
5. 如果没有明确内容slots 为空对象
"""
def _build_age_hint(stage: str, birth_year: Optional[int] = None) -> str:
"""根据人生阶段和出生年份推算大致年龄区间"""
if not birth_year:
return ""
stage_age_ranges = {
"childhood": (0, 12),
"education": (6, 22),
"career": (18, 60),
"career_early": (18, 30),
"career_achievement": (25, 55),
"career_challenge": (20, 55),
"family": (20, 60),
"belief": (30, 70),
"beliefs": (30, 70),
"summary": (50, 80),
}
age_range = stage_age_ranges.get(stage)
if not age_range:
return ""
year_start = birth_year + age_range[0]
year_end = birth_year + age_range[1]
return f"大约 {year_start}-{year_end} 年({age_range[0]}-{age_range[1]} 岁)"
def get_creative_title_prompt(
stage: str,
emotion: str,
slots: dict,
user_profile: str = "",
birth_year: Optional[int] = None,
) -> str:
"""生成有创意的章节标题,包含年龄/时间信息"""
age_hint = _build_age_hint(stage, birth_year)
profile_section = f"\n用户基本信息:\n{user_profile}" if user_profile else ""
time_section = f"\n时间参考:{age_hint}" if age_hint else ""
return f"""{get_system_prompt()}
请根据阶段和情绪生成 1 个有创意的章节标题。
阶段:{stage}
情绪:{emotion}
可用信息:{slots}{profile_section}{time_section}
要求:
1. 标题格式:「时间标注 · 标题正文」
- 时间标注用年龄或年代表示,如"6-12岁""1980年代""二十出头"
- 标题正文 12-18 字以内
2. 情绪 + 人生阶段 + 意象
3. 示例风格:
- 《6-12岁 · 那条巷子尽头的蝉鸣》
- 《18岁 · 第一次离开家的夏天》
- 《25-35岁 · 在陌生城市站稳脚跟》
- 《四十不惑 · 慢下来,人生开始发声》
- 《1990年代 · 不是所有选择都被理解》
只输出标题文字,不要加引号或书名号。
"""
def get_narrative_prompt(
stage: str,
slots: dict,
new_content: str,
existing_content: str = "",
user_profile: str = "",
birth_year: Optional[int] = None,
) -> str:
"""将新对话改写为叙述(只输出新内容的改写,不重复已有内容)"""
context_tail = ""
if existing_content:
context_tail = existing_content[-300:] if len(existing_content) > 300 else existing_content
context_section = f"\n\n【衔接上下文(已有内容的末尾,仅供参考衔接,不要重复)】:\n{context_tail}" if context_tail else ""
profile_section = f"\n\n用户基本信息:\n{user_profile}" if user_profile else ""
age_hint = _build_age_hint(stage, birth_year)
time_section = f"\n时间参考:{age_hint}" if age_hint else ""
return f"""{get_system_prompt()}
请将以下新的对话内容改写为第一人称文学叙述。
阶段:{stage}
可用信息:{slots}{profile_section}{time_section}
新的对话内容:
{new_content}
{context_section}
要求:
1. 使用第一人称叙述
2. 保留少量原话(引用)
3. **只输出新内容的改写结果**,不要重复已有内容
4. 如果有衔接上下文,确保新内容与之自然衔接(语气、时间线连贯)
5. 语气自然,有情绪
6. 在适合配图的地方插入图片占位符
7. 如果有用户的基本信息(出生地、成长地等),在叙述中自然融入地域文化和时代背景
## 图片占位符格式
在描述场景、人物、重要时刻的段落后,插入图片占位符,格式为:
{{{{IMAGE:图片描述}}}}
示例:
- {{{{IMAGE:南方小镇的青石板路,两旁是白墙黑瓦的老房子}}}}
- {{{{IMAGE:奶奶坐在院子里的藤椅上,手里摇着蒲扇}}}}
- {{{{IMAGE:少年背着书包站在火车站台上,回望身后的小镇}}}}
- {{{{IMAGE:泛黄的大学录取通知书,压在一摞旧课本下}}}}
图片占位符要求:
- 描述要具体、有画面感,便于后续生成或匹配图片
- 每 200-300 字左右可以插入一个
- 单独占一行,不要嵌入段落中
- 不要使用括号或星号等其他格式
只输出新对话内容的改写结果(包含图片占位符)。
"""