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

99 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 服务器端代码修改记录
本文档记录每次对服务器端代码的修改,方便追踪变更历史。
---
## 修改格式说明
每次修改按以下格式记录:
```
### [日期] 修改简述
- **文件路径**: 相对于项目根目录的文件路径
- **修改类型**: 新增 / 修改 / 删除 / 重构 / 修复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保证唯一性。