lty/qy_lty/docs/修改记录.md
pmc c1722413ad feat: update AI app, device interaction, and docs
- Update aiapp views
- Update device_interaction consumers and views
- Update docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 11:55:42 +08:00

6.1 KiB
Raw Blame History

服务器端代码修改记录

本文档记录每次对服务器端代码的修改,方便追踪变更历史。


修改格式说明

每次修改按以下格式记录:

### [日期] 修改简述

- **文件路径**: 相对于项目根目录的文件路径
- **修改类型**: 新增 / 修改 / 删除 / 重构 / 修复Bug
- **修改内容**: 具体修改了什么
- **修改原因**: 为什么要做这个修改

修改历史

[2026-04-29] 手机端聊天记录切换服务端字幕落库B' 方案 服务端部分)

配套手机端方案文档:LTY_App_Project_URP/docs/手机端聊天记录_切换服务端字幕落库方案.md。手机端已实施 B'(本地 ASR 实时显示 + 服务端 webhook 静默替换服务端需要补三件事strategy B 落库后 group_send 推回客户端、DeviceConsumer 加 handler、RTCChatHistoryAPIView 灰度期去重 + since_id 增量拉取。

修改 1strategy B 落库成功后 group_send 转推

  • 文件路径: device_interaction/views.py
  • 修改类型: 新增功能
  • 修改内容:
    • conversation_status action 内字幕落库分支(约 L1414 ChatMessage.objects.create(...) 处):
      • create() 返回值赋给变量 chat_msg,落库成功 log 加上 id 字段
      • 落库成功后追加 channel_layer.group_send 调用,向 device_{paradise_user_id} 群组发送 type='chat_message_persisted' 消息payload 含 id / sender / message / timestamp / source_client
      • 用独立 try/except 包住,转推失败仅 warning 日志,不影响主落库流程
    • source_client 暂传 'unknown'(决策点 #3 落定后改为 'phone' / 'device'
  • 修改原因:
    • 手机端 B' 方案需要服务端在字幕入库后通过 WebSocket 把"权威 LLM 原始版本"推回客户端
    • 手机端按 chat_msg.id 去重 + 按 (sender, timestamp ±10s) 匹配本地待替换队列做静默替换,达到 UI 与 DB 字符级一致
    • 不影响设备端:设备端不订阅 chat_message_persisted 类型即可DeviceConsumer handler 仅向已实现处理的客户端透传)

修改 2DeviceConsumer 加 chat_message_persisted handler

  • 文件路径: device_interaction/consumers.py
  • 修改类型: 新增功能
  • 修改内容:
    • conversation_subtitle handler 之后新增 chat_message_persisted handler
    • 接收 group_send 事件后通过 self.send 把 JSON 推到 WebSocket 客户端
    • 日志记录 id / sender / source_client 用于后续排查
  • 修改原因:
    • Channels 协议要求 group_send 的 type 字段值在 Consumer 上有同名方法处理,否则消息被丢弃且报警
    • 必须与修改 1 同步部署,否则 strategy B 的 group_send 调用会失败

修改 3RTCChatHistoryAPIView 灰度期 POST 去重 + GET since_id 支持

  • 文件路径: aiapp/views.py
  • 修改类型: 新增功能 + 增强
  • 修改内容:
    • RTCChatHistoryAPIView.post() 入口加去重判定:同一 (user, bot, sender, message)±2s 时间窗内已存在则跳过 create,返回 deduplicated: true
    • RTCChatHistoryAPIView.get() 支持 since_id query 参数:传入则返回 id > since_id 的消息(升序,最多 page_size 条),未传则保持原最近 page_size 条逻辑
  • 修改原因:
    • 灰度期双倒保护:手机端 App 发版到用户手里需要时间,老版仍走 POST 落库strategy B webhook 此时也在落库 → 同一对话产生重复行。POST 去重让两条路径并存而不致脏库
    • 重放保护strategy B 自身被火山重试或客户端重连补提时,去重也能挡住
    • WebSocket 漏推兜底B' 方案手机端 5s 超时未收到 chat_message_persisted 时调 GET ?since_id=<last> 增量拉取替换队列里待修正的消息

关联代码(手机端,仅记录依赖关系)

  • 手机端 Assets/Scripts/Manager/WebSocketNetworking.cs 已新增 chat_message_persisted 类型分发分支
  • 手机端 Assets/Scripts/AI/ChatLogManager.cs 已新增 OnServerChatPersisted 方法、_pendingReplaceQueue 与 5s 超时兜底
  • 手机端 Assets/Scripts/AI/getJson.cs 已加 Config.SubtitleConfig.SubtitleMode=1

部署顺序与回滚

  • 部署顺序:服务端先部署(修改 1+2+3 三处一同上线)→ 验证 group_send 通道工作 → 手机端再发版
  • 回滚:三处改动都用独立 try/except 包住,可独立 git revert
    • 修改 1 revertstrategy B 主流程不受影响,只是不再 group_send手机端 UI 替换路径变为 5s 超时兜底
    • 修改 2 revert与修改 1 必须同时 revert否则 group_send 收方为空报警
    • 修改 3 revertPOST 不再去重(灰度期会出现双倒,需人工清理 DBGET 不再支持 since_id手机端兜底拉取无效

待跟进 TODO

  • 决策点 #3服务端区分手机端 / 设备端 RTC sessionmac 标记 / task_id 命名规则)→ source_client 字段填充真实值,让两端按需过滤
  • 决策点 #5服务端验证打断时是否仍 flush 部分内容;如不 flush手机端打断分支应跳过入待替换队列以避免 5s 超时空触发
  • Phase 0 步骤 1DB 双轨验证SQL 见 LTY_App_Project_URP/docs/手机端聊天记录_切换服务端字幕落库方案.md
  • Phase 0 步骤 4清理历史脏数据如发现

[2026-03-17] 修复手机号登录时 IntegrityError

  • 文件路径: userapp/views.py
  • 修改类型: 修复Bug
  • 修改内容: PhoneLoginView.post()get_or_create 新增 defaults={'username': phone_number}
  • 修改原因: 新用户首次通过手机号登录时,get_or_create 未设置 username 字段,导致 username="" 与数据库中已有空 username 记录冲突,触发 IntegrityError: duplicate key value violates unique constraint "userapp_paradiseuser_username_key"。改为用手机号作为默认 username保证唯一性。