|
|
@@ -1,7 +1,7 @@
|
|
1
|
1
|
# AI 诊断(兽医、机构)— 技术方案
|
|
2
|
2
|
|
|
3
|
3
|
> 依据:`AI诊断(兽医、机构)功能需求.md`(v1.1);关联 `在线接诊(兽医)技术方案.md`(v1.1)、`在线接诊(兽医)功能需求.md`
|
|
4
|
|
-> **本文档版本:1.4**(管理端隐藏 AI 诊断会话 `POST .../hide`,见 **§4.5**;`/v1` 见 **§1.2**)
|
|
|
4
|
+> **本文档版本:1.5**(`real_session_id`、`ai_category` 字段与落库接口 Body 同步,见 **§3.1**、**§3.2**、**§4.3**)
|
|
5
|
5
|
|
|
6
|
6
|
---
|
|
7
|
7
|
|
|
|
@@ -120,6 +120,7 @@ Payload 同在线接诊 **§4.2**(`senderRole`:1 提问人,**3** AI 助手
|
|
120
|
120
|
| `receiver_provider_id` | **NULL**(禁止写入兽医/机构资源 ID) |
|
|
121
|
121
|
| `receiver_name` | **NULL** |
|
|
122
|
122
|
| `session_title` | 新建时 **「新会话」**;首条有效文本提问后更新为摘要(≤50 字) |
|
|
|
123
|
+| `real_session_id` | **varchar(64)**,可为空;大模型网关 `session_id`,由 `POST .../message` 写入/更新,供多轮 `session_id` 回传 |
|
|
123
|
124
|
| `last_message_time` / `last_message_preview` | 每次提问或 AI 回复后更新 |
|
|
124
|
125
|
| `vet_visible` | 默认 **1**;提问人 `hide` 后置 **0** |
|
|
125
|
126
|
|
|
|
@@ -136,6 +137,12 @@ Payload 同在线接诊 **§4.2**(`senderRole`:1 提问人,**3** AI 助手
|
|
136
|
137
|
|
|
137
|
138
|
在线接诊使用的 **2**(接诊兽医)在 AI 会话中**不出现**。
|
|
138
|
139
|
|
|
|
140
|
+| 字段 | 说明 |
|
|
|
141
|
+| --- | --- |
|
|
|
142
|
+| `ai_category` | **varchar(32)**,可为空;仅 **提问人消息**(`sender_role=1`)写入;AI 回复为 `NULL`。纯数字时须为 `1`~`4`(与 `AiConsultConstants` 分类一致),亦可存业务编码字符串 |
|
|
|
143
|
+
|
|
|
144
|
+**已有库迁移**:`sql/alter_biz_consult_session_real_session_id.sql`、`sql/alter_biz_consult_message_ai_category.sql`。
|
|
|
145
|
+
|
|
139
|
146
|
### 3.3 AI 列表查询语义
|
|
140
|
147
|
|
|
141
|
148
|
**默认列表**(`searchMode=false`):
|
|
|
@@ -208,19 +215,21 @@ ORDER BY COALESCE(last_message_time, create_time) DESC
|
|
208
|
215
|
| 4.1 | 历史会话列表 | GET | `/session/list` | `...:list` | Query:`pageNum`、`pageSize`(默认 20)、`contentKeyword`、`searchMode`;`asker_user_id` 服务端注入 |
|
|
209
|
216
|
| 4.2 | 新增会话 | POST | `/session` | `...:add` | 创建 `consult_type=2` 空会话;`session_title=新会话`;`last_message_time=create_time`(**§3.5 #1**);返回 `sessionId`、`disclaimer` |
|
|
210
|
217
|
| 4.3 | 历史消息 | GET | `/session/{sessionId}/messages` | `...:query` | 校验 `consult_type=2` + `asker_user_id` + `vet_visible=1`;`beforeId`、`pageSize`(默认 50) |
|
|
211
|
|
-| 4.4 | 提问(触发 AI) | POST | `/session/{sessionId}/message` | `...:send` | Body:`msgType`、`content`、`mediaDuration?`;流程见 **§5** |
|
|
|
218
|
+| 4.4 | 提问(触发 AI) | POST | `/session/{sessionId}/message` | `...:send` | Body:`msgType`、`content`、`mediaDuration?`、`aiReplyContent?`、`realSessionId?`、`aiCategory?`;流程见 **§5** |
|
|
212
|
219
|
| 4.5 | 隐藏会话 | POST | `/session/{sessionId}/hide` | `...:remove` | 管理端隐藏 AI 诊断会话;`vet_visible=0`;仅本人会话;隐藏后列表/消息/提问不可用 |
|
|
213
|
220
|
|
|
214
|
221
|
### 4.1 列表 `rows[]` 字段
|
|
215
|
222
|
|
|
216
|
|
-`sessionId`、`sessionTitle`、`lastMessagePreview`、`lastMessageTime`(前端格式化为「M月D日」)。
|
|
|
223
|
+`sessionId`、`sessionTitle`、`lastMessagePreview`、`lastMessageTime`、`realSessionId`(大模型网关会话 ID,可为空)。
|
|
217
|
224
|
|
|
218
|
225
|
### 4.2 消息 `rows[]` / 推送字段
|
|
219
|
226
|
|
|
220
|
|
-`messageId`、`sessionId`、`senderRole`(1 提问人 / **3** AI)、`senderName`、`msgType`、`content`、`mediaDuration`、`sendTime`。
|
|
|
227
|
+`messageId`、`sessionId`、`senderRole`(1 提问人 / **3** AI)、`senderName`、`msgType`、`content`、`mediaDuration`、`aiCategory`(可为空)、`sendTime`。
|
|
221
|
228
|
|
|
222
|
229
|
### 4.3 提问 Body 示例
|
|
223
|
230
|
|
|
|
231
|
+**服务端调 `ConsultAiGateway`(无 `aiReplyContent`)**
|
|
|
232
|
+
|
|
224
|
233
|
```json
|
|
225
|
234
|
{
|
|
226
|
235
|
"msgType": 1,
|
|
|
@@ -228,6 +237,37 @@ ORDER BY COALESCE(last_message_time, create_time) DESC
|
|
228
|
237
|
}
|
|
229
|
238
|
```
|
|
230
|
239
|
|
|
|
240
|
+**前端大模型直连后落库(推荐)**
|
|
|
241
|
+
|
|
|
242
|
+```json
|
|
|
243
|
+{
|
|
|
244
|
+ "msgType": 1,
|
|
|
245
|
+ "content": "牛不吃草、精神沉郁,请问可能原因?",
|
|
|
246
|
+ "aiReplyContent": "可能原因包括…",
|
|
|
247
|
+ "realSessionId": "gateway-session-001",
|
|
|
248
|
+ "aiCategory": "2"
|
|
|
249
|
+}
|
|
|
250
|
+```
|
|
|
251
|
+
|
|
|
252
|
+| Body 字段 | 类型 | 必填 | 说明 |
|
|
|
253
|
+| --- | --- | --- | --- |
|
|
|
254
|
+| `msgType` | int | Y | 1 文本 2 图 3 视频 4 语音 |
|
|
|
255
|
+| `content` | string | 条件 | 文本或媒体 URL |
|
|
|
256
|
+| `mediaDuration` | int | N | 音视频秒数 |
|
|
|
257
|
+| `aiReplyContent` | string | N | 非空时服务端**仅落库**,不调 `ConsultAiGateway` |
|
|
|
258
|
+| `realSessionId` | string | N | 大模型 `session_id`;写入 `biz_consult_session.real_session_id`(别名 `real_session_id`、`session_id`、`llmSessionId`) |
|
|
|
259
|
+| `aiCategory` | string | N | 写入提问人消息 `ai_category`(别名 `ai_category`、`category`);最长 32 |
|
|
|
260
|
+
|
|
|
261
|
+**提问成功 `data`**
|
|
|
262
|
+
|
|
|
263
|
+```json
|
|
|
264
|
+{
|
|
|
265
|
+ "userMessage": { "id": 1, "senderRole": 1, "aiCategory": "2", "...": "..." },
|
|
|
266
|
+ "aiMessage": { "id": 2, "senderRole": 3, "...": "..." },
|
|
|
267
|
+ "realSessionId": "gateway-session-001"
|
|
|
268
|
+}
|
|
|
269
|
+```
|
|
|
270
|
+
|
|
231
|
271
|
### 4.4 业务错误(`msg` 示例)
|
|
232
|
272
|
|
|
233
|
273
|
| 场景 | 文案 |
|
|
|
@@ -241,6 +281,7 @@ ORDER BY COALESCE(last_message_time, create_time) DESC
|
|
241
|
281
|
| AI 超时 | AI 回复超时,请稍后重试 |
|
|
242
|
282
|
| AI 失败 | AI 回复失败,请稍后重试 |
|
|
243
|
283
|
| AI 处理中 | AI 正在回复中,请稍候 |
|
|
|
284
|
+| AI 提问分类无效 | AI提问分类无效 / AI提问分类长度不能超过32个字符 |
|
|
244
|
285
|
|
|
245
|
286
|
---
|
|
246
|
287
|
|
|
|
@@ -249,20 +290,22 @@ ORDER BY COALESCE(last_message_time, create_time) DESC
|
|
249
|
290
|
```text
|
|
250
|
291
|
1. 校验会话归属(type=2, asker=当前用户, vet_visible=1)
|
|
251
|
292
|
2. 若会话 AI 处理中 → 拒绝(§3.5 #7)
|
|
252
|
|
-3. 校验 Body(VetConsultValidation)
|
|
253
|
|
-4. 标记会话 processing=1(内存/Redis 锁)
|
|
254
|
|
-5. INSERT 提问消息(sender_role=1)
|
|
255
|
|
-6. 更新 session.last_message_*(提问侧摘要)
|
|
256
|
|
-7. 推送 NEW_MESSAGE(提问)→ 前端立即展示
|
|
257
|
|
-8. 调用 ConsultAiGateway(≤60s,单轮 §3.5 #6):
|
|
|
293
|
+3. 校验 Body(VetConsultValidation、AiConsultValidation.validateAiCategory)
|
|
|
294
|
+4. 若 Body.realSessionId 非空 → 更新 biz_consult_session.real_session_id
|
|
|
295
|
+5. 标记会话 processing=1(内存/Redis 锁)
|
|
|
296
|
+6. INSERT 提问消息(sender_role=1,含 ai_category 若有)
|
|
|
297
|
+7. 更新 session.last_message_*(提问侧摘要)
|
|
|
298
|
+8. 推送 NEW_MESSAGE(提问)→ 前端立即展示
|
|
|
299
|
+9a. 若 aiReplyContent 非空:直接作为 AI 文本,跳过 ConsultAiGateway(前端直连大模型落库通道)
|
|
|
300
|
+9b. 否则调用 ConsultAiGateway(≤60s,单轮 §3.5 #6):
|
|
258
|
301
|
- msg_type=1:文本问答
|
|
259
|
302
|
- msg_type=2:图文;失败 → §3.5 #4 固定 AI 文案仍入库
|
|
260
|
303
|
- msg_type=3/4:§3.5 #3 固定引导文案入库
|
|
261
|
|
-9. 成功:INSERT AI 消息(sender_role=3)
|
|
262
|
|
-10. 更新 session.last_message_*;首问更新 session_title
|
|
263
|
|
-11. 推送 NEW_MESSAGE(AI 回复,落库后 ≤1s)
|
|
264
|
|
-12. 释放 processing;响应 data:{ userMessage, aiMessage }
|
|
265
|
|
-13. 网关硬失败(非图片软失败):不写 AI 消息;HTTP 错误 + §4.4 文案
|
|
|
304
|
+10. 成功:INSERT AI 消息(sender_role=3,ai_category=NULL)
|
|
|
305
|
+11. 更新 session.last_message_*;首问更新 session_title
|
|
|
306
|
+12. 推送 NEW_MESSAGE(AI 回复,落库后 ≤1s)
|
|
|
307
|
+13. 释放 processing;响应 data:{ userMessage, aiMessage, realSessionId? }
|
|
|
308
|
+14. 网关硬失败(非图片软失败且无 aiReplyContent):不写 AI 消息;HTTP 错误 + §4.4 文案
|
|
266
|
309
|
```
|
|
267
|
310
|
|
|
268
|
311
|
### 5.1 同步、超时与展示策略(v1.1 已确认)
|
|
|
@@ -379,3 +422,4 @@ ORDER BY COALESCE(last_message_time, create_time) DESC
|
|
379
|
422
|
| 1.2 | 补充 §1.2:`KbOpenAiProxyController` 转发 `/v1/models`、`/v1/chat/completions`;区分对话框直连/转发与 `ConsultAiGateway` 兜底 |
|
|
380
|
423
|
| 1.3 | §1.2:`/v1/**` 须若依 Token,取消匿名访问 |
|
|
381
|
424
|
| 1.4 | 管理端 **§4.5** `POST /session/{id}/hide` 隐藏 AI 诊断会话;权限 `...:remove` |
|
|
|
425
|
+| 1.5 | **§3.1** `biz_consult_session.real_session_id`;**§3.2** `biz_consult_message.ai_category`(varchar32);**§4.3** 落库 Body/响应字段;**§5** 前端 `aiReplyContent` 落库通道 |
|