Files
life-echo/api/app/agents/chat/slot_question_bank.py
2026-04-09 15:44:14 +08:00

266 lines
17 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.
"""
按人生阶段 × 叙述槽位slot固化「问题大纲」供访谈提示词引用。
- 同一 slot key 在不同 stage 语义不同(如 education.change vs family.change必须分 stage 配置。
- 条目是采集方向/示意问法,模型须在对话中情景化改写,禁止照抄题库原句。
"""
from __future__ import annotations
from app.agents.stage_constants import STAGE_SLOT_KEYS, VALID_CHAT_STAGES
# (stage, slot) -> 有序大纲:从宽泛落到具体,供缺口推进时优先参考
SLOT_QUESTION_OUTLINES: dict[tuple[str, str], tuple[str, ...]] = {
# --- 童年时光 ---
("childhood", "place"): (
"小时候主要是在哪儿长大的——城市、镇上还是村里,能具体到一片街区或一座院子吗?",
"住的地方大概什么样,有没有到现在还记得清的角落(厨房、院子、门槛)?",
"外人一眼能认出的地标或某种气味、声音(河、庙、集市、某种树)是什么?",
"四季里你对那个地方印象最深的是哪个季节、哪种天气里发生的事?",
"若现在闭上眼睛往回走,出门先路过哪条巷、先摸到哪扇门,还记得吗?",
"那个地方后来变了很多吗?你最后一次像小时候那样走在那儿是什么感觉?",
),
("childhood", "people"): (
"那时候最黏、最怕或最佩服的是谁,和你们日常是怎么相处的?",
"带你玩或管你最多的是家人还是祖辈、邻居孩子?有没有一位到现在还会突然想起的人?",
"有没有某个人一句话或一个动作,小时候的你特别当回事?",
"那个人后来还在你生活里吗,还是停在记忆里某个年纪?",
"有没有谁让你第一次觉得「大人原来也会……」——会软、会怕、会不讲理?",
"现在想起ta你会先想到脸、声音还是某件一起做过的小事",
),
("childhood", "daily_life"): (
"不上学的一天通常怎么过,有没有固定的小规矩或小乐趣?",
"放学之后最常去哪儿、和谁在一起,那种日子现在回想是什么颜色的?",
"记忆里常重复出现的一个场景(吃饭、睡午觉、出门玩)愿意多说两句吗?",
"家里吃饭、看电视或听广播有什么固定座位、固定节目吗?",
"有没有一件家务或小活儿是从小就特别会、或特别烦、一直想躲的?",
"零钱、零食、压岁钱这些事,家里规矩严不严,你钻过空子吗?",
),
("childhood", "emotion"): (
"回想小时候,身体哪个地方会先「有感觉」——收紧、发暖还是发酸?",
"那时候整体更像踏实、兴奋、还是有点孤单或紧张?能举一个具体小事吗?",
"有没有一件当时觉得天塌了或特别亮堂的事,现在看又不太一样?",
"小时候敢不敢把真实感受说出口?一般是谁接得住、谁一听就烦?",
"哪种滋味你长大了反而不太敢细想,一提心里会顿一下?",
"若用一个颜色或一种天气形容童年大多数时候,你会选什么——不必合理,凭第一感。",
),
("childhood", "turning_event"): (
"有没有一件事让小时候的你一下子觉得「我跟以前不一样了」?",
"难忘不一定是大事——一次搬家、一次生病、一次被骂或一次被护着也算,你愿意从画面讲起吗?",
"那之后别人对待你的方式,或你对自己的看法,哪儿变了?",
"当时有没有跟谁说破这件事,对方怎么接的,那句话还记得吗?",
"若这件事没发生,你觉得自己会少掉哪一小块脾气或对世界的看法?",
"现在想来,那时候最需要却没说出口的一句安慰或道歉是什么?",
),
# --- 求学经历 ---
("education", "school"): (
"印象最深的一所学校是哪段,校园里你记得清的细节是什么(光线、气味、铃声、操场)?",
"有没有一门课、一位老师或一间教室,想到还会心里一动?",
"那时候和同学之间,最典型的相处方式是什么样的?",
"毕业或转学离开那所学校时,有没有「还没做完」的遗憾?",
"若用一句话形容那所学校对你的「塑形」,你会怎么说?",
"有没有一次集体活动、一次处分或一次表扬,到现在还是同学聚会上会被提起的?",
),
("education", "city"): (
"求学待过哪些城或镇,第一次到那儿下车或进校园时是什么感觉?",
"和老家比,那边最陌生的地方是什么——人、节奏还是规矩?",
"后来有没有哪条街、哪个小店或公交站,和你的一段日子绑在一起?",
"那几年你更像「外来户」整天想家,还是很快就混出了自己的地盘?",
"后来再路过或想起那座城市,第一反应是亲切、恍如隔世,还是五味杂陈?",
"当地吃食、口音或公交习惯,有没有一样跟了你很多年?",
),
("education", "motivation"): (
"当时为什么读书或选这个方向——是自愿、家里期待,还是偶然被推向那条路?",
"有没有谁的一句话、一本书或一件事,真正推了你一把?",
"撑不下去的时候,是靠什么念头把自己劝回书桌前的?",
"有没有一度想放弃、逃开,最后又被什么拽回来的?",
"今天的你回看当时的动力,还会点头,还是觉得年轻得莽、或带着无奈?",
"若当时完全选了另一条路,你现在最怕错过的是哪一段人还是哪一种自己?",
),
("education", "challenge"): (
"求学阶段最难的一段是什么——考试、钱、适应环境,还是家里的事?",
"最难的那会儿,一天里通常怎么扛过去,有没有人帮你垫了一下?",
"回头看,那段难有没有改变你对自己的看法?",
"最难的时候你瞒着谁,又不得不依赖谁?",
"那段经历给你留下什么后来反复用上的本事、或戒心?",
"现在愿意把它当勋章讲,还是更愿意翻篇不提?",
),
("education", "change"): (
"毕业或离开那段求学生活时,和刚入学比,你觉得自己哪块最明显变了?",
"是更知道自己要什么,还是更知道不要什么?能各举一个细节吗?",
"如果有机会对当时的自己说一句话,你会叮嘱什么?",
"外貌、说话方式或看人眼神,有没有被别人点过「你跟以前不一样了」?",
"离开校园踏进下一段人生那一瞬间,最先撞上来的现实是什么?",
"求学时交的朋友,到现在还剩几个能说心里话的?",
),
# --- 职业生涯 ---
("career", "job"): (
"那段工作里你具体在做什么,一天里真实在忙的核心事是什么?",
"有没有一个小场景能代表那份活(开会、跑现场、对客户、写东西)?",
"你最熟练或最头疼的环节是哪一块?",
"这份工作最怕在哪个环节翻车,真的翻过吗,后来怎么收拾的?",
"若向完全外行的人解释你做的事,你会打什么比方?",
"离开那份活之后,还有什么肌肉记忆或口头禅跟了很久?",
),
("career", "environment"): (
"上班或干活的场子什么样——吵、静、乱中有序,还是总在移动?",
"同事或搭档大概怎么相处,有没有固定的小默契(吃饭、抽烟、对表、一块儿吐槽)?",
"那个环境里,什么让你待得下去,什么让你想逃?",
"领导或老板的风格,放手还是盯细,你怎么适应或怎么扛的?",
"换环境之后,有没有突然想念旧地方某一种声音、气味或节奏?",
"团建、年会、加班夜这类集体记忆,有没有一次特别像样的或特别荒唐的?",
),
("career", "decision"): (
"换工作、入行或接某个项目时,有没有一次关键决定是你拍板的?",
"当时心里在权衡什么——钱、体面、家庭、兴趣、还是别的东西?",
"如果重来,你还会那么选吗,哪一步可能会松一点或紧一点?",
"拍板那晚睡得好吗,跟谁商量到吵起来过没有?",
"家人当时站你这边吗,还是你得先说服自己再说服他们?",
"十年后的你看这个决定,会感激、会骂自己,还是两边都有?",
),
("career", "pressure"): (
"压力最大的阶段是什么,外界逼你还是自己逼自己更多?",
"身体或情绪上最先亮红灯的信号是什么(睡不着、胃、脾气)?",
"后来是环境变了,还是你换了应对方式,才缓过来的?",
"崩溃边缘有没有做过什么「完全不像自己」的事?",
"后来聊起那段日子,你会自嘲、沉默,还是能当故事讲?",
"有没有一个人或一次倾诉,真正帮你卸过一点担子?",
),
("career", "growth"): (
"哪一段经历让你觉得能力、心气或看人的眼光真的上了一层?",
"有没有一件当时觉得过不去的事,做完反而长出了新本事?",
"现在回望,你愿意把哪段职业经历称为自己的「底色」?",
"有人实打实带过你吗,还是大多靠自己啃、靠摔?",
"若给那段成长起个小标题,三个字或五个字会叫什么?",
"从坑里爬出来之后,你对「靠谱」或「信任」的看法变了吗?",
),
# --- 家庭生活 ---
("family", "relationship"): (
"和伴侣、父母或孩子之间,最近最常见的一个相处画面是什么?",
"亲昵和疏远在你家里大概怎么分配——是话说得多还是活儿帮得多?",
"有没有一种默契是你们家的「规矩外规矩」?",
"家里说话直来直去还是爱绕弯,吵架了通常谁先低头、谁最硬?",
"有没有一件小事能说明「我们这一家子就这样」,外人觉得怪你们却觉得正常?",
"若用一个词形容家里大多数时候的气氛,你会用什么,为什么?",
),
("family", "conflict"): (
"家里有没有一次争执或冷战让你印象最深,起因其实是什么?",
"后来是时间抹平的还是有人先伸手,中间最难受的是哪几天?",
"那段矛盾过后,关系里是多了道疤还是多了一层理解?",
"那次冲突有没有扯出很久以前的旧账,真正吵的其实是不是另一件事?",
"有没有第三方(长辈、朋友、孩子)意外当了和事佬或火上浇油?",
"现在聊起那次,你们家是讳莫如深、能当笑谈,还是一提还会沉一下?",
),
("family", "support"): (
"难的时候谁最站你这边,对方具体做过一件什么事你记到现在?",
"你又是怎么支持家里人的——出钱、出力、还是稳稳在场?",
"有没有一次你觉得「没有ta那次就真的悬了」",
"家里有人特别会「不说破但一直在」吗,你后来才意识到那种支持多沉?",
"有没有你自以为能扛、结果最后还是家里人帮你兜了一底的经历?",
"支持是双向的吗,还是有一段时期你主要在收、主要在给?",
),
("family", "responsibility"): (
"在家里你扛的主责是什么——钱、照料、决策、还是情绪托底?",
"从什么时候开始你觉得自己是「要主动揽过来」的那个人?",
"这份责任有没有让你骄傲,也有没有让你委屈的时候?",
"有没有和家里人因职责分配闹过别扭,最后是谁调整了、怎么调的?",
"这份主责有没有挤掉你留给自己的时间或身体,你后来怎么补或怎么认命?",
"若卸下这份担子一天,你最先想做什么、又怕谁不适应?",
),
("family", "change"): (
"成家或角色变了(当父母、当主心骨)之后,生活节奏或心态最明显的一处变化是什么?",
"和以前单身或二人世界比,你最怀念和最怕失去的各是什么?",
"如果现在给家里关系打分,你会先改哪一件小事?",
"有没有一次家庭结构的变动(生病、分居、添丁、送走长辈)一下子改了全家相处方式?",
"孩子和爸妈同时在场时,你自己的身份有没有瞬间切换、甚至分裂的感觉?",
"五年或十年后你希望家里「还记得现在这一段」的什么——好赖都算?",
),
# --- 人生信念 ---
("belief", "value"): (
"若要把诚实、自由、家庭、成就、平安排个序,你心里默认的前两位是什么?",
"有没有一条线是你不太愿意让步的,哪怕会吃亏?",
"这套看重的东西,是家里传下来的还是你自己摔打出来的?",
"年轻时和现在,这份排序有没有对调过,是什么事让你松口或咬死了?",
"有没有一种价值你嘴上说不屑、行动上却很诚实?",
"若必须选一个最怕被误解的品质,你会捍卫哪一个,举一个小例子?",
),
("belief", "regret"): (
"若重来会犹豫的一件选择是什么,当时缺的是信息还是勇气?",
"遗憾现在还在拉扯你,还是已经能放在一旁?你怎么和它相处?",
"这份遗憾有没有悄悄改了你后来做决定的方式?",
"有没有人会跟你提起那件遗憾,你一听到就条件反射想挡回去?",
"若能对当时的自己补一句实话,只许一句,你会说什么,用谁的口气?",
"这份遗憾里有没有藏着一丝「其实也不后悔」的复杂?",
),
("belief", "pride"): (
"不一定要大成就——一件你心底觉得「这事我做得对、做得像我自己」的事?",
"那时候外人怎么看不重要,你自己凭什么觉得踏实?",
"骄傲里有没有夹着一点后怕或侥幸?",
"这件事有没有低调到连家里人都不知道全貌,你只偷偷为自己点头?",
"后来有没有人用一句话把你的骄傲一下子说扁了,你怎么接的?",
"若骄傲可以封存成一件具体物,你会选什么——奖状、伤疤、还是一句口头禅?",
),
("belief", "lesson"): (
"如果只能留一句话给后辈或给年轻时的自己,你会留什么?",
"这个道理是从谁身上、哪段经历里磨出来的?",
"有没有一次你差点不信这句话,最后还是被生活按着头认了?",
"这句话有没有反过来坑过你——太当真或太不当真的时候?",
"你现在还会把它教给身边具体某个人吗,怎么开口才不讨人嫌?",
"若这话有一天被你自己推翻,你最怕是因为变世故了,还是因为终于敢诚实了?",
),
}
def _validate_outlines() -> None:
for stage, slots in STAGE_SLOT_KEYS.items():
for slot in slots:
key = (stage, slot)
if key not in SLOT_QUESTION_OUTLINES:
raise RuntimeError(f"slot_question_bank missing outline for {key}")
_validate_outlines()
def outlines_for_stage_slots(
stage: str, empty_slots: list[str]
) -> list[tuple[str, tuple[str, ...]]]:
"""返回 [(slot key, 大纲句...), ...],仅含本阶段且仍在 empty_slots 中的槽。"""
if stage not in VALID_CHAT_STAGES:
return []
empty_set = set(empty_slots)
order = STAGE_SLOT_KEYS.get(stage, ())
out: list[tuple[str, tuple[str, ...]]] = []
for slot in order:
if slot not in empty_set:
continue
key = (stage, slot)
lines = SLOT_QUESTION_OUTLINES.get(key, ())
if not lines:
continue
out.append((slot, lines))
return out
def format_slot_question_outline_block(stage: str, empty_slots: list[str]) -> str:
"""供 system prompt 注入;无缺口时返回空串。"""
from app.agents.chat.prompts_conversation import SLOT_NAME_MAP
rows = outlines_for_stage_slots(stage, empty_slots)
if not rows:
return ""
blocks = [
"## 本阶段问题大纲(仅列仍缺的叙述槽;条目是**采集目标与思路**,不是台词)\n"
"- 每条大纲按**由宽到细**排序;推进缺口时通常优先靠上的条目,但**用户情绪明显起伏时,宁可停在大纲外多接两轮**,不要为凑进度硬问。\n"
"- 发问前必须把大纲句**打散、改写**,嵌进对方刚说的名词/动作/比喻;禁止整段背诵题库原句。\n"
"- 每轮若需要推进缺口,**全段只服务一个槽、最多一个问句**(或无问句只承接)。\n\n"
]
for slot, lines in rows:
label = SLOT_NAME_MAP.get(slot, slot)
blocks.append(f"### {label}\n")
for i, line in enumerate(lines, start=1):
blocks.append(f"{i}. {line}\n")
blocks.append("\n")
return "".join(blocks).rstrip() + "\n\n"