541 lines
12 KiB
Markdown
541 lines
12 KiB
Markdown
# 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 <access_token>
|
||
```
|
||
|
||
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、知识库配置是否可用
|