FastGPT源码解析 Agent知识库文本资料处理详解和代码分析
FastGPT知识库文本处理完整分析
1. 支持的文本输入类型
FastGPT支持多种文本输入类型,定义在 DatasetTypeEnum
和 ImportDataSourceEnum
中:
导出数据支持数据集类型
folder
- 文件夹dataset
- 普通数据集websiteDataset
- 网站数据集externalFile
- 外部文件apiDataset
- API数据集feishu
- 飞书数据集yuque
- 语雀数据集
导入数据源
fileLocal
- 本地文件上传fileLink
- 链接导入fileCustom
- 手动输入文本csvTable
- CSV表格导入externalFile
- 外部文件apiDataset
- API数据集reTraining
- 重新训练
2. 文件格式支持
支持的文件格式(在 readRawContentByFileBuffer
中处理):
// 支持的文件扩展名
const supportedExtensions = ['txt', 'md', 'html', 'pdf', 'docx', 'pptx', 'xlsx', 'csv'
];
3. 文本处理流程
3.1 文件读取阶段
核心文件: packages/service/core/dataset/read.ts
// 根据不同数据源读取原始文本
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
// 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
// 将原始文本转换为训练块
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
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
// 数据集基本信息
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
// 数据集合(文件/文档)
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, // 本地文件IDrawLink: String, // 链接URLexternalFileId: String, // 外部文件IDapiFileId: 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
// 训练数据块
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
// 插入向量数据
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
支持三种搜索模式:
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数据库
- 检索 → 支持向量搜索、全文搜索、混合搜索
这套系统支持从简单的文本输入到复杂的多模态文档处理,提供了完整的知识库构建和检索能力。