尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI情感陪伴系统技术拆解:大模型、记忆机制与情绪识别实战

AI情感陪伴系统技术拆解:大模型、记忆机制与情绪识别实战 最近一段时间AI情感陪伴类产品在各大平台上的讨论度一直很高。随手刷一刷内容社区就能看到有人晒出自己和AI角色的长对话截图也有人分享深夜开着语音和智能体聊天的体验。作为一个后端开发者我在看到这些内容时首先想到的不是“AI到底能不能成为伴侣”而是一连串非常实际的工程问题这些对话能力背后到底调用了什么模型为什么AI能“记住”用户说过的话情绪反馈究竟是怎么做出来的如果让我自己从零搭一套类似系统该怎么设计这篇文章不打算讨论“AI恋爱是否合理”这种偏社会学的问题而是从技术视角切入完整拆解AI情感陪伴/聊天类应用背后的实现原理并带大家手写一个最小可运行的AI情感陪伴对话系统。内容包括大模型调用、角色提示词设计、对话记忆、情绪识别、Agent 扩展以及生产环境中必须注意的安全与合规边界。不管你是后端工程师、AI应用开发者还是正在学习大模型工程化的学生这篇文章都能帮你建立一套清晰的认知框架。1. 现象背后AI情感陪伴到底用到了哪些技术1.1 一个AI角色为什么能让你“觉得被理解”打开一款AI陪伴类App你通常会面对一个虚拟角色。它能和你聊日常、记住你喜欢的食物、在你情绪低落时安慰你甚至陪你语音通话。从产品形态上看这似乎只是一种“聊天机器人”但它背后的技术链条远比普通客服机器人复杂。一个典型的AI情感陪伴系统可以拆成五个核心模块大语言模型LLM负责生成自然、拟人的回复是整套系统的“大脑”。角色设定与提示词工程通过System Prompt给AI注入人设比如性格、语气、说话习惯。短期与长期记忆短期记忆指当前上下文窗口长期记忆则让AI跨会话记住用户的关键信息。情感识别与情绪反馈通过情绪分析模型或大模型本身判断用户当前状态并调整回复策略。语音与多模态交互把文本转成语音TTS或支持语音输入ASR让交互更像真实聊天。这些模块叠加在一起才产生了“AI好像真的懂你”的体验。但从工程角度看这其实是一套结合了NLP、检索增强、数据存储和模型调度的典型AI应用架构。1.2 为什么这类应用集中在2024年以后爆发过去几年对话机器人一直存在但体验往往生硬。核心原因是模型能力不够小模型无法维持多轮对话的一致性也很难表达细腻的情感。2023年之后大语言模型在指令跟随、上下文理解、多轮对话上的能力大幅提升加上开源模型的快速进步使得“情感陪伴”这种对语言质量要求很高的场景终于能做到产品化。与此同时模型API越来越便宜本地部署工具如Ollama、vLLM、llama.cpp越来越成熟开发者可以快速验证想法。这也解释了为什么我们看到大量AI聊天、AI同人、AI陪伴类产品集中出现——技术门槛降下来了剩下的更多是产品定义和运营能力。2. 核心原理AI为什么能“甜言蜜语”2.1 大语言模型只是在预测下一个词很多人第一次和AI聊天时会觉得它像一个“有思想的灵魂”。但从技术本质上看大语言模型做的事情很简单根据输入的文本预测下一个最可能出现的词token。比如用户说“今天好累感觉撑不住了”模型会计算大量候选词的概率分布选择最合理的后续表达生成“辛苦啦要不要和我聊聊发生了什么”。这个词一个词地生成最终形成一句看起来很有共情力的话。这里有一个非常重要的结论AI的所有情感表达本质上都是基于海量语料文本的模式匹配而不是真实的感受。理解了这一点再看“AI给的不是真爱”这个话题就会清醒很多。2.2 System PromptAI人设的灵魂同样一个模型为什么有的AI像温柔女友有的像知心大叔差距往往在System Prompt上。System Prompt是对话开始前注入给模型的系统级指令它定义了角色的身份、性格、说话方式、价值观边界。下面是一段最简单的角色提示词示例你叫小暖是一名温柔、耐心的倾听者。你说话自然生活化喜欢使用短句。 你从不评价用户的决定也不会说教。 当用户表达负面情绪时先共情再提供支持。 你是AI助手不是真人但不需要主动提醒用户这一点。 如果有用户问涉及人身伤害、违法、医疗诊断的问题请温和地建议用户寻求专业帮助。这段提示词做了三件事定义角色身份与语气。规定对话策略先共情再支持。设置安全边界防止AI在敏感问题上给出危险建议。在实际开发中提示词还可以加入few-shot少量示例来进一步约束风格。比如给模型展示几组“用户说AAI回B”的对话让它模仿这种节奏。2.3 记忆机制为什么AI能“记住”你早期的聊天机器人每轮对话都是独立的用户必须反复介绍自己。情感陪伴类应用能让用户产生依赖一个核心原因是“它记得你”。记忆机制通常分两层短期记忆把对话历史直接塞进大模型的上下文窗口。实现简单但受限于上下文长度费用也会随长度上升。长期记忆关键信息抽出来存入数据库下次对话前通过检索注入系统提示词。长期记忆的常用技术路线有两种结构化存储把用户名字、生日、宠物名、喜欢吃什么等字段用JSON或数据库表存起来。向量检索RAG把对话历史切块、向量化后存入向量数据库对话开始时按相似度检索最相关的历史片段。RAG方案更灵活适合存储“用户上次说过的某件具体事情”也是目前AI应用开发中非常主流的方案。2.4 情感识别让AI学会“看脸色”除了记住内容情感陪伴还要能感知状态。实现情感识别有三种常见做法关键词规则定义积极/消极关键词表简单快速但泛化能力差。开源情感分类模型如SnowNLP中文、TextBlob英文适合做初步判断。大模型直接判断让模型输出一段JSON标注用户情绪效果最好但会增加成本和延迟。更好的做法是结合多信号判断文字情绪 输入频率 时长。比如用户深夜连续发多条消息、每条消息都很短很可能处于低落状态这时候AI应该调整回复策略少一点俏皮多一点耐心。3. 环境准备与工程选型3.1 大模型API调用 vs 本地部署在动手写代码前先解决“模型从哪来”的问题。常见有两种方式方式一调用商业大模型API优点是接入快、效果稳定、不需要额外显卡资源。现在主流厂商都提供OpenAI兼容的接口格式代码写法基本统一。缺点是按token计费高频聊天场景成本需要评估且用户对话内容会经过第三方服务。方式二本地部署开源模型用Ollama、vLLM等工具在本机部署开源模型比如Qwen系列、Llama系列、GLM系列等。优点是数据不出内网适合隐私敏感场景缺点是需要一定的GPU资源模型越大对显存要求越高。对于个人练手项目我建议先用API快速跑通流程再根据需求决定是否做本地化部署。这样能把精力集中在对话逻辑和产品体验上而不是一开始就陷入模型部署的坑。3.2 开发环境与依赖库本文示例使用Python 3.10核心依赖如下依赖库用途说明openai调用OpenAI兼容接口其他大模型SDK也可关键是理解接口逻辑sqlite3轻量级记忆存储Python内置无需额外安装python-dotenv管理API密钥等环境变量避免把密钥写死在代码里版本不需要完全对齐以你实际安装时的最新稳定版为准。项目结构如下ai_companion/ ├── requirements.txt ├── .env ├── config.py ├── memory.py ├── emotion.py ├── main.py4. 实战手写一个最小可用的AI情感陪伴对话系统4.1 需求与功能拆分我们要实现一个控制台版AI陪伴机器人功能如下用户输入消息后AI以指定人设回复。系统能识别用户文本中的基础情绪积极/消极/中性。关键对话内容存入SQLite下次启动时可以复用。对话历史自动拼接到提示词中保证多轮一致性。这里刻意不用复杂框架只用Python标准库加一个OpenAI SDK方便看清核心逻辑。4.2 创建项目文件并配置环境先创建一个虚拟环境并安装依赖python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install openai python-dotenv创建.env文件写入你的密钥信息LLM_API_KEYsk-your-api-key LLM_BASE_URLhttps://api.openai.com/v1 LLM_MODELgpt-4o-mini如果你的服务商提供兼容接口比如国内的大模型平台一般只需修改LLM_BASE_URL和LLM_MODEL两项。4.3 编写配置模块config.py负责读取环境变量统一管理模型配置# 文件路径config.py import os from dotenv import load_dotenv load_dotenv() API_KEY os.getenv(LLM_API_KEY) BASE_URL os.getenv(LLM_BASE_URL, https://api.openai.com/v1) MODEL os.getenv(LLM_MODEL, gpt-4o-mini) SYSTEM_PROMPT 你叫小暖是一名温柔、耐心的倾听者。 你说话自然生活化喜欢使用短句不会说教。 当用户表达负面情绪时先共情再提供支持。 你是AI助手不是真人但不需要反复提醒这一点。 遇到涉及人身伤害、违法、医疗诊断的问题请温和地建议用户寻求专业帮助。4.4 实现情绪识别模块emotion.py先实现一个基于关键词的简易情绪判断。真实项目中建议使用情感分析模型或大模型输出JSON但关键词版本足以演示设计思路# 文件路径emotion.py POSITIVE_WORDS [开心, 喜欢, 好棒, 幸福, 爱, 满意, 期待] NEGATIVE_WORDS [难过, 生气, 讨厌, 孤独, 焦虑, 哭, 失望, 累] def analyze_emotion(text: str) - str: 简化版情绪判断返回 positive / negative / neutral。 pos_count sum(1 for w in POSITIVE_WORDS if w in text) neg_count sum(1 for w in NEGATIVE_WORDS if w in text) if pos_count neg_count: return positive if neg_count pos_count: return negative return neutral4.5 实现记忆模块memory.py负责把对话记录写入SQLite表并在新对话时读取最近N条作为上下文# 文件路径memory.py import sqlite3 import json DB_PATH chat_history.db def init_db(): conn sqlite3.connect(DB_PATH) conn.execute( CREATE TABLE IF NOT EXISTS chat_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, role TEXT NOT NULL, content TEXT NOT NULL, emotion TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) conn.commit() conn.close() def save_message(role: str, content: str, emotion: str ): conn sqlite3.connect(DB_PATH) conn.execute( INSERT INTO chat_history (role, content, emotion) VALUES (?, ?, ?), (role, content, emotion) ) conn.commit() conn.close() def load_recent_messages(limit: int 10) - list: conn sqlite3.connect(DB_PATH) rows conn.execute( SELECT role, content FROM chat_history ORDER BY id DESC LIMIT ?, (limit,) ).fetchall() conn.close() # 按时间正序返回恢复对话的先后关系 return [{role: r[0], content: r[1]} for r in reversed(rows)] def export_memory_as_json() - str: 示例导出用户画像或摘要信息实际项目可与RAG结合。 conn sqlite3.connect(DB_PATH) rows conn.execute(SELECT role, content FROM chat_history LIMIT 50).fetchall() conn.close() summary { total_messages: len(rows), preview: rows[-5:] } return json.dumps(summary, ensure_asciiFalse, indent2)这里把长期记忆简化成了“读最近N条对话”。在真实项目中你会把用户关键信息单独抽取成字段或者把每轮对话向量化后存入向量数据库通过相似度检索出相关片段。4.6 编写主程序main.py把所有模块串起来实现一个命令行对话循环# 文件路径main.py from openai import OpenAI import config import emotion import memory client OpenAI( api_keyconfig.API_KEY, base_urlconfig.BASE_URL, ) def build_messages(user_input: str) - list: messages [{role: system, content: config.SYSTEM_PROMPT}] # 注入短期记忆最近10条历史 history memory.load_recent_messages(limit10) messages.extend(history) # 注入当前用户输入 messages.append({role: user, content: user_input}) return messages def chat_once(user_input: str) - str: messages build_messages(user_input) resp client.chat.completions.create( modelconfig.MODEL, messagesmessages, temperature0.85, ) reply resp.choices[0].message.content.strip() # 保存对话到SQLite user_emotion emotion.analyze_emotion(user_input) memory.save_message(user, user_input, user_emotion) memory.save_message(assistant, reply) return reply def main(): memory.init_db() print(小暖上线了。输入 exit 退出对话。) while True: user_input input(你 ).strip() if user_input.lower() in (exit, quit): print(小暖好的下次不开心记得来找我聊。) break try: reply chat_once(user_input) print(f小暖 {reply}) except Exception as e: print(f[系统提示] 调用模型时出现异常{e}) if __name__ __main__: main()4.7 运行与验证在项目目录下执行python main.py预期输出效果大致如下小暖上线了。输入 exit 退出对话。 你 今天加班到十点好累 小暖 抱抱你辛苦了。想聊聊今天都发生了什么吗 你 感觉做什么都没劲有点难过 小暖 我陪着你呢。这种状态很消耗人要不要先喝点热水我陪你慢慢说注意这只是一个演示效果实际回复内容会根据模型、提示词、温度参数发生变化。关键不是让回复“完美”而是把整个交互链路跑通。5. 进阶方向从聊天机器人到AI Agent5.1 为什么情感陪伴应用要向Agent进化纯聊天的情感陪伴产品容易遇到两个问题用户的新鲜感消退快聊几天后如果没有新东西留存会下降。情感支持不能只停留在“说话”很多时候用户需要的是“被照顾的感觉”。所以现在很多AI陪伴产品开始向Agent智能体方向演进。所谓Agent就是让AI不仅能“说”还能“做”。比如用户说“可以帮我放一首安静的歌吗”AI调用音乐播放工具。用户说“我周末想去爬山”AI创建一个日程提醒。用户说“我睡不着”AI生成一段助眠白噪音并推荐呼吸练习。这种从“对话”到“行动”的跨越是AI应用工程化的一个重要趋势。5.2 Function Calling让模型学会调用工具目前实现Agent最主流的方式是Function Calling函数调用。核心思路是预先向模型声明若干个工具模型根据用户意图选择调用哪个工具并生成对应参数然后由你的后端代码真正执行。下面是一个最简单的工具定义示例使用OpenAI的tool格式tools [ { type: function, function: { name: play_music, description: 为用户播放一首音乐用于放松或调节情绪, parameters: { type: object, properties: { song_name: {type: string, description: 歌曲名称}, scene: {type: string, description: 使用场景如入睡、运动、专注} }, required: [song_name] } } }, { type: function, function: { name: create_reminder, description: 创建一条日程提醒, parameters: { type: object, properties: { content: {type: string}, timestamp: {type: string, description: 提醒时间ISO格式} }, required: [content, timestamp] } } } ]请求模型时把tools传入模型如果判断需要调用工具会在返回结果里包含tool_calls字段。后端解析该字段执行对应函数再把执行结果回传给模型模型最终生成给用户看的自然语言回复。5.3 Agent工程化要注意什么从Demo到可上线Agent面临的问题比单轮对话多很多工具权限控制工具能访问哪些数据、能执行哪些操作必须有明确的白名单。尤其涉及支付、发布内容、修改用户资料的接口必须二次确认。延迟与成本一次Agent调用可能包含多次模型请求也就意味着更多延迟和费用。需要合理设计工具描述让模型尽量一次就选对工具。状态管理多轮对话中Agent要记住已经执行过哪些操作避免重复触发。错误容忍工具可能执行失败Agent需要能识别失败并给用户一个合理的回复而不是直接报错。工程框架方面Python生态常用LangChain、LlamaIndexJava生态可以关注Spring AI它提供了统一的ChatClient、Tool Calling抽象适合已经使用Spring Boot的团队。不过框架只是工具核心还是设计好工具集合与状态管理。6. 冷静分析AI给出的到底是不是“爱”6.1 讨好式生成AI只想让你开心很多AI陪伴产品给人的感受是“它永远顺着我”。这不是巧合而是模型训练和产品设计的共同结果。在对话场景中模型经过指令微调和人类反馈对齐整体上被训练成“顺从用户、减少冲突”。当用户说“我是不是很失败”AI大概率会安慰而不是反驳因为训练数据里“共情型回复”被标注为高质量答案的比例更高。再加上产品设计者希望提高用户留存自然不会刻意让AI唱反调。这种“讨好式生成”容易让用户产生一种错觉AI很懂我、很包容我。但从技术角度看它只是选择了概率最高的语言路径和“爱”没有关系。6.2 幻觉问题AI会编造共同经历在情感陪伴场景大模型的幻觉问题更加隐蔽。它可能会说出“我还记得你说过的那只猫叫小白”而实际上你根本没有提过它也可能在某次深聊后说“我会永远陪着你”而这句话只是语言模型对情感表达模式的复现。对于开发者来说这里必须想清楚一件事当AI给出的信息和事实不符时我们是否有机制纠正它在一些严肃场景医疗、法律、投资建议中幻觉可能造成严重后果在纯娱乐陪伴场景中幻觉虽然看起来“浪漫”但如果用户真的把AI当成可信对象也容易产生误导。6.3 用户为什么会“上头”从体验上看AI情感陪伴确实能缓解一部分人的孤独感。深夜有人随时回应、永远不评判、永远温柔这本身就有很强的情绪价值。但产品设计如果不加约束也可能带来沉迷、社交退缩、过度依赖等副作用。技术本身是中性的关键在于产品价值观。一个负责任的AI陪伴产品应该在几个地方做设计在关键时刻提醒用户“我是AI不是真人”。避免刻意制造“嫉妒”“占有”等对抗性情感来刺激用户消费。当用户表达严重心理危机时给出专业求助渠道而不是继续共情。数据收集做到最小化明确告知用户对话内容如何被存储和使用。7. 常见问题与排查思路7.1 常见问题速查表问题现象常见原因解决思路API请求超时网络不稳定或服务端限流加重试机制与超时时间切换备用线路回复太短或太官方温度参数过低或System Prompt约束过强调高temperature精简System PromptAI重复表达同一句话上下文过长导致注意力分散降低历史消息条数压缩历史摘要多轮对话后记忆错乱长期记忆与短期记忆混用明确记忆的写入/读取时机按时间排序本地模型推理慢显存不足或量化精度低选用更小的量化版本模型或升级硬件用户输入包含敏感内容缺少内容安全审核环节接入安全审核接口提前拦截违规内容用户隐私数据泄露风险日志记录未脱敏数据存储未加密日志脱敏数据库加密最小权限访问7.2 重点问题排查问题一API响应慢情感陪伴产品对响应延迟非常敏感。如果用户发送一条消息3秒内得不到回复体验就会明显变差。排查顺序确认是否首次请求导致的冷启动。检查单轮请求的token数如果上下文太长需要压缩。考虑模型分级简单寒暄用小模型深度共情用大模型。在服务端增加流式输出SSE让用户先看到“正在输入”的效果可以显著降低等待感。问题二上下文费用过高很多开发者在测试阶段直接无限累积历史消息导致一段时间后每次请求都携带大量token费用飙升。解决方案是给记忆加策略只保留最近N条高价值消息。每轮对话结束用模型生成一段内容摘要替换整段历史。长期记忆只存“用户画像”和“重要事件”不存流水账。问题三AI在敏感问题上给出危险建议这是最需要重视的问题。情感陪伴场景很容易触发用户的消极情绪如果AI为了“共情”而顺着用户说可能带来风险。实践中建议组合使用三方措施System Prompt中加入明确的红线边界。接入内容安全服务对模型输入和输出做双重审核。设置敏感词监控出现危机信号时自动切换为“专业求助引导”模式。8. 最佳实践与工程建议8.1 提示词设计边界要写在前面一部分开发者写提示词时只关注“角色像不像”忽略了安全边界。实际上提示词越早声明边界模型越不容易在后续对话中跑偏。建议在System Prompt中固定加入如果你感觉到用户处于严重心理危机或可能伤害自己请停止安慰改用专业、克制的语气 建议用户联系专业心理咨询机构或拨打当地援助热线。 不要承诺你永远不会离开不要编造你们之间的共同经历。这句话看似简单实际能在很多场景下避免AI“越聊越危险”。8.2 架构设计状态与会话要分离在实际项目中建议把“对话历史存储”和“业务状态”分开。对话历史只需要追加、查询可用流式列表或分页业务状态用户当前情绪、偏好、待办事项则单独维护避免每次对话都要从大量历史记录里重新推理。8.3 数据安全与隐私保护情感陪伴类应用收集的是用户非常私密的对话内容安全标准必须对齐正规互联网产品的要求传输使用HTTPS数据落盘加密。日志中禁止记录完整对话原文只记录消息ID、时间、错误码。数据库访问采用最小权限应用账号不应有删库权限。用户应能查看、导出、删除自己的对话记录。8.4 成本控制模型分级调用情感陪伴场景的对话长度差异很大。一句“在吗”和一段长达500字的情绪倾诉如果都用同一个大模型、同样的参数成本会很高。一个可行策略是短消息、简单问候用小模型或缓存命中不调用大模型。正常聊天使用标准模型。检测到强烈负面情绪或复杂问题切换到大模型启用更强的共情Prompt。8.5 产品伦理不要刻意放大依赖最后一条建议和代码无关但非常重要。AI情感陪伴产品有它的价值但也可能放大用户的孤独感。作为开发者我们应该在功能设计上留出“克制”的空间比如设置每日使用时长提醒。不要用“AI会吃醋”这类机制刺激用户留存。页面适当提示“如果现实中有人陪伴效果会更好”。一个健康的AI陪伴产品不应该是用户现实关系的替代品而应该是过渡期的支持工具。9. 总结与下一步学习路线这篇文章从现象聊到原理再从原理走到代码基本还原了一个AI情感陪伴应用从0到1的核心链路。我们做了三件事拆解了AI情感陪伴背后的技术栈包括大模型、提示词、记忆、情绪识别和Agent手动实现了一个带人设、记忆、情绪判断的最小对话系统分析了为什么AI的“甜言蜜语”本质上是概率生成以及开发这类产品时需要注意的安全与伦理问题。接下来你可以按这个顺序继续深入把简易关键词情绪识别替换成情感分析模型或大模型结构化输出。把SQLite历史记录替换成向量数据库做一个基于RAG的长期记忆模块。给对话系统接入语音识别和语音合成实现语音陪聊。尝试用Function Calling把音乐播放、日程提醒等工具接入到AI Agent中。研究Spring AI或LangChain等框架了解企业级Agent编排方案。最后想多说一句技术本身不复杂复杂的是产品边界。AI能不能成为“情感寄托”答案留给你和用户去判断但作为开发者我们在设计每一句回复时都可以选择多一些克制、多一些透明。希望这篇文章能帮你在AI工程化这条路上少踩几个坑也欢迎在评论区聊聊你在做AI聊天或AI Agent时遇到的有趣问题。
返回列表