mirror of
https://github.com/labring/FastGPT.git
synced 2025-12-25 20:02:47 +00:00
Some checks are pending
Document deploy / sync-images (push) Waiting to run
Document deploy / generate-timestamp (push) Blocked by required conditions
Document deploy / build-images (map[domain:https://fastgpt.cn suffix:cn]) (push) Blocked by required conditions
Document deploy / build-images (map[domain:https://fastgpt.io suffix:io]) (push) Blocked by required conditions
Document deploy / update-images (map[deployment:fastgpt-docs domain:https://fastgpt.cn kube_config:KUBE_CONFIG_CN suffix:cn]) (push) Blocked by required conditions
Document deploy / update-images (map[deployment:fastgpt-docs domain:https://fastgpt.io kube_config:KUBE_CONFIG_IO suffix:io]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / get-vars (push) Waiting to run
Build FastGPT images in Personal warehouse / build-fastgpt-images (map[arch:amd64 runs-on:ubuntu-24.04]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / build-fastgpt-images (map[arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Blocked by required conditions
Build FastGPT images in Personal warehouse / release-fastgpt-images (push) Blocked by required conditions
* add manual create http toolset (#5743) * add manual create http toolset * optimize code * optimize * fix * fix * rename filename * feat: integrate ts-rest (#5741) * feat: integrate ts-rest * chore: classify core contract and pro contract * chore: update lockfile * chore: tweak dir structure * chore: tweak dir structure * update tsrest code (#5755) * doc * update tsrest code * fix http toolset (#5753) * fix http toolset * fix * perf: http toolset * fix: toolresponse result (#5760) * doc * fix: toolresponse result * fix: mongo watch * remove log * feat: integrated to minio (#5748) * feat: migrate to minio * feat: migrate apps' and dataset's avatar to minio * feat: migrate more avatars to minio * fix: lock file * feat: migrate copyright settings' logo to minio * feat: integrate minio * chore: improve code * chore: rename variables * refactor: s3 class * fix: s3 and mongo operations * chore: add session for avatar source * fix: init s3 buckets * fix: bugbot issues * expired time code * perf: avatar code * union type * export favouriteContract * empty bucket check --------- Co-authored-by: archer <545436317@qq.com> * refactor: zod schema to generate OpenAPI instead (#5771) * doc * fix: text split code (#5773) * fix: toolresponse result * remove log * stream remove * fix: text split code * fix: workflow (#5779) * fix: toolresponse result * remove log * fix: value check * fix: workflow * openapi doc * perf: bucket delete cron * doc * feat: apikey health * feat: export variables * api code move * perf: workflow performance (#5783) * perf: reactflow context * perf: workflow context split * perf: nodeList computed map * perf: nodes dependen * perf: workflow performance * workflow performance * removel og * lock * version * loop drag * reactflow size * reactflow size * fix: s3init (#5784) * doc * fix: s3init * perf: dynamic import * remove moongose dep * worker build * worker code * perf: worker build * fix: error throw * doc * doc * fix: build * fix: dockerfile * nextjs config * fix: worker * fix: build (#5791) * fix: build * vector cache code * fix: app info modal avatar upload method replace (#5787) * fix: app info modal avatar upload method replace * chore: replace all useSelectFile with useUploadAvatar * remove invalid code * add size * Update projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/templates/CommonInputForm.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update projects/app/src/pageComponents/app/detail/WorkflowComponents/context/workflowInitContext.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: 伍闲犬 <whoeverimf5@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
30 KiB
30 KiB
| name | description | model | color |
|---|---|---|---|
| dataset-agent | 知识库开发 Agent,负责 FastGPT 知识库模块代码开发。 | inherit | blue |
FastGPT 知识库(Dataset)模块架构说明
概述
FastGPT 知识库模块是一个基于 MongoDB + PostgreSQL(向量数据库) 的 RAG(检索增强生成)知识库系统,支持多种数据源导入、智能文档分块、向量化索引、混合检索等核心能力。
核心概念层次结构
Dataset (知识库)
├── DatasetCollection (文档集合/文件)
│ ├── DatasetData (数据块/Chunk)
│ │ ├── indexes[] (向量索引)
│ │ └── history[] (历史版本)
│ └── DatasetTraining (训练队列)
└── Tag (标签系统)
1. Dataset (知识库)
- 作用: 最顶层容器,可以是普通知识库、文件夹、网站知识库或外部数据源
- 类型:
folder: 文件夹组织dataset: 普通知识库websiteDataset: 网站深度链接apiDataset: API 数据集feishu: 飞书知识库yuque: 语雀知识库externalFile: 外部文件
2. DatasetCollection (文档集合)
- 作用: 知识库中的具体文件或文档,承载原始数据
- 类型:
folder: 文件夹file: 本地文件link: 单个链接apiFile: API 文件images: 图片集合virtual: 虚拟集合
3. DatasetData (数据块)
- 作用: 文档分块后的最小知识单元,实际检索的对象
- 核心字段:
q: 问题或大块文本a: 答案或自定义内容indexes[]: 向量索引列表(可多个)chunkIndex: 块索引位置imageId: 关联图片IDhistory[]: 修改历史
4. DatasetTraining (训练队列)
- 作用: 异步训练任务队列,负责向量化和索引生成
- 训练模式:
chunk: 文本分块qa: 问答对image: 图像处理imageParse: 图像解析
代码目录结构
Packages 层(共享代码)
1. packages/global/core/dataset/
类型定义和常量
├── constants.ts # 所有枚举定义(类型、状态、模式)
├── type.d.ts # TypeScript 类型定义
├── api.d.ts # API 接口类型
├── controller.d.ts # 控制器类型定义
├── utils.ts # 通用工具函数
├── collection/
│ ├── constants.ts # 集合相关常量
│ └── utils.ts # 集合工具函数
├── data/
│ └── constants.ts # 数据相关常量
├── training/
│ ├── type.d.ts # 训练相关类型
│ └── utils.ts # 训练工具函数
├── apiDataset/
│ ├── type.d.ts # API数据集类型
│ └── utils.ts # API数据集工具
└── search/
└── utils.ts # 搜索工具函数
关键枚举定义:
DatasetTypeEnum: 知识库类型DatasetCollectionTypeEnum: 集合类型DatasetSearchModeEnum: 搜索模式(embedding/fullText/mixed)TrainingModeEnum: 训练模式DatasetCollectionDataProcessModeEnum: 数据处理模式
2. packages/service/core/dataset/
业务逻辑和数据库操作
├── schema.ts # Dataset MongoDB Schema
├── controller.ts # Dataset 核心控制器
├── utils.ts # 业务工具函数
├── collection/
│ ├── schema.ts # Collection Schema
│ ├── controller.ts # Collection 控制器
│ └── utils.ts # Collection 工具
├── data/
│ ├── schema.ts # DatasetData Schema
│ ├── dataTextSchema.ts # 全文搜索 Schema
│ └── controller.ts # Data 控制器
├── training/
│ ├── schema.ts # Training Schema
│ ├── controller.ts # Training 控制器
│ └── constants.ts # Training 常量
├── tag/
│ └── schema.ts # Tag Schema
├── image/
│ ├── schema.ts # Image Schema
│ └── utils.ts # Image 工具
├── search/
│ ├── controller.ts # 🔥 核心检索控制器
│ └── utils.ts # 检索工具函数
└── apiDataset/
├── index.ts # API数据集入口
├── custom/api.ts # 自定义API
├── feishuDataset/api.ts # 飞书集成
└── yuqueDataset/api.ts # 语雀集成
Projects 层(应用实现)
3. projects/app/src/pages/api/core/dataset/
NextJS API 路由
├── detail.ts # 获取知识库详情
├── delete.ts # 删除知识库
├── paths.ts # 获取路径信息
├── exportAll.ts # 导出全部数据
├── collection/
│ ├── create.ts # 创建集合(基础)
│ ├── create/
│ │ ├── localFile.ts # 本地文件导入
│ │ ├── link.ts # 链接导入
│ │ ├── text.ts # 文本导入
│ │ ├── images.ts # 图片导入
│ │ ├── apiCollection.ts # API集合
│ │ └── fileId.ts # 文件ID导入
│ ├── update.ts # 更新集合
│ ├── list.ts # 集合列表
│ ├── detail.ts # 集合详情
│ ├── sync.ts # 同步集合
│ └── export.ts # 导出集合
├── data/
│ ├── list.ts # 数据列表
│ ├── detail.ts # 数据详情
│ ├── insertData.ts # 插入数据
│ ├── pushData.ts # 推送数据
│ ├── update.ts # 更新数据
│ └── delete.ts # 删除数据
├── training/
│ ├── getDatasetTrainingQueue.ts # 获取训练队列
│ ├── getTrainingDataDetail.ts # 训练数据详情
│ ├── updateTrainingData.ts # 更新训练数据
│ ├── deleteTrainingData.ts # 删除训练数据
│ └── getTrainingError.ts # 获取训练错误
└── apiDataset/
├── list.ts # API数据集列表
├── getCatalog.ts # 获取目录
└── getPathNames.ts # 获取路径名
4. projects/app/src/components/ 和 pageComponents/
前端组件
components/core/dataset/ # 通用组件
├── SelectModal.tsx # 知识库选择器
├── QuoteItem.tsx # 引用项展示
├── DatasetTypeTag.tsx # 类型标签
├── RawSourceBox.tsx # 原始来源展示
└── SearchParamsTip.tsx # 搜索参数提示
pageComponents/dataset/ # 页面组件
├── list/ # 列表页
│ └── SideTag.tsx # 侧边标签
├── detail/ # 详情页
│ ├── CollectionCard/ # 集合卡片
│ ├── DataCard.tsx # 数据卡片
│ ├── Test.tsx # 测试组件
│ ├── Info/ # 信息组件
│ ├── Import/ # 导入组件
│ │ ├── diffSource/ # 不同数据源
│ │ ├── components/ # 公共组件
│ │ └── commonProgress/ # 进度组件
│ └── Form/ # 表单组件
└── ApiDatasetForm.tsx # API数据集表单
数据库 Schema 详解
1. Dataset Schema (datasets 集合)
{
_id: ObjectId,
parentId: ObjectId | null, // 父级ID(支持文件夹)
teamId: ObjectId, // 团队ID
tmbId: ObjectId, // 团队成员ID
type: DatasetTypeEnum, // 知识库类型
avatar: string, // 头像
name: string, // 名称
intro: string, // 简介
updateTime: Date, // 更新时间
vectorModel: string, // 向量模型
agentModel: string, // AI模型
vlmModel?: string, // 视觉语言模型
websiteConfig?: { // 网站配置
url: string,
selector: string
},
chunkSettings: { // 分块配置
trainingType: DatasetCollectionDataProcessModeEnum,
chunkTriggerType: ChunkTriggerConfigTypeEnum,
chunkTriggerMinSize: number,
chunkSettingMode: ChunkSettingModeEnum,
chunkSplitMode: DataChunkSplitModeEnum,
chunkSize: number,
chunkSplitter: string,
indexSize: number,
qaPrompt: string,
// ... 更多配置
},
inheritPermission: boolean, // 继承权限
apiDatasetServer?: object // API服务器配置
}
// 索引
teamId_1
type_1
2. DatasetCollection Schema (dataset_collections 集合)
{
_id: ObjectId,
parentId: ObjectId | null, // 父级集合
teamId: ObjectId,
tmbId: ObjectId,
datasetId: ObjectId, // 所属知识库
type: DatasetCollectionTypeEnum, // 集合类型
name: string, // 名称
tags: string[], // 标签ID列表
createTime: Date,
updateTime: Date,
// 元数据(根据类型不同)
fileId?: ObjectId, // 本地文件ID
rawLink?: string, // 原始链接
apiFileId?: string, // API文件ID
externalFileId?: string, // 外部文件ID
externalFileUrl?: string, // 外部导入URL
rawTextLength?: number, // 原始文本长度
hashRawText?: string, // 文本哈希
metadata?: object, // 其他元数据
forbid: boolean, // 是否禁用
// 解析配置
customPdfParse?: boolean,
apiFileParentId?: string,
// 分块配置(继承自 ChunkSettings)
...chunkSettings
}
// 索引
teamId_1_fileId_1
teamId_1_datasetId_1_parentId_1_updateTime_-1
teamId_1_datasetId_1_tags_1
teamId_1_datasetId_1_createTime_1
datasetId_1_externalFileId_1 (unique)
3. DatasetData Schema (dataset_datas 集合)
{
_id: ObjectId,
teamId: ObjectId,
tmbId: ObjectId,
datasetId: ObjectId,
collectionId: ObjectId,
q: string, // 问题/大块文本
a?: string, // 答案/自定义内容
imageId?: string, // 图片ID
imageDescMap?: object, // 图片描述映射
updateTime: Date,
chunkIndex: number, // 块索引
indexes: [{ // 向量索引数组
type: DatasetDataIndexTypeEnum,
dataId: string, // PG向量数据ID
text: string // 索引文本
}],
history?: [{ // 历史版本
q: string,
a?: string,
updateTime: Date
}],
rebuilding?: boolean // 重建中标志
}
// 索引
teamId_1_datasetId_1_collectionId_1_chunkIndex_1_updateTime_-1
teamId_1_datasetId_1_collectionId_1_indexes.dataId_1
rebuilding_1_teamId_1_datasetId_1
4. DatasetTraining Schema (dataset_trainings 集合)
{
_id: ObjectId,
teamId: ObjectId,
tmbId: ObjectId,
datasetId: ObjectId,
collectionId: ObjectId,
billId?: string, // 账单ID
mode: TrainingModeEnum, // 训练模式
expireAt: Date, // 过期时间(7天自动删除)
lockTime: Date, // 锁定时间
retryCount: number, // 重试次数
q: string, // 待训练问题
a: string, // 待训练答案
imageId?: string,
imageDescMap?: object,
chunkIndex: number,
indexSize?: number,
weight: number, // 权重
dataId?: ObjectId, // 关联的DatasetData ID
indexes: [{ // 待生成的索引
type: DatasetDataIndexTypeEnum,
text: string
}],
errorMsg?: string // 错误信息
}
// 索引
teamId_1_datasetId_1
mode_1_retryCount_1_lockTime_1_weight_-1
expireAt_1 (TTL: 7 days)
5. 辅助 Schema
DatasetCollectionTags (dataset_collection_tags)
{
_id: ObjectId,
teamId: ObjectId,
datasetId: ObjectId,
tag: string // 标签名称
}
DatasetDataText (dataset_data_texts) - 全文搜索
{
_id: ObjectId,
teamId: ObjectId,
datasetId: ObjectId,
collectionId: ObjectId,
dataId: ObjectId, // 关联 DatasetData
fullTextToken: string // 全文搜索Token
}
// 全文索引
fullTextToken: text
核心业务流程
1. 数据导入流程
用户上传文件/链接
↓
创建 DatasetCollection
↓
文件解析 & 预处理
↓
文本分块(根据 ChunkSettings)
↓
创建 DatasetTraining 任务
↓
后台队列处理:
- 向量化(embedding)
- 创建 PG 向量索引
- 生成 DatasetData
- 创建全文搜索索引(DatasetDataText)
↓
训练完成,可以检索
关键代码位置:
- 文件上传:
projects/app/src/pages/api/core/dataset/collection/create/localFile.ts - 分块逻辑:
packages/service/core/dataset/collection/utils.ts - 训练控制:
packages/service/core/dataset/training/controller.ts
2. 检索流程(核心算法)
位置: packages/service/core/dataset/search/controller.ts
// 三种检索模式
enum DatasetSearchModeEnum {
embedding = 'embedding', // 纯向量检索
fullTextRecall = 'fullTextRecall', // 纯全文检索
mixedRecall = 'mixedRecall' // 混合检索
}
// 检索流程
async function searchDatasetData(props) {
// 1. 参数初始化和权重配置
const { embeddingWeight, rerankWeight } = props;
// 2. 集合过滤(标签/时间/禁用)
const filterCollectionIds = await filterCollectionByMetadata();
// 3. 多路召回
const { embeddingRecallResults, fullTextRecallResults } =
await multiQueryRecall({
embeddingLimit: 80, // 向量召回数量
fullTextLimit: 60 // 全文召回数量
});
// 4. RRF(倒数排名融合)合并
const rrfResults = datasetSearchResultConcat([
{ weight: embeddingWeight, list: embeddingRecallResults },
{ weight: 1 - embeddingWeight, list: fullTextRecallResults }
]);
// 5. ReRank 重排序(可选)
if (usingReRank) {
const reRankResults = await datasetDataReRank({
rerankModel,
query: reRankQuery,
data: rrfResults
});
}
// 6. 相似度过滤
const scoreFiltered = results.filter(item =>
item.score >= similarity
);
// 7. Token 限制过滤
const finalResults = await filterDatasetDataByMaxTokens(
scoreFiltered,
maxTokens
);
return finalResults;
}
核心算法详解:
a. 向量召回 (embeddingRecall)
// 1. 查询向量化
const { vectors, tokens } = await getVectorsByText({
model: getEmbeddingModel(model),
input: queries,
type: 'query'
});
// 2. PG 向量库召回
const recallResults = await Promise.all(
vectors.map(vector =>
recallFromVectorStore({
teamId,
datasetIds,
vector,
limit,
forbidCollectionIdList,
filterCollectionIdList
})
)
);
// 3. 关联 MongoDB 数据
const dataMaps = await MongoDatasetData.find({
teamId,
datasetId: { $in: datasetIds },
'indexes.dataId': { $in: indexDataIds }
});
b. 全文召回 (fullTextRecall)
// MongoDB 全文搜索
const results = await MongoDatasetDataText.aggregate([
{
$match: {
teamId: new Types.ObjectId(teamId),
$text: { $search: await jiebaSplit({ text: query }) },
datasetId: { $in: datasetIds.map(id => new Types.ObjectId(id)) }
}
},
{
$sort: {
score: { $meta: 'textScore' }
}
},
{
$limit: limit
}
]);
c. RRF 合并算法
// 倒数排名融合(Reciprocal Rank Fusion)
function datasetSearchResultConcat(weightedLists) {
const k = 60; // RRF 参数
const scoreMap = new Map();
for (const { weight, list } of weightedLists) {
list.forEach((item, index) => {
const rrfScore = weight / (k + index + 1);
scoreMap.set(item.id,
(scoreMap.get(item.id) || 0) + rrfScore
);
});
}
return Array.from(scoreMap.entries())
.sort((a, b) => b[1] - a[1])
.map(([id]) => findItemById(id));
}
d. ReRank 重排序
// 使用重排序模型(如 bge-reranker)
const { results } = await reRankRecall({
model: rerankModel,
query: reRankQuery,
documents: data.map(item => ({
id: item.id,
text: `${item.q}\n${item.a}`
}))
});
// 重排序结果融合到 RRF 结果
const finalResults = datasetSearchResultConcat([
{ weight: 1 - rerankWeight, list: rrfResults },
{ weight: rerankWeight, list: reRankResults }
]);
3. 分块策略
位置: packages/global/core/dataset/constants.ts
// 分块模式
enum DataChunkSplitModeEnum {
paragraph = 'paragraph', // 段落分割(智能)
size = 'size', // 固定大小分割
char = 'char' // 字符分隔符分割
}
// AI 段落模式
enum ParagraphChunkAIModeEnum {
auto = 'auto', // 自动判断
force = 'force', // 强制使用AI
forbid = 'forbid' // 禁用AI
}
// 分块配置示例
const chunkSettings = {
chunkSplitMode: 'paragraph',
chunkSize: 512, // 最大块大小
chunkSplitter: '\n', // 分隔符
paragraphChunkDeep: 2, // 段落层级
paragraphChunkMinSize: 100, // 最小段落大小
indexSize: 256, // 索引大小
// 数据增强
dataEnhanceCollectionName: true,
autoIndexes: true, // 自动多索引
indexPrefixTitle: true // 索引前缀标题
}
4. 训练队列机制
位置: packages/service/core/dataset/training/controller.ts
// 训练队列调度
class TrainingQueue {
// 1. 获取待训练任务(按权重排序)
async getNextTrainingTask() {
return MongoDatasetTraining.findOne({
mode: { $in: supportedModes },
retryCount: { $gt: 0 },
lockTime: { $lt: new Date(Date.now() - lockTimeout) }
})
.sort({ weight: -1, lockTime: 1 })
.limit(1);
}
// 2. 锁定任务
async lockTask(taskId) {
await MongoDatasetTraining.updateOne(
{ _id: taskId },
{ $set: { lockTime: new Date() } }
);
}
// 3. 执行向量化
async processTask(task) {
const vectors = await getVectorsByText({
model: getEmbeddingModel(task.model),
input: task.indexes.map(i => i.text)
});
// 保存到 PG 向量库
const indexDataIds = await saveToVectorDB(vectors);
// 创建 DatasetData
await MongoDatasetData.create({
...task,
indexes: task.indexes.map((idx, i) => ({
...idx,
dataId: indexDataIds[i]
}))
});
}
// 4. 完成/失败处理
async completeTask(taskId, success, error) {
if (success) {
await MongoDatasetTraining.deleteOne({ _id: taskId });
} else {
await MongoDatasetTraining.updateOne(
{ _id: taskId },
{
$inc: { retryCount: -1 },
$set: {
errorMsg: error,
lockTime: new Date('2000/1/1')
}
}
);
}
}
}
关键技术点
1. 多索引机制
为什么需要多索引?
- 大块文本可以拆分为多个小索引,提高召回精度
- 支持不同粒度的检索(粗粒度+细粒度)
// DatasetData 中的 indexes 数组
{
q: "这是一段很长的文本...",
indexes: [
{
type: 'custom', // 自定义索引
dataId: 'pg_vector_id_1',
text: "第一部分索引文本"
},
{
type: 'custom',
dataId: 'pg_vector_id_2',
text: "第二部分索引文本"
}
]
}
2. 混合检索(Hybrid Search)
结合向量检索和全文检索的优势:
- 向量检索: 语义相似度,理解意图
- 全文检索: 精确匹配关键词,高召回
- RRF 融合: 互补优势,提升整体效果
权重配置:
{
searchMode: 'mixedRecall',
embeddingWeight: 0.5, // 向量权重
// fullTextWeight = 1 - 0.5 = 0.5
usingReRank: true,
rerankWeight: 0.7 // 重排序权重
}
3. 集合过滤(Collection Filter)
支持灵活的元数据过滤:
// 标签过滤
{
tags: {
$and: ["标签1", "标签2"], // 必须同时包含
$or: ["标签3", "标签4", null] // 包含任一,null表示无标签
}
}
// 时间过滤
{
createTime: {
$gte: '2024-01-01',
$lte: '2024-12-31'
}
}
4. 向量数据库架构
双数据库架构:
MongoDB (元数据 + 全文索引)
- 存储原始文本、配置、关系
- 全文搜索索引(jieba 分词)
PostgreSQL + pgvector (向量存储)
- 高维向量存储
- 高效余弦相似度检索
- HNSW 索引加速
数据流转:
原始文本 → Embedding API → 向量 → PG 存储
↓
索引ID 存回 MongoDB
检索时:
查询文本 → 向量 → PG 召回 topK →
获取 dataIds → MongoDB 查询完整数据
5. 图片知识库
特殊的图片处理流程:
// 1. 图片上传
{
type: 'images',
imageId: 'image_storage_id'
}
// 2. 图片向量化(VLM)
const imageVector = await getImageEmbedding({
model: vlmModel,
imageId
});
// 3. 图片描述映射
{
imageDescMap: {
'image_url_1': '这是一张产品图片',
'image_url_2': '这是一张流程图'
}
}
// 4. 检索时返回预签名URL
const previewUrl = getDatasetImagePreviewUrl({
imageId,
teamId,
datasetId,
expiredMinutes: 60 * 24 * 7 // 7天有效
});
API 路由映射
Dataset 基础操作
GET /api/core/dataset/detail # 获取知识库详情
DELETE /api/core/dataset/delete # 删除知识库
GET /api/core/dataset/paths # 获取路径
POST /api/core/dataset/exportAll # 导出全部
Collection 操作
POST /api/core/dataset/collection/create # 创建集合
POST /api/core/dataset/collection/create/localFile # 本地文件
POST /api/core/dataset/collection/create/link # 链接导入
POST /api/core/dataset/collection/create/text # 文本导入
POST /api/core/dataset/collection/create/images # 图片导入
PUT /api/core/dataset/collection/update # 更新集合
GET /api/core/dataset/collection/list # 集合列表
GET /api/core/dataset/collection/detail # 集合详情
POST /api/core/dataset/collection/sync # 同步集合
GET /api/core/dataset/collection/export # 导出集合
Data 操作
GET /api/core/dataset/data/list # 数据列表
GET /api/core/dataset/data/detail # 数据详情
POST /api/core/dataset/data/insertData # 插入数据
POST /api/core/dataset/data/pushData # 推送数据(批量)
PUT /api/core/dataset/data/update # 更新数据
DELETE /api/core/dataset/data/delete # 删除数据
Training 操作
GET /api/core/dataset/training/getDatasetTrainingQueue # 训练队列
GET /api/core/dataset/training/getTrainingDataDetail # 训练详情
PUT /api/core/dataset/training/updateTrainingData # 更新训练
DELETE /api/core/dataset/training/deleteTrainingData # 删除训练
GET /api/core/dataset/training/getTrainingError # 获取错误
前端状态管理
位置: projects/app/src/web/core/dataset/store/
// dataset.ts - 知识库状态
{
datasets: DatasetListItemType[],
currentDataset: DatasetItemType,
loadDatasets: () => Promise<void>,
createDataset: (data) => Promise<string>,
updateDataset: (data) => Promise<void>,
deleteDataset: (id) => Promise<void>
}
// searchTest.ts - 搜索测试状态
{
searchQuery: string,
searchMode: DatasetSearchModeEnum,
similarity: number,
limit: number,
searchResults: SearchDataResponseItemType[],
performSearch: () => Promise<void>
}
性能优化要点
1. 索引优化
// 核心复合索引
DatasetCollection:
- { teamId: 1, datasetId: 1, parentId: 1, updateTime: -1 }
- { teamId: 1, datasetId: 1, tags: 1 }
DatasetData:
- { teamId: 1, datasetId: 1, collectionId: 1, chunkIndex: 1, updateTime: -1 }
- { teamId: 1, datasetId: 1, collectionId: 1, 'indexes.dataId': 1 }
DatasetTraining:
- { mode: 1, retryCount: 1, lockTime: 1, weight: -1 }
2. 查询优化
// 使用从库读取(降低主库压力)
const readFromSecondary = {
readPreference: 'secondaryPreferred'
};
MongoDatasetData.find(query, fields, {
...readFromSecondary
}).lean();
3. 分页优化
// 使用 scrollList 而非传统分页
// 避免深度分页性能问题
GET /api/core/dataset/collection/scrollList?lastId=xxx&limit=20
4. 缓存策略
// Redis 缓存热门检索结果
const cacheKey = `dataset:search:${hashQuery(query)}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
// 缓存 5 分钟
await redis.setex(cacheKey, 300, JSON.stringify(results));
测试覆盖
测试文件位置: projects/app/test/api/core/dataset/
├── create.test.ts # 知识库创建
├── paths.test.ts # 路径测试
├── collection/
│ └── paths.test.ts # 集合路径
└── training/
├── deleteTrainingData.test.ts # 训练删除
├── getTrainingError.test.ts # 训练错误
└── updateTrainingData.test.ts # 训练更新
常见开发任务
1. 添加新的数据源类型
步骤:
- 在
packages/global/core/dataset/constants.ts添加新类型枚举 - 在
packages/service/core/dataset/apiDataset/创建新集成 - 在
projects/app/src/pages/api/core/dataset/collection/create/添加 API 路由 - 在
projects/app/src/pageComponents/dataset/detail/Import/diffSource/添加前端组件
2. 修改检索算法
核心文件: packages/service/core/dataset/search/controller.ts
关键函数:
embeddingRecall: 向量召回逻辑fullTextRecall: 全文召回逻辑datasetSearchResultConcat: RRF 融合算法datasetDataReRank: 重排序逻辑
3. 优化分块策略
核心文件: packages/service/core/dataset/collection/utils.ts
关键逻辑:
- 段落识别
- 智能合并小块
- 标题提取
- 多索引生成
4. 添加新的训练模式
步骤:
- 在
TrainingModeEnum添加新模式 - 在
packages/service/core/dataset/training/controller.ts添加处理逻辑 - 更新训练队列调度器
依赖关系图
Dataset (1:N)
├─→ DatasetCollection (1:N)
│ ├─→ DatasetData (1:N)
│ │ └─→ PG Vectors (1:N)
│ └─→ DatasetTraining (1:N)
│ └─→ Bills (1:1)
└─→ DatasetCollectionTags (1:N)
└─→ DatasetCollection.tags[] (N:M)
权限系统
位置: packages/global/support/permission/dataset/
// 权限级别
enum PermissionTypeEnum {
owner = 'owner', // 所有者
manage = 'manage', // 管理员
write = 'write', // 编辑
read = 'read' // 只读
}
// 权限继承
{
inheritPermission: true // 从父级继承权限
}
// 协作者管理
DatasetCollaborators: {
datasetId,
tmbId,
permission: PermissionTypeEnum
}
国际化
位置: packages/web/i18n/
// 知识库相关翻译 key
'dataset:common_dataset'
'dataset:folder_dataset'
'dataset:website_dataset'
'dataset:api_file'
'dataset:sync_collection_failed'
'dataset:training.Image mode'
// ... 更多
调试技巧
1. 查看训练队列状态
// MongoDB Shell
db.dataset_trainings.find({
teamId: ObjectId('xxx')
}).sort({ weight: -1, lockTime: 1 }).limit(10)
2. 检查向量索引
// PG SQL
SELECT datasetid, count(*)
FROM pg_vectors
GROUP BY datasetid;
3. 全文搜索测试
db.dataset_data_texts.find({
$text: { $search: "测试查询" }
}, {
score: { $meta: "textScore" }
}).sort({ score: { $meta: "textScore" } })
4. 查看检索日志
// 开启详细日志
searchDatasetData({
...props,
debug: true // 输出详细召回信息
})
最佳实践
1. 分块大小设置
- 短文档:
chunkSize: 256-512 - 长文档:
chunkSize: 512-1024 - FAQ:
chunkSize: 128-256
2. 检索参数调优
// 高精度场景(客服)
{
searchMode: 'mixedRecall',
similarity: 0.7, // 较高阈值
embeddingWeight: 0.6, // 偏向语义
usingReRank: true,
rerankWeight: 0.8
}
// 高召回场景(搜索)
{
searchMode: 'mixedRecall',
similarity: 0.4, // 较低阈值
embeddingWeight: 0.4, // 偏向全文
usingReRank: false
}
3. 标签组织
按主题: #产品文档 #技术规范 #客服FAQ
按来源: #官网 #手册 #社区
按时效: #2024Q1 #最新版本
4. 性能监控
// 关键指标
- 训练队列长度
- 检索平均耗时
- Token 消耗量
- 向量库大小
- 召回率/准确率
扩展阅读
相关文档
外部依赖
pgvector: PostgreSQL 向量扩展jieba: 中文分词库tiktoken: Token 计数pdf-parse: PDF 解析mammoth: Word 解析
总结
FastGPT 知识库模块是一个完整的 RAG 系统实现,核心特点:
- 分层架构: Dataset → Collection → Data → Indexes
- 混合检索: 向量 + 全文 + 重排序,灵活配置权重
- 异步训练: 队列化向量化任务,支持重试和失败处理
- 双数据库: MongoDB 存元数据,PG 存向量
- 多数据源: 支持文件/链接/API/外部集成
- 灵活分块: 段落/大小/字符多种策略
- 权限控制: 继承式权限管理
开发时重点关注:
- 检索性能:
search/controller.ts - 分块质量:
collection/utils.ts - 训练队列:
training/controller.ts - 数据流转: Schema 之间的关联关系