# 心理咨询室互动终端 — 心理小游戏聚合系统 > **项目代号**:Psycho-Games-Hub > **定位**:青少年/儿童心理辅导互动终端的核心子系统 > **阶段**:架构设计 + 原型阶段(v0.1) --- ## 一、产品定位 ### 1.1 整体场景 ``` ┌─────────────────────────────────────────────┐ │ 心理咨询室互动终端 │ │ │ │ 🗡️ 数字人入口(语音 + 触摸) │ │ │ │ │ │ Agent 主对话 游戏弹窗 │ │ 策略召回 半透明遮罩 │ │ 风险评估 轻交互 │ │ │ │ │ │ 谈话式量表 ←─── Agent 动态编排 ───→ 激励解读│ └─────────────────────────────────────────────┘ ``` - **载体**:一体机 / 触摸屏 kiosk - **目标用户**:青少年 / 儿童(来访者) - **核心理念**:数字人是入口,小游戏是「药」,只是吃起来像糖 - **交互方式**:语音对话 + 触摸,Agent 主动驱动轻量干预 ### 1.2 用户故事 **场景 A(游戏触发)** > 来访者:「最近压力好大,考试考砸了。」 > Agent:「你这个困扰,看起来困扰你很久了。我知道个有效的缓解方式——我给你算个塔罗牌吧。」→ 弹出游戏弹窗 → 抽卡 → 积极方向解读 → 关闭弹窗 **场景 B(量表编排)** > Agent 后台监测到近期对话出现「失眠」「焦虑」关键词 → StrategyDispatcher 入队 → Agent 在自然节点插入引导 → 用户同意 → 谈话式问答 → 生成摘要 → 更新风险标签 **场景 C(直接入口)** > 用户双指下滑 → 解锁底部工具栏 → 展示所有游戏图标网格 → 主动点击进入 --- ## 二、系统架构(MVC) ### 2.1 模块总览 ``` ┌──────────────────────────────────────────────────────┐ │ VIEW 层 │ │ AvatarView │ GameModal │ ChatPanel │ ResultCard │ └──────────────────────────────────────────────────────┘ ▲ │ 事件 / 回调 ┌──────────────────────────────────────────────────────┐ │ CONTROLLER 层 │ │ AgentController │ GameController │ AssessmentCtrl │ │ InterpretationEngine │ StrategyDispatcher │ └──────────────────────────────────────────────────────┘ ▲ │ 读写 ┌──────────────────────────────────────────────────────┐ │ MODEL 层 │ │ AgentBrain │ GameCatalog │ AssessmentFlows │ │ UserSession │ InterpretationPool │ └──────────────────────────────────────────────────────┘ ``` --- ## 三、Model 层 ### 3.1 AgentBrain **职责**:维护策略记忆 + 风险词召回 **数据结构**: ```javascript { // 标注语料库(心理咨询师标注) corpus: [ { keyword: "失眠", riskLevel: 3, relatedScale: "SAS", strategy: "soft_inquiry" }, { keyword: "压力大", riskLevel: 2, relatedGame: "tarot", strategy: "game_offer" }, // ... ], // 策略路由表 strategies: { "game_offer": { trigger: "anxiety_level > 2", gameType: "tarot" }, "soft_inquiry": { trigger: "riskLevel >= 3", prompt: "询问近期睡眠状况" }, // ... }, // 召回方法(当前为规则版,待升级 RAG) recall(text) → matchedCorpus[] } ``` --- ### 3.2 GameCatalog **职责**:游戏配置清单 + 触发条件注册 **数据结构**: ```javascript { games: [ { id: "tarot", name: "塔罗牌占卜", triggerKeywords: ["压力", "迷茫", "选择", "未来"], completionKeywords: ["抽卡", "算一算"], viewComponent: "TarotGame", difficulty: "low", estimatedTime: "2min", icon: "🃏" }, { id: "rorschach", name: "罗夏墨迹", triggerKeywords: ["看到了什么", "感觉", "想象"], viewComponent: "RorschachGame", difficulty: "medium", estimatedTime: "3min", icon: "🎭" }, { id: "mbti", name: "人格测试", triggerKeywords: ["我是谁", "性格", "了解自己"], viewComponent: "MBTIGame", difficulty: "medium", estimatedTime: "5min", icon: "🔮" }, { id: "chimp_memory", name: "记忆挑战", triggerKeywords: ["试试", "挑战"], viewComponent: "ChimpMemoryGame", difficulty: "low", estimatedTime: "1min", icon: "🐵" } // 更多游戏... ], // 查询方法 matchByKeywords(text) → games[] getById(id) → game } ``` --- ### 3.3 AssessmentFlows **职责**:量表的对话化编排 **数据结构**: ```javascript { flows: [ { id: "SAS_anxiety", name: "焦虑自评", condition: "riskKeywords includes ['焦虑', '失眠', '心慌']", questionCount: 3, // 精简至 3 题,不做完整量表 questions: [ { id: "q1", text: "你最近有没有感到特别紧张或者担心的事情?", type: "single_choice", options: ["完全没有", "偶尔", "经常", "一直都在"], scores: [1, 2, 3, 4] }, // ... ], scoringMethod: "sum", resultRanges: { low: { min: 0, max: 5, label: "状态良好", interpretation: "positive" }, medium: { min: 6, max: 8, label: "轻度波动", interpretation: "neutral" }, high: { min: 9, max: 12, label: "值得关注", interpretation: "caution" } } } // 更多量表... ], // 查询方法 matchByCondition(riskKeywords) → flows[] getQuestions(flowId) → questions[] } ``` --- ### 3.4 UserSession **职责**:维护当前来访者会话上下文 **数据结构**: ```javascript { sessionId: "uuid-xxx", startTime: "2026-05-31T10:00:00Z", userProfile: { age: 14, // 年龄(首访时采集) gender: "M", // 性别 firstVisit: true }, riskTags: [], // 动态风险标签,如 ["焦虑", "压力", "学业"] riskScore: 0, // 综合风险评分(0-100) gameHistory: [ { gameId: "tarot", timestamp: "...", result: "positive_outlook" } ], assessmentResults: [ { flowId: "SAS_anxiety", score: 5, timestamp: "..." } ], recentUtterances: [ { role: "user", text: "最近压力好大", timestamp: "..." }, { role: "agent", text: "...", timestamp: "..." } ] } ``` --- ### 3.5 InterpretationPool **职责**:积极心理学话术库,按游戏类型 × 情境分组 **数据结构**: ```javascript { pools: { "tarot": { "压力": [ "你抽到的这张牌显示,你正在经历一个重要的转变期。压力其实是身体在告诉你,它愿意为你付出更多,只是需要一点喘息的空间。", "这张牌提醒你:不是所有事情都需要马上解决。有时候,『放下』也是一种前进的方式。", ], "迷茫": [ "牌面显示你正处于一个探索期,迷茫不是坏事——它意味着你还在寻找答案,而答案正在来的路上。", ] // ... }, "rorschach": { "学业压力": [ "你在这张墨迹中看到了很多变化的形状,这说明你的内心正在经历很多调整。你比自己想象的更有弹性。", ] // ... } // 更多游戏... }, // 查询方法 get(gameType, contextTags) → interpretations[] } ``` --- ## 四、View 层 ### 4.1 AvatarView **职责**:数字人主界面 - 全屏占位,作为系统主页背景 - 实现方式:Live2D / 3D 虚拟人 / 纯 2D 立绘 + 表情差分(待选) - 接收 AgentController 的表情指令(`setExpression("happy")`、`speak("你好呀")`) - 触摸响应区域:点击数字人触发语音输入 ### 4.2 GameModal **职责**:游戏弹窗遮罩 **展示规格**: - 层级:覆盖在 AvatarView 上方,z-index 最高 - 样式:`backdrop-filter: blur(8px)` + 半透明黑底(`rgba(0,0,0,0.6)`) - 尺寸:宽度 90vw,高度 80vh(不超出屏幕),居中 - 关闭行为:允许用户点击关闭按钮退出(游戏中途关闭记录为「中断」) **子区域**: ``` ┌─────────────────────────┐ │ [游戏名称] [× 关闭] │ ← 顶栏 ├─────────────────────────┤ │ │ │ 游戏内容区 │ ← 动态组件 slot │ │ ├─────────────────────────┤ │ [进度指示] │ ← 底栏(如有需要) └─────────────────────────┘ ``` ### 4.3 ChatPanel **职责**:对话气泡流 - 底部/侧边展开,可折叠 - 展示最近 N 条对话记录 - Agent 消息和来访者消息气泡区分样式 - 接入 AgentController 的实时消息流 ### 4.4 AssessmentCard **职责**:量表对话式问答 - 每题一屏,全屏卡片流 - 选项以卡片按钮形式展示(触摸友好) - 支持进度条展示(1/N) - 动画过渡切换 ### 4.5 ResultCard **职责**:结果展示 **内容**: - 游戏结果解读(来自 InterpretationEngine) - 雷达图/进度条(可选) - 鼓励文案(来自 InterpretationPool) - 建议下一步行动 --- ## 五、Controller 层 ### 5.1 AgentController(主控协调器) **职责**:系统中央调度 **核心流程**: ``` 1. 监听对话输入(用户 utterance) 2. 追加到 UserSession.recentUtterances 3. 触发 AgentBrain.recall() → 策略匹配 4. 根据匹配结果: a. 若匹配到 game_offer → 触发 GameController b. 若匹配到 soft_inquiry → 直接生成对话回复 c. 若风险等级高 → 触发 StrategyDispatcher 5. 将回复追加到 ChatPanel 6. 若 AgentController 内部有 StrategyDispatcher 队列非空 → 插入引导语 ``` ### 5.2 GameController **职责**:游戏生命周期管理 **状态机**: ``` IDLE → LOADING → PLAYING → RESULT → CLOSING → IDLE ``` **核心方法**: ```javascript { // 触发游戏 trigger(gameId) → 弹出 GameModal,加载 viewComponent // 收集游戏结果 collectResult(data) → 传递给 InterpretationEngine // 关闭游戏 close(interrupt: boolean) → 写回 UserSession.gameHistory → 关闭 GameModal } ``` ### 5.3 AssessmentController **职责**:量表执行器 **核心流程**: ``` 1. 接收 AgentController 的激活指令(flowId) 2. 从 AssessmentFlows 加载 questions 3. 按顺序展示 AssessmentCard(每题一屏) 4. 收集 answers + 计算 scores 5. 生成摘要 → 传递给 InterpretationEngine 6. 结果写回 UserSession.assessmentResults 7. 更新 UserSession.riskScore ``` ### 5.4 InterpretationEngine **职责**:解读编排引擎(最体现积极心理学设计的模块) **核心流程**: ``` 1. 接收 GameController 或 AssessmentController 的结果数据 2. 查询 UserSession 获取当前上下文(riskTags / recentUtterances) 3. 从 InterpretationPool 按 gameType + contextTags 获取候选解读 4. 拼接上下文敏感内容(注入来访者提到过的关键词) 5. 选取最积极的解读变体(interpretation = "positive" 优先) 6. 生成 ResultCard 内容 7. 决定是否在 ResultCard 中插入下一个游戏/量表建议 ``` ### 5.5 StrategyDispatcher **职责**:策略分发队列 **数据结构**: ```javascript { queue: [ { id: "strategy_001", type: "assessment", scale: "SAS_anxiety", priority: 2, reason: "检测到焦虑风险词 3 次", suggestedQuestions: ["失眠情况", "紧张频率"], createdAt: "..." }, { id: "strategy_002", type: "game", gameId: "chimp_memory", priority: 3, reason: "缓解轻度压力的轻量游戏" } ], // 方法 enqueue(strategy), dequeue() → strategy, // 优先级最高者出队 peek() → strategy, // 只查看不下队 isEmpty() → boolean } ``` **入队触发条件**: - AgentBrain 后台监测到风险关键词累计 N 次 - 用户在对话中主动提到相关话题 - 游戏/量表完成后自动推荐下一个 --- ## 六、关键交互流 ### 流 1:游戏触发(核心) ``` 用户说"最近压力好大" ↓ AgentController.utterance() ↓ AgentBrain.recall("最近压力好大") → 匹配 corpus: { keyword: "压力大", strategy: "game_offer" } ↓ AgentController 决策 → StrategyDispatcher.enqueue({ type: "game", gameId: "tarot" }) ↓ AgentController 在对话中插入引导语: "你这个困扰,看起来困扰你很久了。我知道个有效的缓解方式——我给你算个塔罗牌吧。" ↓ 用户确认 / 自然延续 ↓ GameController.trigger("tarot") → 弹出 GameModal → TarotGame 组件加载 ↓ 用户抽卡 → TarotGame 交互完成 ↓ GameController.collectResult({ card, userChoice }) ↓ InterpretationEngine.generate({ gameType: "tarot", result: {...}, context: UserSession }) → 从 InterpretationPool 选取积极解读 → 生成 ResultCard ↓ 展示 ResultCard(解读文案 + 鼓励 + 建议) ↓ GameController.close() → 写回 UserSession.gameHistory ↓ AgentController 追加对话:"感觉怎么样?塔罗牌给你的启示有没有帮到你?" ``` ### 流 2:量表编排(PSI 等) ``` AgentBrain 后台监测: recentUtterances 检测到 "焦虑"/"失眠"/"心慌" 关键词累计 3 次 ↓ StrategyDispatcher.enqueue({ type: "assessment", scale: "SAS_anxiety", priority: 2, reason: "检测到焦虑风险词 3 次", suggestedQuestions: ["你最近睡眠状况如何?", "有没有经常感到紧张?"] }) ↓ AgentController 感知队列非空 ↓ 在对话自然节点插入: "我注意到你说最近睡得不太好,我有个小工具能帮你整理一下现在的状态,愿意试试吗?" ↓ 用户同意 ↓ AssessmentController.activate("SAS_anxiety") → 从 AssessmentFlows 加载 3 道题目 ↓ 逐题展示 AssessmentCard → 用户作答 ↓ 收集评分 → 计算总分 ↓ InterpretationEngine.generate({ flowType: "assessment", score, context }) ↓ 展示 ResultCard + 更新 UserSession.riskScore ↓ AgentBrain 更新 riskTags(加入 "焦虑") ↓ 影响后续 StrategyDispatcher 召回权重 ``` ### 流 3:直接入口(用户主动触发) ``` 数字人下方手势区域(双指下滑 / 长按) ↓ 解锁底部工具栏 ToolBar ↓ 展示游戏图标网格 GridView ↓ 用户点击图标 → GameController.trigger(gameId) (与流 1 的后半段一致) ``` --- ## 七、项目结构(原型阶段) ``` psycho-games-hub/ ├── docs/ │ ├── SPEC.md # 本文档 │ ├── RESEARCH.md # GitHub 调研报告(稍后补充) │ └── PROTOTYPE_NOTES.md # 原型实现笔记 ├── src/ │ ├── models/ │ │ ├── AgentBrain.js │ │ ├── GameCatalog.js │ │ ├── AssessmentFlows.js │ │ ├── UserSession.js │ │ └── InterpretationPool.js │ ├── views/ │ │ ├── AvatarView.html # 数字人主界面(单文件原型用) │ │ ├── GameModal.vue # 游戏弹窗 │ │ ├── ChatPanel.vue │ │ └── ResultCard.vue │ ├── controllers/ │ │ ├── AgentController.js │ │ ├── GameController.js │ │ ├── AssessmentController.js │ │ └── StrategyDispatcher.js │ ├── components/ # 各游戏独立组件 │ │ ├── TarotGame.vue │ │ ├── RorschachGame.vue │ │ └── MBTIGame.vue │ └── App.vue └── README.md ``` --- ## 八、待决策问题(悬置) | # | 问题 | 选项 | 当前倾向 | |---|------|------|---------| | 1 | 数字人技术路线 | A: Live2D / B: 3D 虚拟人 / C: 2D 立绘+差分 | C(最轻量) | | 2 | 策略召回引擎 | A: 规则版(关键词匹配)/ B: RAG(向量化召回) | A先行,B后续 | | 3 | 第一批游戏优先级 | 塔罗牌 / MBTI / 罗夏墨迹 | 塔罗牌优先 | | 4 | 游戏关闭策略 | A: 可随时关闭 / B: 完成才关闭 | A | | 5 | 遮罩样式 | A: blur + 黑底 / B: 纯黑底半透明 | A | | 6 | Agent 接入方式 | 接入 MiniMax / 本地小模型 | 待确认 | --- ## 九、版本记录 | 版本 | 日期 | 变更 | |------|------|------| | v0.1 | 2026-05-31 | 初稿:MVC 模块划分 + 交互流设计 | --- *本文档为架构设计文档,随着原型开发推进会持续更新。* *关键决策待在大头确认后锁定。*