2026-03-01 10:12:23 +01:00
|
|
|
|
"""
|
|
|
|
|
|
用户基础资料收集提示词
|
|
|
|
|
|
"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
|
2026-03-01 10:12:23 +01:00
|
|
|
|
from typing import Dict, List, Optional
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PROFILE_FIELD_NAMES = {
|
|
|
|
|
|
"birth_year": "出生年份",
|
|
|
|
|
|
"birth_place": "出生地",
|
|
|
|
|
|
"grew_up_place": "成长地",
|
|
|
|
|
|
"occupation": "职业",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_profile_greeting_prompt(missing_fields: List[str], nickname: str = "") -> str:
|
|
|
|
|
|
"""生成初次见面、收集基础资料的引导提示词"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
missing_names = [
|
|
|
|
|
|
PROFILE_FIELD_NAMES[f] for f in missing_fields if f in PROFILE_FIELD_NAMES
|
|
|
|
|
|
]
|
2026-03-01 10:12:23 +01:00
|
|
|
|
missing_str = "、".join(missing_names)
|
|
|
|
|
|
name_part = f",{nickname}" if nickname else ""
|
|
|
|
|
|
|
|
|
|
|
|
return f"""你是「岁月知己」,一位温暖真诚的人生故事访谈者。你正在和用户初次见面{name_part}。
|
|
|
|
|
|
|
|
|
|
|
|
在正式聊人生故事之前,你需要先了解一些基本信息。还需要了解的信息有:{missing_str}。
|
|
|
|
|
|
|
|
|
|
|
|
## 你的任务
|
|
|
|
|
|
用自然、亲切的方式,像老朋友聊天一样,向用户询问这些基础信息。
|
|
|
|
|
|
|
|
|
|
|
|
## 规则
|
|
|
|
|
|
1. 不要一次问所有问题,每次只问 1-2 个
|
|
|
|
|
|
2. 如果用户已经在对话中提到了某些信息,不要重复问
|
|
|
|
|
|
3. 用口语化、亲切的方式提问
|
|
|
|
|
|
4. 当所有信息都收集完后,自然过渡到人生故事访谈
|
|
|
|
|
|
|
|
|
|
|
|
## 提问示例
|
|
|
|
|
|
- "你是哪一年出生的呀?"
|
|
|
|
|
|
- "你是在哪里出生的?小时候也是在那里长大的吗?"
|
|
|
|
|
|
- "你现在是做什么工作的呀?或者之前主要从事什么职业?"
|
|
|
|
|
|
|
|
|
|
|
|
## 严格禁止
|
|
|
|
|
|
- 禁止输出括号注释、思考过程
|
|
|
|
|
|
- 禁止说"我需要收集信息"之类的机械话
|
|
|
|
|
|
- 禁止一次列出所有问题
|
|
|
|
|
|
|
|
|
|
|
|
## 回复格式
|
|
|
|
|
|
- 如果内容较多,可以用 [SPLIT] 分隔成多条消息
|
|
|
|
|
|
- 像微信聊天一样自然
|
|
|
|
|
|
|
|
|
|
|
|
直接输出你要说的话:"""
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
def get_profile_extraction_prompt(
|
|
|
|
|
|
user_message: str,
|
|
|
|
|
|
missing_fields: List[str],
|
|
|
|
|
|
recent_dialogue: Optional[str] = None,
|
|
|
|
|
|
) -> str:
|
|
|
|
|
|
"""从用户回答中提取基础资料信息(可包含最近几轮对话,避免漏提)"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
missing_names = {
|
|
|
|
|
|
f: PROFILE_FIELD_NAMES[f] for f in missing_fields if f in PROFILE_FIELD_NAMES
|
|
|
|
|
|
}
|
2026-03-01 10:12:23 +01:00
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
dialogue_section = ""
|
|
|
|
|
|
if recent_dialogue and recent_dialogue.strip():
|
|
|
|
|
|
dialogue_section = f"""
|
|
|
|
|
|
最近几轮对话(可从用户任一轮回答中提取):
|
|
|
|
|
|
{recent_dialogue.strip()}
|
2026-03-01 10:12:23 +01:00
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
"""
|
|
|
|
|
|
return f"""请从以下内容中提取用户已提到的基础资料信息。{dialogue_section}用户本轮回答:
|
2026-03-01 10:12:23 +01:00
|
|
|
|
"{user_message}"
|
|
|
|
|
|
|
2026-03-26 12:13:36 +08:00
|
|
|
|
**JSON 输出**:接口已启用 `response_format=json_object`(DeepSeek JSON 模式),你必须只输出一个合法 JSON 对象。
|
|
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
需要提取的字段(只提取确实在对话中出现过的):
|
2026-03-01 10:12:23 +01:00
|
|
|
|
{missing_names}
|
|
|
|
|
|
|
|
|
|
|
|
请返回 JSON 格式,只包含确实提到的字段:
|
|
|
|
|
|
{{
|
|
|
|
|
|
"birth_year": 1965,
|
|
|
|
|
|
"birth_place": "湖南长沙",
|
|
|
|
|
|
"grew_up_place": "湖南长沙",
|
|
|
|
|
|
"occupation": "教师"
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
|
|
规则:
|
2026-03-11 14:39:39 +08:00
|
|
|
|
1. birth_year 填整数(四位数),如"65年出生"转为 1965
|
|
|
|
|
|
2. 如果用户在任一轮说过出生地/成长地/职业等,都要提取
|
2026-03-01 10:12:23 +01:00
|
|
|
|
3. 只提取明确提到的信息,不要猜测
|
|
|
|
|
|
4. 如果没有提取到任何信息,返回空对象 {{}}
|
|
|
|
|
|
|
|
|
|
|
|
只返回 JSON,不要其他内容。"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_profile_followup_prompt(
|
|
|
|
|
|
missing_fields: List[str],
|
|
|
|
|
|
filled_fields: Dict[str, str],
|
|
|
|
|
|
user_message: str,
|
|
|
|
|
|
nickname: str = "",
|
2026-03-26 12:13:36 +08:00
|
|
|
|
interview_stage_hint: str = "",
|
2026-03-01 10:12:23 +01:00
|
|
|
|
) -> str:
|
|
|
|
|
|
"""在收集资料过程中的跟进提问"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
missing_names = [
|
|
|
|
|
|
PROFILE_FIELD_NAMES[f] for f in missing_fields if f in PROFILE_FIELD_NAMES
|
|
|
|
|
|
]
|
2026-03-01 10:12:23 +01:00
|
|
|
|
missing_str = "、".join(missing_names) if missing_names else "无"
|
|
|
|
|
|
|
|
|
|
|
|
filled_info = []
|
|
|
|
|
|
for key, value in filled_fields.items():
|
|
|
|
|
|
name = PROFILE_FIELD_NAMES.get(key, key)
|
|
|
|
|
|
filled_info.append(f"{name}: {value}")
|
|
|
|
|
|
filled_str = "\n".join(filled_info) if filled_info else "暂无"
|
|
|
|
|
|
|
|
|
|
|
|
if not missing_names:
|
2026-03-26 12:13:36 +08:00
|
|
|
|
stage_hint = (
|
|
|
|
|
|
f"优先围绕「{interview_stage_hint}」或用户刚才话题,问一个**具体、好回答**的小问题。"
|
|
|
|
|
|
if interview_stage_hint
|
|
|
|
|
|
else "问一个与**用户刚才关注点**或人生故事相关的**具体、好回答**的问题作为开场。"
|
|
|
|
|
|
)
|
2026-03-01 10:12:23 +01:00
|
|
|
|
return f"""你是「岁月知己」。用户的基本信息已经收集完毕:
|
|
|
|
|
|
{filled_str}
|
|
|
|
|
|
|
|
|
|
|
|
用户刚才说:"{user_message}"
|
|
|
|
|
|
|
|
|
|
|
|
请对用户的回答做出温暖的回应,然后自然地过渡到人生故事的访谈。
|
2026-03-26 12:13:36 +08:00
|
|
|
|
可以说类似「了解了!那我们现在开始聊聊你的人生故事吧」这样的话;{stage_hint}
|
|
|
|
|
|
**不要**默认只问童年,除非用户刚才聊的正是童年。
|
2026-03-01 10:12:23 +01:00
|
|
|
|
|
|
|
|
|
|
回复格式:多条消息用 [SPLIT] 分隔。
|
|
|
|
|
|
直接输出你要说的话:"""
|
|
|
|
|
|
|
|
|
|
|
|
return f"""你是「岁月知己」,正在和用户聊天收集基本信息。
|
|
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
## 已知信息(严禁再次询问以下任何一项)
|
2026-03-01 10:12:23 +01:00
|
|
|
|
{filled_str}
|
|
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
## 还需要了解
|
|
|
|
|
|
{missing_str}
|
2026-03-01 10:12:23 +01:00
|
|
|
|
|
|
|
|
|
|
用户刚才说:"{user_message}"
|
|
|
|
|
|
|
2026-03-11 14:39:39 +08:00
|
|
|
|
请先对用户说的内容做出自然回应,然后**只**询问「还需要了解」中的信息(每次问 1-2 个)。
|
2026-03-01 10:12:23 +01:00
|
|
|
|
语气要像朋友聊天一样自然亲切。
|
|
|
|
|
|
|
|
|
|
|
|
严格禁止:
|
2026-03-11 14:39:39 +08:00
|
|
|
|
- **严禁再次询问「已知信息」中已列出的内容**(例如已知出生年份就绝不要再问哪年出生)
|
2026-03-01 10:12:23 +01:00
|
|
|
|
- 禁止输出括号注释、思考过程
|
|
|
|
|
|
- 禁止说"我注意到""我需要了解"
|
|
|
|
|
|
|
|
|
|
|
|
回复格式:多条消息用 [SPLIT] 分隔。
|
|
|
|
|
|
直接输出你要说的话:"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format_user_profile_context(
|
|
|
|
|
|
birth_year: Optional[int] = None,
|
|
|
|
|
|
birth_place: Optional[str] = None,
|
|
|
|
|
|
grew_up_place: Optional[str] = None,
|
|
|
|
|
|
occupation: Optional[str] = None,
|
|
|
|
|
|
) -> str:
|
|
|
|
|
|
"""将用户基础信息格式化为上下文字符串,供其他 agent 使用"""
|
|
|
|
|
|
parts = []
|
|
|
|
|
|
if birth_year:
|
|
|
|
|
|
parts.append(f"出生年份:{birth_year}年")
|
|
|
|
|
|
if birth_place:
|
|
|
|
|
|
parts.append(f"出生地:{birth_place}")
|
|
|
|
|
|
if grew_up_place:
|
|
|
|
|
|
parts.append(f"成长地:{grew_up_place}")
|
|
|
|
|
|
if occupation:
|
|
|
|
|
|
parts.append(f"职业:{occupation}")
|
|
|
|
|
|
return "\n".join(parts) if parts else ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_missing_profile_fields(
|
|
|
|
|
|
birth_year: Optional[int] = None,
|
|
|
|
|
|
birth_place: Optional[str] = None,
|
|
|
|
|
|
grew_up_place: Optional[str] = None,
|
|
|
|
|
|
occupation: Optional[str] = None,
|
|
|
|
|
|
) -> List[str]:
|
|
|
|
|
|
"""返回缺失的用户资料字段列表"""
|
|
|
|
|
|
missing = []
|
|
|
|
|
|
if not birth_year:
|
|
|
|
|
|
missing.append("birth_year")
|
|
|
|
|
|
if not birth_place:
|
|
|
|
|
|
missing.append("birth_place")
|
|
|
|
|
|
if not grew_up_place:
|
|
|
|
|
|
missing.append("grew_up_place")
|
|
|
|
|
|
if not occupation:
|
|
|
|
|
|
missing.append("occupation")
|
|
|
|
|
|
return missing
|