From 72d47ffba0f676d55b2754f8a515e8417d9c6f8a Mon Sep 17 00:00:00 2001 From: bigemon Date: Sun, 31 May 2026 10:35:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(v0.1):=20=E5=88=9D=E5=A7=8B=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=BB=93=E6=9E=84=20+=20=E6=9E=B6=E6=9E=84=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=96=87=E6=A1=A3=20SPEC.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 42 ++++ docs/SPEC.md | 600 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 642 insertions(+) create mode 100644 README.md create mode 100644 docs/SPEC.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..b956625 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# 🗡️ Psycho-Games-Hub + +心理咨询室互动终端 — 心理小游戏聚合系统 + +> **定位**:面向青少年/儿童心理辅导的互动终端子系统 +> **核心理念**:数字人是入口,小游戏是「药」,只是吃起来像糖 + +## 项目状态 + +🚧 **架构设计阶段(v0.1)** — 详见 [docs/SPEC.md](docs/SPEC.md) + +## 功能特性 + +- 🎭 **数字人入口** — Live2D/虚拟形象作为主交互界面 +- 🃏 **游戏弹窗机制** — 半透明遮罩 + 轻交互小游戏 +- 💬 **谈话式量表** — 心理量表对话化编排,非接触评估 +- 🧠 **积极心理学解读** — 基于上下文动态编排鼓励文案 +- 📊 **风险标签系统** — Agent 后台监测 + 策略分发队列 + +## 技术栈(原型阶段) + +- **前端**:Vue 3 + Vite + TypeScript(简化可单文件 HTML) +- **Agent**:MiniMax / 本地小模型(待接入) +- **存储**:LocalStorage(原型阶段) + +## 文档 + +| 文档 | 内容 | +|------|------| +| [docs/SPEC.md](docs/SPEC.md) | 系统架构规范(MVC 模块划分 + 交互流设计) | +| [docs/RESEARCH.md](docs/RESEARCH.md) | GitHub 心理小游戏调研报告 | + +## 快速启动(原型) + +```bash +# 原型阶段直接打开单文件即可 +open src/views/AvatarView.html +``` + +## License + +MIT \ No newline at end of file diff --git a/docs/SPEC.md b/docs/SPEC.md new file mode 100644 index 0000000..931e753 --- /dev/null +++ b/docs/SPEC.md @@ -0,0 +1,600 @@ +# 心理咨询室互动终端 — 心理小游戏聚合系统 + +> **项目代号**: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 模块划分 + 交互流设计 | + +--- + +*本文档为架构设计文档,随着原型开发推进会持续更新。* +*关键决策待在大头确认后锁定。* \ No newline at end of file