# 保存聊天记录到 ia_messages 表设计文档 ## 1. 需求概述 修改 ChatController 中的 `chat` 和 `chatStreaming` 接口,将对话数据保存到 `ia_messages` 表中。 ## 2. 表结构 | 字段名 | 类型 | 说明 | |--------|------|------| | id | BIGINT | 主键,自增 | | task_id | VARCHAR(64) | 任务id (Dify返回) | | message_id | VARCHAR(64) | 信息id (Dify返回) | | conversation_id | VARCHAR(64) | 会话id | | app_id | VARCHAR(64) | 应用id | | inputs | TEXT | 输入 (JSON格式) | | query | TEXT | 问题 | | response_mode | VARCHAR(20) | 回复模式 (blocking/streaming) | | user_id | VARCHAR(64) | 用户id | | answer | LONGTEXT | AI回复 | | created_at | DATETIME | 创建时间 | ## 3. 技术方案 ### 3.1 架构设计 采用标准三层架构: - **Entity**: `IaMessageEntity` - 映射 ia_messages 表 - **Mapper**: `IaMessageMapper` - 数据访问层(继承 MyBaseMapper) - **Service**: `IaMessageService` / `IaMessageServiceImpl` - 业务逻辑层 - **Controller**: 修改 `ChatController` - 在返回前调用 Service 保存数据 ### 3.2 数据流 ``` ChatController.chat/chatStreaming ↓ 调用 Dify API ↓ 获取响应结果 ↓ 提取关键字段 → 构建 IaMessageEntity ↓ 调用 IaMessageService.save() ↓ 返回原结果给客户端 ``` ### 3.3 数据来源映射 **从 ChatDTO 获取:** | ChatDTO 字段 | ia_messages 字段 | 说明 | |--------------|------------------|------| | input | inputs | List 转 JSON | | query | query | 直接映射 | | response_mode | response_mode | 直接映射 | | conversation_id | conversation_id | 直接映射 | | user | user_id | 直接映射 | | appId | app_id | 直接映射 | **从 Dify 响应获取(blocking模式):** ```json { "task_id": "...", "message_id": "...", "answer": "...", "conversation_id": "..." } ``` **从 Dify 响应获取(streaming模式):** 流式数据最后一帧包含完整信息,需要解析 `data:` 行中的 JSON。 ## 4. 实现细节 ### 4.1 实体类 IaMessageEntity ```java @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("ia_messages") public class IaMessageEntity { @TableId(type = IdType.AUTO) private Long id; private String taskId; private String messageId; private String conversationId; private String appId; private String inputs; private String query; private String responseMode; private String userId; private String answer; private LocalDateTime createdAt; } ``` ### 4.2 修改 chat() 方法 ```java @PostMapping("chat") public Result chat(@RequestBody ChatDTO chatDTO) throws JsonProcessingException { String url = difyProperties.getBaseUrl() + "chat-messages"; String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(chatDTO); Result result = httpService.post(url, null, "Bearer "+difyProperties.getAppKeys().get(chatDTO.getAppId()), body, new TypeReference<>() {}); // 保存到数据库(异步处理,不影响主流程) if (result.isOk() && result.getData() != null) { saveChatMessage(chatDTO, result.getData()); } return result; } ``` ### 4.3 修改 chatStreaming() 方法 流式响应需要先收集完整 answer,再保存。修改 `postStream` 方法或使用拦截器模式: ```java // 方案:修改 postStream 方法,增加回调处理最后一帧数据 httpService.postStream(url, authorization, body, emitter, (lastData) -> { // 解析 lastData 保存到数据库 saveStreamingMessage(chatDTO, lastData); }); ``` ## 5. 边界条件处理 1. **数据库保存失败**:使用 try-catch 包裹,不影响 API 返回 2. **Dify 响应解析失败**:记录日志,不影响主流程 3. **流式响应中断**:在 emitter 的 onError 中处理 4. **字段为空处理**:允许为空,按实际返回数据存储 ## 6. 影响文件 | 文件类型 | 路径 | 操作 | |----------|------|------| | Entity | storlead-knowledge-core/.../entity/IaMessageEntity.java | 新增 | | Mapper | storlead-knowledge-biz/.../mapper/IaMessageMapper.java | 新增 | | Service | storlead-knowledge-biz/.../service/IaMessageService.java | 新增 | | ServiceImpl | storlead-knowledge-biz/.../service/impl/IaMessageServiceImpl.java | 新增 | | Controller | storlead-knowledge-api/.../api/ChatController.java | 修改 | | HttpService | storlead-knowledge-core/.../utils/HttpService.java | 修改(增加回调) | ## 7. SQL 建表语句 ```sql CREATE TABLE IF NOT EXISTS `ia_messages` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `task_id` varchar(64) DEFAULT NULL COMMENT '任务id', `message_id` varchar(64) DEFAULT NULL COMMENT '信息id', `conversation_id` varchar(64) DEFAULT NULL COMMENT '会话id', `app_id` varchar(64) DEFAULT NULL COMMENT '应用id', `inputs` text COMMENT '输入(JSON)', `query` text COMMENT '问题', `response_mode` varchar(20) DEFAULT NULL COMMENT '回复模式', `user_id` varchar(64) DEFAULT NULL COMMENT '用户id', `answer` longtext COMMENT 'AI回复', `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_conversation_id` (`conversation_id`), KEY `idx_user_id` (`user_id`), KEY `idx_app_id` (`app_id`), KEY `idx_created_at` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI对话消息记录表'; ```