FastGPT知识库文本处理完整分析
1. 支持的文本输入类型
FastGPT支持多种文本输入类型,定义在 DatasetTypeEnum
和 ImportDataSourceEnum
中:
导出数据支持数据集类型
folder
- 文件夹dataset
- 普通数据集websiteDataset
- 网站数据集externalFile
- 外部文件apiDataset
- API数据集feishu
- 飞书数据集yuque
- 语雀数据集
导入数据源
fileLocal
- 本地文件上传fileLink
- 链接导入fileCustom
- 手动输入文本csvTable
- CSV表格导入externalFile
- 外部文件apiDataset
- API数据集reTraining
- 重新训练
2. 文件格式支持
支持的文件格式(在 readRawContentByFileBuffer
中处理):
typescript
// 支持的文件扩展名
const supportedExtensions = [
'txt', 'md', 'html', 'pdf', 'docx', 'pptx', 'xlsx', 'csv'
];
3. 文本处理流程
3.1 文件读取阶段
核心文件: packages/service/core/dataset/read.ts
typescript
// 根据不同数据源读取原始文本
export const readDatasetSourceRawText = async ({
teamId,
type,
sourceId,
isQAImport,
selector,
externalFileId,
apiServer,
feishuServer,
yuqueServer
}) => {
if (type === DatasetSourceReadTypeEnum.fileLocal) {
// 从MongoDB GridFS读取本地文件
const { rawText } = await readFileContentFromMongo({
teamId,
bucketName: BucketNameEnum.dataset,
fileId: sourceId,
isQAImport
});
return rawText;
} else if (type === DatasetSourceReadTypeEnum.link) {
// 网页链接抓取
const result = await urlsFetch({
urlList: [sourceId],
selector
});
return result[0]?.content || '';
} else if (type === DatasetSourceReadTypeEnum.externalFile) {
// 外部文件URL读取
const rawText = await readFileRawTextByUrl({
teamId,
url: sourceId,
relatedId: externalFileId
});
return rawText;
} else if (type === DatasetSourceReadTypeEnum.apiFile) {
// API数据集文件读取
const rawText = await readApiServerFileContent({
apiServer,
feishuServer,
yuqueServer,
apiFileId: sourceId,
teamId
});
return rawText;
}
return '';
};
3.2 文件内容解析
核心文件: packages/service/worker/readFile/index.ts
typescript
// Worker进程处理不同格式文件
const readRawContentByFileBuffer = async (params) => {
switch (params.extension) {
case 'txt':
case 'md':
return readFileRawText(params);
case 'html':
return readHtmlRawText(params);
case 'pdf':
return readPdfFile(params);
case 'docx':
return readDocsFile(params);
case 'pptx':
return readPptxRawText(params);
case 'xlsx':
return readXlsxRawText(params);
case 'csv':
return readCsvRawText(params);
default:
return Promise.reject('不支持的文件格式');
}
};
3.3 文本分块处理
核心文件: packages/service/core/dataset/read.ts
typescript
// 将原始文本转换为训练块
export const rawText2Chunks = ({
rawText,
isQAImport,
chunkLen = 512,
...splitProps
}) => {
if (isQAImport) {
// CSV QA格式导入
const { chunks } = parseCsvTable2Chunks(rawText);
return chunks;
}
// 普通文本分块
const { chunks } = splitText2Chunks({
text: rawText,
chunkLen,
...splitProps
});
return chunks.map((item) => ({
q: item,
a: ''
}));
};
4. 训练模式
核心文件: packages/global/core/dataset/constants.ts
typescript
export enum TrainingModeEnum {
chunk = 'chunk', // 直接分块
auto = 'auto', // 自动处理
qa = 'qa' // 问答对
}
export const TrainingTypeMap = {
[TrainingModeEnum.chunk]: {
label: '直接分块模式',
tooltip: '将文本按长度切分成块',
openSource: true
},
[TrainingModeEnum.auto]: {
label: '自动处理模式',
tooltip: 'AI自动优化处理',
openSource: false
},
[TrainingModeEnum.qa]: {
label: 'QA拆分模式',
tooltip: '问答对格式导入',
openSource: true
}
};
5. 数据存储结构
5.1 数据集Schema
核心文件: packages/service/core/dataset/schema.ts
typescript
// 数据集基本信息
const DatasetSchema = new Schema({
teamId: { type: Schema.Types.ObjectId, required: true },
name: { type: String, required: true },
avatar: { type: String, default: '' },
intro: { type: String, default: '' },
type: { type: String, required: true },
status: { type: String, default: DatasetStatusEnum.active },
vectorModel: { type: String, required: true },
agentModel: { type: String, required: true },
// 网站配置
websiteConfig: {
url: String,
selector: String
},
// API服务器配置
apiServer: Object,
feishuServer: Object,
yuqueServer: Object,
autoSync: { type: Boolean, default: false }
});
5.2 集合Schema
核心文件: packages/service/core/dataset/collection/schema.ts
typescript
// 数据集合(文件/文档)
const DatasetCollectionSchema = new Schema({
teamId: { type: Schema.Types.ObjectId, required: true },
datasetId: { type: Schema.Types.ObjectId, required: true },
parentId: Schema.Types.ObjectId,
name: { type: String, required: true },
type: { type: String, required: true },
// 训练配置
trainingType: { type: String, default: TrainingModeEnum.chunk },
chunkSize: { type: Number, default: 512 },
chunkSplitter: String,
qaPrompt: String,
// 文件信息
fileId: String, // 本地文件ID
rawLink: String, // 链接URL
externalFileId: String, // 外部文件ID
apiFileId: String, // API文件ID
// 文本信息
rawTextLength: Number,
hashRawText: String,
// 元数据
metadata: {
webPageSelector: String,
relatedImgId: String,
type: Object
},
tags: [String],
nextSyncTime: Date
});
5.3 数据块Schema
核心文件: packages/service/core/dataset/data/schema.ts
typescript
// 训练数据块
const DatasetDataSchema = new Schema({
teamId: { type: Schema.Types.ObjectId, required: true },
datasetId: { type: Schema.Types.ObjectId, required: true },
collectionId: { type: Schema.Types.ObjectId, required: true },
q: { type: String, required: true }, // 问题或文本块
a: { type: String, default: '' }, // 答案或补充内容
chunkIndex: { type: Number, default: 0 },
// 向量索引
indexes: [{
defaultIndex: { type: Boolean, default: false },
dataId: { type: String, required: true },
text: { type: String, required: true }
}],
updateTime: { type: Date, default: Date.now },
rebuilding: Boolean
});
6. 向量化处理
核心文件: packages/service/common/vectorStore/controller.ts
typescript
// 插入向量数据
export const insertDatasetDataVector = async ({
model,
query,
...props
}) => {
// 生成向量
const { vectors, tokens } = await getVectorsByText({
model,
input: query,
type: 'db'
});
// 插入向量数据库
const { insertId } = await Vector.insert({
...props,
vector: vectors[0]
});
return { tokens, insertId };
};
7. 搜索检索
核心文件: packages/service/core/dataset/search/controller.ts
支持三种搜索模式:
typescript
export enum DatasetSearchModeEnum {
embedding = 'embedding', // 向量搜索
fullTextRecall = 'fullTextRecall', // 全文搜索
mixedRecall = 'mixedRecall' // 混合搜索
}
// 主搜索函数
export async function searchDatasetData(props) {
// 1. 向量召回
const embeddingRecall = async ({ query, limit }) => {
const { vectors } = await getVectorsByText({
model: getEmbeddingModel(model),
input: query,
type: 'query'
});
const { results } = await recallFromVectorStore({
teamId,
datasetIds,
vector: vectors[0],
limit
});
return formatResults(results);
};
// 2. 全文召回
const fullTextRecall = async ({ query, limit }) => {
const searchResults = await MongoDatasetDataText.aggregate([
{
$match: {
teamId: new Types.ObjectId(teamId),
datasetId: { $in: datasetIds },
$text: { $search: jiebaSplit({ text: query }) }
}
},
{ $sort: { score: { $meta: 'textScore' } } },
{ $limit: limit }
]);
return formatResults(searchResults);
};
// 3. 重排序
const reRankResults = usingReRank
? await datasetDataReRank({ query: reRankQuery, data: concatResults })
: [];
// 4. RRF融合多路召回结果
const rrfConcatResults = datasetSearchResultConcat([
{ k: 60, list: embeddingRecallResults },
{ k: 60, list: fullTextRecallResults },
{ k: 58, list: reRankResults }
]);
return filterAndRankResults(rrfConcatResults);
}
8. 前端导入界面
核心文件: projects/app/src/pageComponents/dataset/detail/Import/
支持多种导入方式的前端组件:
FileLocal.tsx
- 本地文件上传FileCustomText.tsx
- 手动输入文本FileLink.tsx
- 网页链接导入TableLocal.tsx
- CSV表格导入ExternalFile.tsx
- 外部文件导入APIDataset.tsx
- API数据集导入
9. 关键代码文件路径
后端核心文件
packages/global/core/dataset/constants.ts
- 数据集常量定义packages/global/core/dataset/type.d.ts
- 数据集类型定义packages/service/core/dataset/read.ts
- 文件读取核心逻辑packages/service/core/dataset/training/controller.ts
- 训练数据处理packages/service/core/dataset/collection/controller.ts
- 集合管理packages/service/core/dataset/search/controller.ts
- 搜索检索packages/service/worker/readFile/index.ts
- 文件解析Workerpackages/service/common/vectorStore/controller.ts
- 向量存储
前端核心文件
projects/app/src/pageComponents/dataset/detail/Import/
- 导入界面组件projects/app/src/web/core/dataset/
- 数据集相关前端逻辑
数据库Schema
packages/service/core/dataset/schema.ts
- 数据集Schemapackages/service/core/dataset/collection/schema.ts
- 集合Schemapackages/service/core/dataset/data/schema.ts
- 数据块Schema
10. 核心处理流程总结
- 文件上传/输入 → 根据类型选择对应的读取方式
- 内容解析 → Worker进程解析不同格式文件内容
- 文本分块 → 根据训练模式进行文本切分
- 向量化 → 生成文本向量并存储到向量数据库
- 索引建立 → 建立全文搜索索引
- 存储 → 保存到MongoDB数据库
- 检索 → 支持向量搜索、全文搜索、混合搜索
这套系统支持从简单的文本输入到复杂的多模态文档处理,提供了完整的知识库构建和检索能力。