Skip to content

SM-Personal-Learning 个性化学习功能设计

版本: v2.0 日期: 2026-07-14 状态: 简化设计版 关联: SA_主动整备_Agent设计.md、SA_空间控制面板设计.md、SM-Weather-API_天气接入设计.md 核心思路: 不聚合、不分类、不建偏好评级,只选最近 30 天内室外温度最相似的 5 条历史快照喂给 LLM


1. 背景与设计原则

1.1 要解决的问题

智能整备 Agent 当前基于知识库规则做全局统一的决策——无论谁来开会、外面什么天气,LLM 推荐的方案都一样。实际上,不同用户对环境有不同的偏好:有人喜欢 22°C 的强劲冷气,有人觉得 26°C 就够。全局规则无法覆盖个人差异。

1.2 设计原则

原则说明
隐式采集用户不需要配置偏好,系统通过深度调节等行为自动学习
不搞分类不做季节/温度带/天气状况的分类标签——直接用原始室外温度排序
不搞聚合不做统计均值、置信度计算——直接喂原始快照,LLM 自己看规律
可降级无记录时退化为知识库规则,冷启动无影响
手工信号优先用户手动调整过的是强信号,未动的虽隐含认可但不作为强依据

1.3 与智能整备的关系

整备触发 → LLM 出建议(含天气+知识库规则)

         推送通知卡片(通知型自动执行 / 确认型等用户确认)

         用户可随时打开面板"深度调节"

         每次操作都记录快照 → 成为下次 prep 的历史参考

2. 数据模型

2.1 整备会话表(prep_sessions

一次会议的一次整备生命周期 = 一条记录。

字段类型说明示例
session_idVARCHAR(64) PK整备会话唯一 IDs_20260714_A101
meeting_idVARCHAR(64)会议 IDmtg_001
room_idVARCHAR(64)空间 IDA-101
booker_idVARCHAR(64)预定人(用户身份)u_zhangsan
meeting_startDATETIME会议开始时间2026-07-14 14:00
meeting_endDATETIME会议结束时间2026-07-14 15:00
prep_trigger_atDATETIMEprep 触发时间2026-07-14 13:45
prep_typeENUM通知型 auto_notify / 确认型 confirmauto_notify
weather_tempINT触发时的室外温度35
weather_conditionVARCHAR(32)触发时的天气状况

2.2 整备快照表(prep_snapshots

每次整备生命周期中的"事件"都记录一条全量快照。

字段类型说明示例
idBIGINT AUTO_INCREMENT主键
session_idVARCHAR(64)所属会话s_20260714_A101
recorded_atDATETIME记录时间2026-07-14 13:45
sourceENUM见下方来源定义
operator_idVARCHAR(64)操作人(LLM 推荐时为 null)u_zhangsan
snapshotJSON全量控制快照见下方示例

source 来源定义

来源含义触发场景
llm_recommendLLM 刚出的推荐值prep 触发 → LLM 输出 recipes 后
auto_executed通知型·已自动下发通知型 prep,设备指令已下发
user_confirmed确认型·用户点了确认确认型 prep,用户点击"确认执行"
user_adjust用户手动调整用户打开深度调节面板修改数值并生效
user_later_adjust会议中再次手动调整会议进行中用户又唤出面板调整

snapshot 结构示例(全量,包含所有设备语义的最终值):

json
{
  "hvac_power": true,
  "hvac_mode": "制冷",
  "hvac_target_temp": 22,
  "light_power": true,
  "light_brightness": 60,
  "curtain_power": true,
  "curtain_position": 100
}

2.3 一个完整 session 的快照示例

场景:A-101, 张三, 14:00~15:00 会议, 通知型 prep

时间      | 来源               | 操作人  | snapshot
──────────┼────────────────────┼────────┼────────────────────────────
13:45     | llm_recommend      | null   | hvac_power=true, hvac_target_temp=24, hvac_mode=制冷, light_power=true, light_brightness=80, curtain_power=true, curtain_position=50
13:45     | auto_executed      | null   | (同上,自动下发执行)
13:50     | user_adjust        | 张三   | hvac_target_temp=22, 其余同上
14:00     | user_later_adjust  | 张三   | hvac_target_temp=23, light_brightness=60, curtain_position=100, 其余同上
14:30     | user_later_adjust  | 张三   | hvac_target_temp=22, 其余同上

3. 召回逻辑——给 LLM 喂什么

3.1 核心思路

不做任何聚合/统计/分类。查最近 30 天同一用户的整备记录,按室外温度接近度排序,取 top 5,直接拿"用户最终决定"的快照喂给 LLM。

3.2 查询逻辑

1. 查 prep_sessions WHERE booker_id = 当前预定人
                        AND room_id = 当前会议室
                        AND prep_trigger_at >= NOW() - 30 天

2. 对每个 session,归约为"用户最终状态":
   - 该 session 中同一语义 key 取最后一次 user_adjust 的值
   - 如果该语义 key 用户从未手动调整过 → 跳过(不输出)
   
3. 按室外温度接近度排序:
   ORDER BY ABS(weather_temp - 当前室外温度) ASC

4. 取 TOP 5

为什么只输出"用户改过的 key":没改过的说明用户接受了推荐值,那是全局规则的功劳,不是个人偏好的体现。

3.3 注入 LLM 的格式

【张三近期操作习惯(近30天·按气温接近排序)】
日期    室外    状态               控制快照
────────────────────────────────────────────────────────
7/12    33°C   你手动调过          空调24→22°C  灯开→亮度70%  窗帘关
7/10    35°C   你确认了推荐         空调24°C    灯开·亮度80%  窗帘开
7/08    32°C   你手动调过          空调24→21°C  灯开→亮度60%  窗帘关
7/05    28°C   你手动调过          空调24→26°C  灯开·亮度80%  窗帘开
7/01    27°C   确认了推荐(未改)    空调24°C    灯开·亮度80%  窗帘开

提示:今天室外 34°C,与 7/12(33°C)、7/10(35°C) 接近。
历史中这种天气下,用户倾向比推荐值调低 2°C 并关窗帘。
上述记录供参考,最终请结合当前 RO 读数和约束判断。

说明

状态对应 source含义
你手动调过user_adjust / user_later_adjust强信号,用户明确改了
你确认了推荐user_confirmed中信号,用户看了并点了同意
自动执行(未干预)auto_executed 后无 user_adjust弱信号,可能是没看到

关键设计点:每个 session 只贡献一条经过归约的快照(即"用户最终决定了什么"),而不是原始的多条事件记录。保持 LLM 输入简洁。


4. 数据采集

4.1 采集时机

时机上报方记录为
prep 触发 → LLM 出推荐值Dify 工作流llm_recommend
通知型·自动下发执行Hub(执行后)auto_executed
确认型·用户点击确认前端控制面板user_confirmed
用户深度调节→立即生效前端控制面板user_adjust
用户会议中再次调节前端控制面板user_later_adjust

4.2 前端上报 API

POST /internal/preparation/snapshots

{
  "session_id": "s_20260714_A101",
  "recorded_at": "2026-07-14 13:50",
  "source": "user_adjust",
  "operator_id": "u_zhangsan",
  "snapshot": {
    "hvac_power": true,
    "hvac_target_temp": 22,
    "light_power": true,
    "light_brightness": 60,
    "curtain_power": true,
    "curtain_position": 100
  }
}

调用方:前端控制面板的"立即生效"/"确认执行"按钮回调。

4.3 所需的前端上下文

数据来源说明
operator_idChatbot 用户身份当前登录用户 ID(已有,Chatbot 内可获取)
session_id面板打开时携带从通知卡片 AppLink 参数带过来
snapshot面板当前所有语义的最终值从 PrepStore 实时获取
recorded_at当前时间前端本地时间

5. Dify 工作流变动

5.1 新增节点

在"构建LLM用户消息"与"LLM推理"之间插入 Code: 召回个人操作记录

输入

  • booker_id:从 Hub Context 新增的字段获取
  • room_id:会议空间 ID(已有)
  • current_weather_temp:当前室外温度(天气节点已有)
  • user_message:"构建LLM用户消息"节点的输出

逻辑

python
def main(user_message, booker_id, room_id, current_weather_temp):
    sessions = query_prep_sessions(booker_id, room_id, days=30)
    
    if not sessions:
        return {"user_message": user_message}
    
    # 对每个 session 归约为"用户最终决定"
    history = []
    for s in sessions:
        snapshots = query_snapshots(s.session_id, 
                                    sources=['user_adjust', 'user_later_adjust', 'user_confirmed', 'auto_executed'])
        if not snapshots:
            continue
        
        # 按语义 key 取最后一次用户修改的值
        final_state = {}
        touched_keys = set()
        has_user_adjust = False
        for snap in snapshots:
            if snap.source in ('user_adjust', 'user_later_adjust'):
                for k, v in snap.snapshot.items():
                    final_state[k] = v
                    touched_keys.add(k)
                has_user_adjust = True
            elif snap.source == 'user_confirmed':
                for k, v in snap.snapshot.items():
                    final_state[k] = v
        
        # 只保留用户明确调过的 key
        user_final = {k: final_state[k] for k in touched_keys}
        
        # 判断状态标签
        if has_user_adjust:
            status_label = "user_adjusted"
        else:
            status_label = "user_confirmed"
        
        history.append({
            "date": s.prep_trigger_at.strftime("%m/%d"),
            "weather_temp": s.weather_temp,
            "weather_condition": s.weather_condition,
            "status": status_label,
            "final_state": user_final
        })
    
    # 按气温接近度排序,取 top 5
    history.sort(key=lambda h: abs(h["weather_temp"] - current_weather_temp))
    history = history[:5]
    
    if not history:
        return {"user_message": user_message}
    
    # 构建注入段落
    lines = ["", "【{}近期操作习惯(近30天·按气温接近排序)】".format(booker_id)]
    lines.append("日期    室外    状态             控制快照")
    lines.append("─" * 60)
    
    for h in history:
        status_text = {
            "user_adjusted": "你手动调过",
            "user_confirmed": "你确认了推荐",
            "auto_no_intervention": "自动执行(未干预)"
        }.get(h["status"], h["status"])
        
        state_parts = []
        for k, v in h["final_state"].items():
            if isinstance(v, bool):
                v_text = "开" if v else "关"
            else:
                v_text = str(v)
            state_parts.append(f"{k}={v_text}")
        state_str = "  ".join(state_parts)
        
        lines.append(f"{h['date']}  {h['weather_temp']}°C  {status_text:<12} {state_str}")
    
    # 加一句提示
    nearest = history[0]
    lines.append("")
    lines.append(f"提示:今天室外 {current_weather_temp}°C,与 {nearest['date']}({nearest['weather_temp']}°C) 最接近。")
    lines.append("上述记录供参考,最终请结合当前 RO 读数和量程约束自行判断。")
    
    return {"user_message": user_message + "\n" + "\n".join(lines)}

5.2 Hub Context API 需补充字段

当前 GET /internal/preparation/tasks/{taskId}/context 返回值需增加:

json
{
  "bookerId": "u_zhangsan",
  "bookerName": "张三"
}

6. 边界情况

场景处理
冷启动(无历史)不注入偏好段落,LLM 纯用知识库规则
不足 5 条有几条给几条
无相同温度匹配按温差升序取,温差再大也有最接近的
用户改过调回最后一次 user_adjust 的值就是最终值,如实记录。如果等于推荐值,状态标记为"确认了推荐"而非"手动调过"(不视为强信号)
同一会议多次调整按语义 key 取最后一次 user_adjust 值,一个 session 归约为一行
窗帘类已纳入curtain_power(bool 开关) 和 curtain_position(number 位置) 均作为标准 RW 语义,与 hvac/light 同等对待

7. 实施计划

序号任务说明
1Hub 新增 prep_sessions记录整备会话
2Hub 新增 prep_snapshots记录每次快照事件
3Hub Context API 补充 booker_id 字段Dify 需要知道是谁的会议
4Hub 新增 POST /snapshots 接收端点前端/后端上报快照
5Dify 新增 Code: 召回个人操作记录 节点查询 top 5 并注入 user_message
6前端控制面板补充快照上报立即生效/确认执行回调中 POST 快照
7端到端联调

8. 附录:相关文档

文档关系
SA_主动整备_Agent设计.md §9.4本设计即对该节"个人偏好习惯表(预研)"的正式落地
SA_空间控制面板设计.md面板的"立即生效"是快照的主要采集入口
SM-Weather-API_天气接入设计.md室外温度是快照排序的核心维度
空间语义管理.md §10空间逻辑映射定义了哪些语义可以被操作,窗帘等语义纳入其中
SA_主动整备_消息通知通道设计.md用户身份(booker_id)的来源定义

Released under the Private License.