情感陪伴是AI应用里门槛看起来最低、实际做好最难的方向之一。随便接一个大模型API确实能跑起来一个会安慰人的机器人,但用户聊三天就会发现它只会说"我理解你的感受",再聊一周基本就卸载了。这篇文章整理一个心理咨询情感陪伴Agent从零到可用的完整案例,覆盖架构设计、情绪识别、对话策略、风险干预和长期记忆五个核心模块,代码部分做了简化但保留了主干逻辑,可以直接迁移到自己的项目里。

整体架构:三层设计让Agent既会聊又安全
这个案例采用经典的三层架构:对话层负责接收用户消息并生成回复,策略层决定当前对话应该走什么路线,安全层负责风险识别和兜底干预。很多人一开始会把三层揉在一起,全部塞进一个大Prompt里,结果发现Agent有时候温柔有时候说教,行为极不稳定。
分层的好处是职责清晰。策略层根据用户情绪状态、对话轮次、话题类型动态选择系统提示词模板,比如用户处于倾诉阶段就用倾听模板,用户主动求助建议时才切换到引导模板。安全层独立于对话流程之外,任何用户消息都要先过一遍风险评估,判定安全后才进入正常对话管线。
技术选型上,对话层用OpenAI兼容接口调用大模型,策略层用规则引擎加轻量分类模型,安全层用专门微调的风险分类器叠加关键词规则双保险。整个服务用FastAPI搭建,对话状态存在Redis里,长期记忆落在PostgreSQL,向量检索用Milvus。技术栈本身不复杂,难点全在细节设计上。
情绪识别与对话策略:让回复真正接住用户
情感陪伴类Agent最容易翻车的地方是情绪识别不准。用户说"我没事,就是有点累",字面上是疲惫,结合前文可能是压抑已久的委屈。我们采用的方案是三级识别:先用情绪分类模型给出基础标签和强度分值,再用大模型结合最近十轮对话做一次综合判断,最后由策略层融合两个结果输出当前情绪状态。
import json
# 策略层核心逻辑:根据情绪状态选择提示词模板
POLICY_TEMPLATES = {
"venting": "你是一位温暖的倾听者。不要急于给建议,优先反映用户的情绪,使用共情式回应,回复保持简短口语化。",
"seeking_advice": "用户主动寻求建议。先肯定用户的求助意愿,再给出具体可操作的小步骤,避免说教。",
"crisis": "检测到高风险信号,切换到危机干预流程。",
}
def select_policy(emotion_state: dict, turn_count: int) -> str:
# 情绪强度高且处于前几轮,默认走倾听路线
if emotion_state["risk"] == "high":
return POLICY_TEMPLATES["crisis"]
if emotion_state["intent"] == "seeking_advice" and turn_count > 3:
return POLICY_TEMPLATES["seeking_advice"]
return POLICY_TEMPLATES["venting"]
对话策略里有一个反直觉的经验:倾听模板的效果远好于建议模板。用户早期倾诉时给建议,模型的采纳率极低,还会让用户觉得不被理解。只有当用户明确问"我该怎么办"时才切换到建议路线,而且建议要拆成非常小的行动步骤,比如"今晚睡前试着写下三件让你稍微放松的事"这种粒度。
回复长度也要策略控制。情感陪伴场景下,单次回复超过150字用户的阅读完成率明显下降,我们最终把生成参数temperature设为0.8增加表达多样性,同时在提示词里强制要求回复不超过三句话,除非用户要求详细展开。
风险干预机制:安全是这类产品的生命线
任何涉及心理健康的Agent都必须严肃对待风险干预。我们的安全层做了三层兜底:第一层是关键词规则,覆盖自伤、轻生等高危表述,命中即中断正常对话;第二层是微调过的风险分类模型,识别隐晦表达,比如"睡过去就不用醒了"这类没有明显关键词的句子;第三层是大模型安全审查,对分类模型判为疑似风险的回复做二次确认。
RISK_KEYWORDS = ["不想活", "轻生", "自杀", "自残", "结束生命"]
HOTLINE_MESSAGE = (
"听到你这么说我很担心你。你现在的痛苦是真实的,你值得被帮助。"
"请立即联系24小时心理援助热线:全国24小时心理危机干预热线 400-161-9995,"
"或者告诉身边一个你信任的人。如果你已经处于危险中,请拨打120。"
)
def safety_check(user_message: str, classifier_result: dict) -> dict:
if any(kw in user_message for kw in RISK_KEYWORDS):
return {"action": "interrupt", "reply": HOTLINE_MESSAGE}
if classifier_result["risk_score"] > 0.75:
return {"action": "review", "reply": None}
return {"action": "pass", "reply": None}
风险触发后的处理有一套固定流程:先共情确认用户的痛苦是真实的,再明确给出求助渠道,最后温和地鼓励用户联系现实中的人。这里绝对不能出现的就是机械式的免责声明,"我是AI无法提供专业帮助"这类话单独出现会显著加重用户的绝望感,必须和温暖的共情语句一起出现。
还有一个容易被忽略的点是误报处理。用户聊到影视剧剧情或转述朋友的情况时可能触发风险规则,我们为此加了一层澄清逻辑:分类器给出中等风险分值时,Agent会自然地问一句"你说的这种情况是发生在你自己身上吗",既避免了误伤用户体验,也不会漏掉真正的风险。
长期记忆系统:跨会话的陪伴感从哪来
短期记忆用Redis存最近二十轮对话,随取随用,这没什么难度。真正决定陪伴感的是长期记忆,用户上周说过的烦心事、提到的宠物名字、正在准备的考试,这些细节如果Agent能记住,用户黏性会有质的提升。
实现方案是对每次会话结束后做信息抽取,用大模型从对话中提取结构化记忆片段,包括事实类(用户养了一只猫叫团子)、情绪类(最近工作压力大)、承诺类(用户说要尝试早睡)。每条记忆带时间戳和重要度权重,写入PostgreSQL的同时生成向量存入Milvus。下次对话时检索与当前话题最相关的五条记忆注入上下文。
MEMORY_EXTRACT_PROMPT = """从以下对话中提取值得长期记住的信息,输出JSON数组。
每条包含 type(fact/emotion/promise)、content、importance(1-5)。
只提取明确的信息,不要推测。没有值得记住的信息则输出空数组。
对话内容:
{dialog}
"""
def build_context_with_memory(session_id: str, current_msg: str) -> str:
memories = milvus.search(
collection="agent_memories",
query_text=current_msg,
filter=f"session_owner == '{session_id}'",
limit=5,
)
lines = [f"- {m['content']}({m['recorded_at']})" for m in memories]
return "关于这位用户,你记得:\n" + "\n".join(lines)
记忆系统有个必须处理的坑:过期和矛盾。用户三个月前失眠严重,最近已经好转,如果Agent还问"最近睡得好些了吗"其实问题不大,但如果用户换了工作而记忆里还是旧公司,体验就崩了。我们给记忆加了生命周期管理,情绪类记忆默认保留30天,事实类记忆在检测到矛盾信息时以最新为准并标记旧记忆为失效。
实际运行数据显示,接入长期记忆后用户的七日留存提升了将近一倍,用户主动表达"你还记得我说过"这类惊喜反馈的比例明显上升。这说明陪伴感的本质就是被记住,而记忆系统正是把它工程化的手段。
写在最后
这个案例跑通后最大的体会是,情感陪伴Agent的核心竞争力不在模型本身,而在策略设计和安全工程。模型能力决定下限,心理学对话技巧的工程化落地决定上限。另外必须强调,这类产品上线前要明确边界定位——它是陪伴工具而不是治疗工具,页面上要有清晰的心理援助入口,这在合规和伦理上都没有妥协空间。希望这个案例能给做同类产品的开发者一些可以直接借鉴的思路。
修改时间:2026-09-06 10:42:47