🎯 派洞察——科研文献智能 RAG 知识库系统

🔍 知识库检索模块

模块定位:知识库检索模块是系统的核心检索引擎,提供基于混合检索技术的智能文档搜索功能,支持语义理解和权限控制。

🎯 核心目标

  • 混合检索:结合关键词检索和语义向量检索,提供更精准的搜索结果
  • 智能理解:支持自然语言查询,理解用户搜索意图
  • 权限控制:根据用户身份和组织标签进行结果过滤
  • 高性能:优化检索性能,支持大规模文档库
  • 可扩展:支持多种检索算法和排序策略

📊 一、功能需求

🔍 混合检索

🔤 功能描述:提供基于关键词和语义向量的混合检索功能,结合两种检索方式的优势,提供更精准的搜索结果。

🔧 检索功能:

  • 支持关键词全文检索
  • 支持语义向量相似度检索
  • 自动融合两种检索结果
  • 支持自定义结果数量(topK参数)

🛡️ 权限控制

🔐 功能描述:根据用户的登录状态和组织标签,对检索结果进行权限过滤,确保用户只能访问其有权限查看的内容。

🔧 权限功能:

  • 登录用户:返回用户有权限访问的所有内容
  • 匿名用户:仅返回公开内容
  • 组织标签过滤:根据用户组织标签筛选结果
  • 私有内容保护:确保私有内容不被未授权访问

📊 结果排序

📈 功能描述:对检索结果进行智能排序,将最相关的内容优先展示给用户。

🔧 排序策略:

  • 相关性评分排序
  • 时间权重排序
  • 用户行为权重
  • 综合评分计算

📝 结果格式化

🎨 功能描述:将检索结果格式化为统一的响应结构,便于前端解析和展示。

🔧 格式功能:

  • 统一的JSON响应格式
  • 包含文档元信息(文件MD5、分片ID等)
  • 包含内容预览和评分
  • 包含权限信息(用户ID、组织标签、公开状态)

🛠️ 二、技术方案

🔍 混合检索技术

🔤 关键词检索:使用全文检索引擎(如Elasticsearch)进行基于关键词的文档检索。

🎯 向量检索:使用向量数据库(如Milvus、Pinecone)进行基于语义向量的相似度检索。

🔄 结果融合:采用加权融合算法,将关键词检索和向量检索的结果进行智能合并。

🧠 语义理解

📝 文本向量化:使用预训练语言模型(如BERT、Sentence-BERT)将文档和查询转换为向量表示。

🎯 相似度计算:使用余弦相似度等算法计算查询向量与文档向量的相似度。

🔧 语义增强:通过同义词扩展、查询重写等技术增强检索效果。

🔐 权限控制机制

👤 用户身份验证:通过JWT token验证用户身份,获取用户ID和组织标签信息。

🏷️ 组织标签过滤:根据用户的组织标签,过滤检索结果,确保内容安全。

🔒 权限层级:支持公开、组织内、私有等多层级权限控制。

📊 性能优化

缓存机制:使用Redis缓存热门查询和检索结果,减少重复计算。

🚀 异步处理:采用异步方式处理复杂的向量计算和结果融合。

📈 索引优化:优化数据库索引和向量索引,提升检索效率。

📝 三、关键流程

🔍 1. 混合检索流程

🔄 流程步骤

  1. 🔍 接收查询:接收用户搜索查询字符串和topK参数
  2. 身份验证:验证用户身份(如果有token)
  3. 🔤 关键词检索:执行基于关键词的全文检索
  4. 🎯 向量检索:执行基于语义向量的相似度检索
  5. 🔄 结果融合:将两种检索结果进行智能融合
  6. 🛡️ 权限过滤:根据用户权限过滤检索结果
  7. 📊 结果排序:对融合后的结果进行相关性排序
  8. 📤 返回结果:返回格式化的检索结果

接口设计

请求URL

1
GET /api/v1/search/hybrid?query=人工智能的发展&topK=10

请求参数

1
2
query: String     // 搜索查询字符串(必需)
topK: int // 返回结果数量(可选,默认10)

请求头(可选)

1
Authorization: Bearer JWT_TOKEN

成功响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"code": 200,
"message": "success",
"data": [
{
"fileMd5": "abc123def456",
"chunkId": 1,
"textContent": "人工智能是未来科技发展的核心方向。",
"score": 0.92,
"userId": "user123",
"orgTag": "TECH_DEPT",
"isPublic": true
},
{
"fileMd5": "def456ghi789",
"chunkId": 2,
"textContent": "机器学习算法的不断进步推动了人工智能的发展。",
"score": 0.88,
"userId": "user456",
"orgTag": "RESEARCH_TEAM",
"isPublic": false
}
]
}

失败响应

1
2
3
4
5
{
"code": 500,
"message": "检索失败: 错误信息",
"data": []
}

🔐 2. 权限控制流程

🔄 流程步骤

  1. 🔍 Token提取:从请求头中提取JWT token(如果有)
  2. 身份验证:验证token有效性,获取用户ID
  3. 🏷️ 权限获取:获取用户的组织标签和角色信息
  4. 🔍 结果检索:执行混合检索获取初步结果
  5. 🛡️ 权限过滤:根据用户权限过滤检索结果
  6. 📤 结果返回:返回用户有权限查看的内容

📊 3. 结果融合流程

🔄 流程步骤

  1. 📊 获取结果:获取关键词检索和向量检索的结果
  2. ⚖️ 权重计算:为两种检索结果分配权重
  3. 🔄 结果合并:将两种结果按照权重进行融合
  4. 📈 重新排序:对融合后的结果进行统一排序
  5. ✂️ 结果截断:根据topK参数截取最终结果

📝 4. 日志记录流程

🔄 流程步骤

  1. 🚀 开始监控:启动性能监控器
  2. 📝 业务日志:记录检索开始和参数信息
  3. 执行检索:执行混合检索操作
  4. 操作记录:记录用户操作和结果状态
  5. 📊 性能记录:记录检索耗时和结果数量
  6. 🏁 结束监控:结束性能监控

🗃️ 四、库表设计

📄 1. 文档分片表

字段设计

1
2
3
4
5
6
7
8
9
10
11
12
| 🔑 **字段** | 📋 **类型** | 📝 **描述** |
| --- | --- | --- |
| `id` | `BIGINT` | 🆔 主键,分片ID |
| `file_md5` | `VARCHAR(32)` | 📊 文件MD5哈希值 |
| `chunk_id` | `INT` | 📑 分片序号 |
| `text_content` | `TEXT` | 📝 分片文本内容 |
| `vector_embedding` | `TEXT` | 🎯 向量嵌入(JSON格式) |
| `user_id` | `VARCHAR(255)` | 👤 文档所有者ID |
| `org_tag` | `VARCHAR(100)` | 🏷️ 组织标签 |
| `is_public` | `BOOLEAN` | 🌐 是否公开 |
| `created_at` | `TIMESTAMP` | 📅 创建时间 |
| `updated_at` | `TIMESTAMP` | 🔄 更新时间 |

建表语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE TABLE document_chunks (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '分片唯一标识',
file_md5 VARCHAR(32) NOT NULL COMMENT '文件MD5哈希值',
chunk_id INT NOT NULL COMMENT '分片序号',
text_content TEXT NOT NULL COMMENT '分片文本内容',
vector_embedding TEXT COMMENT '向量嵌入(JSON格式)',
user_id VARCHAR(255) NOT NULL COMMENT '文档所有者ID',
org_tag VARCHAR(100) DEFAULT NULL COMMENT '组织标签',
is_public BOOLEAN DEFAULT FALSE COMMENT '是否公开可见',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_file_md5 (file_md5) COMMENT '文件MD5索引',
INDEX idx_user_id (user_id) COMMENT '用户ID索引',
INDEX idx_org_tag (org_tag) COMMENT '组织标签索引',
INDEX idx_is_public (is_public) COMMENT '公开状态索引',
UNIQUE KEY uk_file_chunk (file_md5, chunk_id) COMMENT '文件分片唯一约束'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档分片表';

📊 2. 检索日志表

字段设计

1
2
3
4
5
6
7
8
9
10
11
| 🔑 **字段** | 📋 **类型** | 📝 **描述** |
| --- | --- | --- |
| `id` | `BIGINT` | 🆔 主键,日志ID |
| `query` | `TEXT` | 🔍 查询字符串 |
| `user_id` | `VARCHAR(255)` | 👤 用户ID(匿名用户为空) |
| `result_count` | `INT` | 📊 返回结果数量 |
| `search_type` | `ENUM('ANONYMOUS', 'AUTHENTICATED')` | 🎯 搜索类型 |
| `response_time_ms` | `INT` | ⏱️ 响应时间(毫秒) |
| `status` | `ENUM('SUCCESS', 'FAILURE')` | ✅ 搜索状态 |
| `error_message` | `TEXT` | ❌ 错误信息 |
| `created_at` | `TIMESTAMP` | 📅 创建时间 |

建表语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE search_logs (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '日志唯一标识',
query TEXT NOT NULL COMMENT '查询字符串',
user_id VARCHAR(255) DEFAULT NULL COMMENT '用户ID',
result_count INT DEFAULT 0 COMMENT '返回结果数量',
search_type ENUM('ANONYMOUS', 'AUTHENTICATED') NOT NULL COMMENT '搜索类型',
response_time_ms INT DEFAULT NULL COMMENT '响应时间(毫秒)',
status ENUM('SUCCESS', 'FAILURE') NOT NULL COMMENT '搜索状态',
error_message TEXT COMMENT '错误信息',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX idx_user_id (user_id) COMMENT '用户ID索引',
INDEX idx_created_at (created_at) COMMENT '时间索引',
INDEX idx_search_type (search_type) COMMENT '搜索类型索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='检索日志表';

🎯 3. 向量索引配置表

字段设计

1
2
3
4
5
6
7
8
9
10
| 🔑 **字段** | 📋 **类型** | 📝 **描述** |
| --- | --- | --- |
| `id` | `BIGINT` | 🆔 主键,配置ID |
| `index_name` | `VARCHAR(100)` | 🏷️ 索引名称 |
| `vector_dimension` | `INT` | 📐 向量维度 |
| `similarity_metric` | `VARCHAR(20)` | 📏 相似度度量方式 |
| `index_type` | `VARCHAR(50)` | 🎯 索引类型 |
| `is_active` | `BOOLEAN` | ✅ 是否激活 |
| `created_at` | `TIMESTAMP` | 📅 创建时间 |
| `updated_at` | `TIMESTAMP` | 🔄 更新时间 |

建表语句

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE vector_index_configs (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '配置唯一标识',
index_name VARCHAR(100) NOT NULL UNIQUE COMMENT '索引名称',
vector_dimension INT NOT NULL COMMENT '向量维度',
similarity_metric VARCHAR(20) NOT NULL COMMENT '相似度度量方式',
index_type VARCHAR(50) NOT NULL COMMENT '索引类型',
is_active BOOLEAN DEFAULT TRUE COMMENT '是否激活',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_index_name (index_name) COMMENT '索引名称索引',
INDEX idx_is_active (is_active) COMMENT '激活状态索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='向量索引配置表';