文章目录
- FastGPT 引申:借鉴 FastGPT 基于MySQL + ES 实现知识库(含表结构以及核心代码)
- 一、整体思路
- 二、存储结构
- 2.1 MySQL 表结构
- (1) knowledge_base_dataset
- (2) knowledge_base_data
- (3) knowledge_base_index
- (4) ai_kb_relation
- 2.2 Elasticsearch Mapping 结构
- (1) ES索引
- (2) 字段说明
- 三、代码实现
- 3.1 调用 Embedding 服务
- 3.2 向量检索(ES KNN 查询)
- 3.3 RRF 排序(融合向量检索和文本检索结果)
- 四、总结
FastGPT 引申:借鉴 FastGPT 基于MySQL + ES 实现知识库(含表结构以及核心代码)
一、整体思路
- 知识库查询能力:引入 Elasticsearch (ES) 提供向量存储和检索能力。
- 三层逻辑结构:
- 数据集:使用模块 ID 关联应用。
- 数据:存储具体的知识内容。
- 索引:提供高效的查询能力。
二、存储结构
2.1 MySQL 表结构
(1) knowledge_base_dataset
存储数据集基本信息
字段名 | 类型 | 描述 |
---|---|---|
id | BIGINT | 主键 |
type | INT | 0:手动数据集 |
name | VARCHAR | 数据集名称 |
es_index_name | VARCHAR | ES 索引名称 |
extract_qa_prompt | TEXT | 抽取 QA 问答对 Prompt |
extract_summary_prompt | TEXT | 抽取摘要 Prompt |
extract_param_prompt | TEXT | 抽取参数 Prompt |
is_deleted | TINYINT | 逻辑删除标志 |
(2) knowledge_base_data
存储具体知识数据项
字段名 | 类型 | 描述 |
---|---|---|
id | BIGINT | 主键 |
dataset_id | BIGINT | 关联 dataset 表 |
main_content | TEXT | 主要内容 |
auxiliary_data | TEXT | 辅助数据 |
is_deleted | TINYINT | 逻辑删除标志 |
(3) knowledge_base_index
存储索引项
字段名 | 类型 | 描述 |
---|---|---|
id | BIGINT | 主键 |
data_id | BIGINT | 关联 data 表主键 |
index_type | INT | 0-默认,1-用户指定,3-提取问题,4-相关摘要 |
index_content | TEXT | 索引内容 |
(4) ai_kb_relation
存储数据集与应用关联
字段名 | 类型 | 描述 |
---|---|---|
id | BIGINT | 主键 |
module_id | BIGINT | 关联的模块 ID |
dataset_id | BIGINT | 知识库数据集 ID |
2.2 Elasticsearch Mapping 结构
(1) ES索引
存储知识数据的向量索引:ai_knowledge
{"mappings": {"properties": {"data_id": {"type": "long","index": true},"index_id": {"type": "long","index": true},"dataset_id": {"type": "long","index": true},"vector_index": {"type": "dense_vector","dims": 1024,"index": true,"similarity": "cosine"},"text_index": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"}}}
}
(2) 字段说明
字段名称 | 类型 | 说明 |
---|---|---|
data_id | long | 关联 knowledge_base_data 主键 ID |
index_id | long | 关联 knowledge_base_index 主键 ID |
dataset_id | long | 关联 knowledge_base_dataset 主键 ID |
vector_index | dense_vector | 1024 维度稠密向量,支持余弦相似度计算 |
text_index | text | 采用 ik_max_word 分词器进行索引 |
三、代码实现
3.1 调用 Embedding 服务
public List<Float> getVector(String text) {ResponseEntity responseEntity = xxxx;if (responseEntity != null && responseEntity.getCode() == 0) {List<List<Double>> vectorList = (List<List<Double>>) responseEntity.getData();if (vectorList != null && !vectorList.isEmpty()) {return vectorList.get(0).stream().map(Double::floatValue).collect(Collectors.toList());}}return null;
}
3.2 向量检索(ES KNN 查询)
public List<Knowledge> searchByVector(List<Float> vector) throws IOException {log.info("Searching knowledge with vector similarity using KNN");try {return client.search(s -> s.index(INDEX_NAME).knn(k -> k.field("vector_index").queryVector(vector).k(DEFAULT_SIZE).numCandidates(100)),Knowledge.class).hits().hits().stream().map(Hit::source).collect(Collectors.toList());} catch (Exception e) {log.error("Error searching knowledge by vector: {}", e.getMessage(), e);throw e;}
}
3.3 RRF 排序(融合向量检索和文本检索结果)
private Map<String, Double> calculateRRFScores(List<Hit<KnowledgeCommon>> vectorHits,List<Hit<KnowledgeCommon>> textHits) {Map<String, Double> rrfScores = new HashMap<>();int rank = 1;for (Hit<KnowledgeCommon> hit : vectorHits) {String id = hit.id();double score = VECTOR_WEIGHT * (1.0 / (rank + RRF_CONSTANT));rrfScores.put(id, rrfScores.getOrDefault(id, 0.0) + score);rank++;}rank = 1;for (Hit<KnowledgeCommon> hit : textHits) {String id = hit.id();double score = TEXT_WEIGHT * (1.0 / (rank + RRF_CONSTANT));rrfScores.put(id, rrfScores.getOrDefault(id, 0.0) + score);rank++;}return rrfScores;
}
四、总结
- 采用 MySQL 存储基础数据,ES 存储向量及文本索引。
- ES 结合 KNN 和分词搜索进行知识检索。
- 使用 RRF 算法融合向量和文本搜索结果,提高查询质量。
此方案支持灵活的知识管理和高效检索,可扩展至更大规模的知识库应用。