psycho-games-hub/docs/SPEC.md

18 KiB
Raw Blame History

心理咨询室互动终端 — 心理小游戏聚合系统

项目代号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

职责:维护策略记忆 + 风险词召回

数据结构

{
  // 标注语料库(心理咨询师标注)
  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

职责:游戏配置清单 + 触发条件注册

数据结构

{
  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

职责:量表的对话化编排

数据结构

{
  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

职责:维护当前来访者会话上下文

数据结构

{
  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

职责:积极心理学话术库,按游戏类型 × 情境分组

数据结构

{
  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

核心方法

{
  // 触发游戏
  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

职责:策略分发队列

数据结构

{
  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 模块划分 + 交互流设计

本文档为架构设计文档,随着原型开发推进会持续更新。 关键决策待在大头确认后锁定。