# RAG 聊天接口 > 最后整理:2026-05-11 > 本文已按当前后端实现逐项核对 > 对应后端:`fastapi_modules/fastapi_leaudit/controllers/ragChatController.py` > 统一前缀:`/api/v3/rag` ## 1. 目标与范围 本组接口用于替代旧的 `dify_chat/*` 对话代理,直接提供自有 RAG 聊天能力。 当前已落地能力: - 获取当前用户可见的 RAG 应用 - 获取默认 RAG 应用 - 获取当前用户可见知识库 - 获取聊天页面参数 - 发起流式对话 - 查询会话列表 - 查询会话消息 - 重命名会话 - 删除会话 - 消息反馈 当前不在本文档范围内: - 知识库 CRUD 管理 - 文档切分 / 入库任务 - Chroma 集合构建脚本 ## 2. 鉴权与权限 ### 2.1 鉴权方式 所有接口都要求请求头带: ```http Authorization: Bearer ``` JWT 解析逻辑见: - `fastapi_common/fastapi_common_security/security.py` - `fastapi_common/fastapi_common_security/jwtService.py` JWT payload 至少会被后端消费这些字段: - `user_id` - `username` - `area` - `user_role` - `type`,必须为 `access` ### 2.2 权限键 | 接口 | 权限 | |------|------| | `GET /api/v3/rag/apps` | `rag:app:read` | | `GET /api/v3/rag/apps/default` | `rag:app:read` | | `GET /api/v3/rag/datasets/my` | `rag:dataset:read` | | `GET /api/v3/rag/chat/parameters` | `rag:chat:use` 或 `rag:app:read` 其一即可 | | `POST /api/v3/rag/chat/messages` | `rag:chat:use` | | `GET /api/v3/rag/chat/conversations` | `rag:conversation:read` | | `GET /api/v3/rag/chat/conversations/{ConversationId}/messages` | `rag:conversation:read` | | `PATCH /api/v3/rag/chat/conversations/{ConversationId}` | `rag:conversation:update` | | `DELETE /api/v3/rag/chat/conversations/{ConversationId}` | `rag:conversation:delete` | | `POST /api/v3/rag/chat/messages/{MessageId}/feedback` | `rag:message:feedback` | 说明: - 权限检查使用 `HasAnyPermission`,即“列表中的任一权限命中即可通过”。 - 具体实现见 `fastapi_modules/fastapi_leaudit/services/impl/permissionServiceImpl.py`。 ## 3. 通用返回格式 除流式接口外,统一返回: ```json { "code": 200, "msg": "success", "data": {} } ``` 权限不足时通常返回: ```json { "code": 403, "msg": "当前用户没有对应权限", "data": null } ``` ## 4. 接口列表 ### 4.1 获取可见应用列表 `GET /api/v3/rag/apps` 用途: - 聊天页面加载应用下拉 - 根据地区 / 省级角色做应用可见性过滤 请求参数:无 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "data": [ { "appId": "1", "appName": "法务问答", "description": "默认烟草法务知识问答", "isDefault": true } ], "total": 1 } } ``` 可见性规则: - `provincial_admin` 可见全部启用应用 - 其他角色仅可见: - `rag_chat_app.area = 用户 area` - `rag_chat_app.area = '省级'` - `rag_chat_app.area = ''` - 或关联数据集 `rag_dataset.is_public = true` ### 4.2 获取默认应用 `GET /api/v3/rag/apps/default` 用途: - 聊天页初始化默认应用 请求参数:无 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "appId": "1", "appName": "法务问答", "description": "默认烟草法务知识问答", "isDefault": true } } ``` 补充说明: - 如果没有显式默认应用,会退回到当前用户可见的第一条应用。 - 如果完全没有可见应用,返回 `data: null`。 ### 4.3 获取当前用户可见知识库 `GET /api/v3/rag/datasets/my` 用途: - 聊天页展示“当前可用知识库”时使用 请求参数:无 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "data": [ { "id": 1, "name": "广东烟草法规库", "description": "省级法规与制度", "area": "省级", "isPublic": true, "isDefault": true, "documentCount": 120, "totalChunks": 8345, "status": 1 } ], "total": 1 } } ``` ### 4.4 获取聊天参数 `GET /api/v3/rag/chat/parameters` 查询参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `appId` | int | 否 | 指定应用 ID;不传则取默认应用 | 用途: - 初始化开场白 - 初始化建议问题 - 初始化上传能力配置 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "openingStatement": "你好,我可以帮你解答烟草行业法务问题。", "suggestedQuestions": [ "烟草专卖许可延续的法定条件是什么?", "行政处罚文书审查重点有哪些?" ], "userInputForm": [], "fileUpload": { "image": { "enabled": false } } } } ``` 补充说明: - 如果 `appId` 不存在、不可见,或者系统默认应用 / 排序第一条应用均不可见,当前实现不会报 404,而是返回一个空参数对象: ```json { "code": 200, "msg": "success", "data": { "openingStatement": "", "suggestedQuestions": [], "userInputForm": [], "fileUpload": { "image": { "enabled": false } } } } ``` ### 4.5 发起流式对话 `POST /api/v3/rag/chat/messages` 请求体: ```json { "query": "烟草专卖许可证延续申请的审查要点是什么?", "conversationId": null, "appId": 1 } ``` 字段说明: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `query` | string | 是 | 用户问题,不能为空 | | `conversationId` | string \| null | 否 | 会话 ID;新对话可传 `null`、不传,当前实现也把 `"-1"` 视为新对话 | | `appId` | int \| null | 否 | 应用 ID;不传则自动回退默认应用 | 返回类型: - `text/event-stream` SSE 事件 1:流式正文片段 ```text data: {"event":"message","task_id":"...","message_id":"...","conversation_id":"...","answer":"第一段内容","created_at":1746580000} ``` SSE 事件 2:流式结束 ```text data: {"event":"message_end","task_id":"...","message_id":"...","conversation_id":"...","metadata":{"usage":{"total_tokens":1234},"retriever_resources":[...],"suggested_questions":["问题1","问题2"]}} ``` SSE 事件 3:模型异常 ```text data: {"event":"error","task_id":"...","message_id":"...","code":"llm_error","message":"..."} ``` 服务端行为说明: - 若 `conversationId` 为空,会自动创建新会话 - 若 `conversationId` 为空,会自动创建新会话,默认标题为 `新对话` - 会先落一条 `role = user` 消息,再流式生成回答 - 流结束后会落一条 `role = assistant` 消息 - 若命中知识库,会把引用结果写入 `sources / metadata` - 会根据对话内容追加 `suggested_questions` - 首轮回答完成后,后端会异步尝试生成会话标题 - 当前应用解析顺序是:指定 `appId` -> 任意默认应用 -> 排序第一条应用;每一步都只检查当前命中的那一条记录是否可见,不会遍历全部可见应用 ### 4.6 获取会话列表 `GET /api/v3/rag/chat/conversations` 查询参数: | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `appId` | int | 否 | - | 按应用过滤 | | `page` | int | 否 | `1` | 页码,从 1 开始 | | `pageSize` | int | 否 | `20` | 每页数量,最大 100 | 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "data": [ { "id": "b17d3b0b-xxxx-xxxx", "name": "烟草专卖法中的烟草定义", "introduction": "", "titleSource": "auto", "createdAt": 1746580000, "updatedAt": 1746580066, "lastMessageAt": 1746580066 } ], "hasMore": false, "limit": 20 } } ``` 补充说明: - `titleSource` 取值: - `default`:默认标题,例如 `新对话` - `auto`:系统自动生成标题 - `manual`:用户手动重命名 - 会话列表排序按 `COALESCE(last_message_at, updated_at) DESC, updated_at DESC` - 自动标题更新不应该被前端视作“新消息到达” ### 4.7 获取会话消息 `GET /api/v3/rag/chat/conversations/{ConversationId}/messages` 路径参数: | 参数 | 类型 | 说明 | |------|------|------| | `ConversationId` | string | 会话 ID | 查询参数: | 参数 | 类型 | 必填 | 默认值 | |------|------|------|--------| | `page` | int | 否 | `1` | | `pageSize` | int | 否 | `20` | 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "data": [ { "id": "assistant-message-id", "conversationId": "b17d3b0b-xxxx-xxxx", "query": "烟草专卖许可证延续申请的审查要点是什么?", "answer": "先核对主体资格,再核对经营条件……", "feedback": { "rating": "like" }, "retrieverResources": [ { "position": 1, "dataset_id": "1", "dataset_name": "广东烟草法规库", "document_id": "12", "document_name": "行政许可审查规范.pdf", "segment_id": "chunk-1", "score": 0.9132 } ], "createdAt": 1746580000 } ], "hasMore": false, "limit": 20 } } ``` 补充说明: - 手动重命名会将该会话的标题来源标记为 `manual` - 已手动重命名的会话,后续自动标题任务不得覆盖 说明: - 返回结构是按“问答对”聚合后的结果,不是底层 `rag_message` 原始逐条结果。 - 分页查询实际先按底层 `rag_message` 行分页,再在服务层折叠成“用户问 + 助手答”结构,所以单页返回条数可能少于 `pageSize`。 ### 4.8 重命名会话 `PATCH /api/v3/rag/chat/conversations/{ConversationId}` 请求体: ```json { "name": "许可证延续审查要点" } ``` 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "result": "success", "name": "许可证延续审查要点" } } ``` ### 4.9 删除会话 `DELETE /api/v3/rag/chat/conversations/{ConversationId}` 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "result": "success" } } ``` 说明: - 逻辑删除,实际是设置 `rag_conversation.deleted_at` ### 4.10 消息反馈 `POST /api/v3/rag/chat/messages/{MessageId}/feedback` 请求体: ```json { "rating": "like" } ``` 约定值: - `like` - `dislike` - `null` 补充说明: - 当前 DTO 仅声明 `rating: str | null`,后端不会强校验枚举,除 `null` 外其余字符串也会被写入 `rag_message.feedback`。 成功响应示例: ```json { "code": 200, "msg": "success", "data": { "result": "success" } } ``` ## 5. 数据表对应关系 | 表 | 用途 | |----|------| | `rag_dataset` | 知识库定义、地区可见性、检索参数 | | `rag_document` | 知识库文档、启停状态、命中次数 | | `rag_chat_app` | 聊天应用配置、默认应用、应用绑定知识库 | | `rag_conversation` | 用户会话 | | `rag_message` | 底层消息落库,包含引用与反馈 | ## 6. 当前实现约束 - 当前只提供 `GET /datasets/my`,不提供知识库管理 CRUD - `fileUpload.image.enabled` 固定为 `false` - 检索依赖 Chroma;Chroma 不可用时,接口仍可回答,但会退化成无知识库上下文 - 建议问题 `suggestedQuestions` 由二次模型调用生成,失败时会降级为空数组 - `GET /chat/parameters` / `POST /chat/messages` 的应用回退逻辑目前不是“从全部可见应用里挑第一条”,而是“默认应用优先,其次全表第一条”;当默认应用或首条应用不可见时,可能出现空参数或 `未配置可用聊天应用` ## 7. 联调建议 最小联调顺序: 1. `GET /api/v3/rag/apps` 2. `GET /api/v3/rag/apps/default` 3. `GET /api/v3/rag/chat/parameters` 4. `POST /api/v3/rag/chat/messages` 5. `GET /api/v3/rag/chat/conversations` 6. `GET /api/v3/rag/chat/conversations/{ConversationId}/messages` 优先检查: - 401:JWT 是否有效 - 403:`rag:*` 权限是否已写入并分配 - 500:LLM、数据库、Chroma、知识库配置是否可用