FastGPT 源码:controller.ts 主要定义

news/2025/3/6 17:41:19/

文章目录

    • FastGPT 源码:controller.ts 主要定义
      • 1. 主要函数和参数定义
      • 2. 参数初始化
      • 3. 内部工具函数
      • 4. 多查询召回实现
      • 5. 主流程执行

FastGPT 源码:controller.ts 主要定义

controller.ts 中的核心搜索实现。

1. 主要函数和参数定义

type SearchDatasetDataProps = {teamId: string;        // 团队IDmodel: string;         // 向量模型similarity?: number;   // 最小相似度阈值limit: number;         // 最大Token限制datasetIds: string[];  // 要搜索的数据集IDssearchMode?: `${DatasetSearchModeEnum}`; // 搜索模式(embedding/全文/混合)usingReRank?: boolean; // 是否使用重排序reRankQuery: string;   // 重排序查询queries: string[];     // 搜索查询列表
};

2. 参数初始化

export async function searchDatasetData(props: SearchDatasetDataProps) {let {teamId,reRankQuery,queries,model,similarity = 0,limit: maxTokens,searchMode = DatasetSearchModeEnum.embedding,  // 默认使用向量搜索usingReRank = false,datasetIds = []} = props;// 初始化搜索模式searchMode = DatasetSearchModeMap[searchMode] ? searchMode : DatasetSearchModeEnum.embedding;// 检查是否可以使用重排序usingReRank = usingReRank && global.reRankModels.length > 0;// token数量限制,最小50if (maxTokens < 50) {maxTokens = 1500;}
}

3. 内部工具函数

// 计算不同搜索模式下的召回限制
const countRecallLimit = () => {if (searchMode === DatasetSearchModeEnum.embedding) {return { embeddingLimit: 150, fullTextLimit: 0 };  // 纯向量搜索}if (searchMode === DatasetSearchModeEnum.fullTextRecall) {return { embeddingLimit: 0, fullTextLimit: 150 };  // 纯全文搜索}return { embeddingLimit: 100, fullTextLimit: 80 };   // 混合搜索
};// 向量检索实现
const embeddingRecall = async ({ query, limit }) => {// 1. 获取查询文本的向量const { vectors, tokens } = await getVectorsByText({...});// 2. 从向量库检索const { results } = await recallFromVectorStore({...});// 3. 获取完整的QA数据const dataList = await MongoDatasetData.find({...});// 4. 格式化结果return { embeddingRecallResults: formatResult, tokens };
};// 全文检索实现
const fullTextRecall = async ({ query, limit }) => {// 使用MongoDB的全文索引搜索let searchResults = await Promise.all(datasetIds.map(id => MongoDatasetData.find({$text: { $search: jiebaSplit({ text: query }) }})));return { fullTextRecallResults, tokenLen: 0 };
};// 重排序实现
const reRankSearchResult = async ({ data, query }) => {// 调用重排序模型const results = await reRankRecall({query,documents: data.map(item => ({id: item.id,text: `${item.q}\n${item.a}`}))});// 合并重排序分数return mergeResult;
};

4. 多查询召回实现

const multiQueryRecall = async ({ embeddingLimit, fullTextLimit }) => {// 并行执行每个query的向量和全文检索await Promise.all(queries.map(async (query) => {const [{ tokens, embeddingRecallResults }, { fullTextRecallResults }] = await Promise.all([embeddingRecall({ query, limit: embeddingLimit }),fullTextRecall({ query, limit: fullTextLimit })]);// 收集结果...}));// 使用RRF合并多个查询的结果const rrfEmbRecall = datasetSearchResultConcat(embeddingRecallResList.map(list => ({ k: 60, list })));const rrfFTRecall = datasetSearchResultConcat(fullTextRecallResList.map(list => ({ k: 60, list })));
};

5. 主流程执行

/* main step */
// 1. 获取召回限制
const { embeddingLimit, fullTextLimit } = countRecallLimit();// 2. 执行多查询召回
const { embeddingRecallResults, fullTextRecallResults } = await multiQueryRecall({...});// 3. 执行重排序
const reRankResults = await (async () => {if (!usingReRank) return [];// 合并向量和全文结果const concatRecallResults = embeddingRecallResults.concat(fullTextRecallResults.filter(item => !set.has(item.id)));// 去重并重排序return reRankSearchResult({...});
})();// 4. 最终RRF合并
const rrfConcatResults = datasetSearchResultConcat([{ k: 60, list: embeddingRecallResults },{ k: 60, list: fullTextRecallResults },{ k: 58, list: reRankResults }
]);// 5. 结果过滤
// - 去重
// - 相似度过滤
// - Token限制过滤
const filterSameDataResults = rrfConcatResults.filter(...);
const scoreFilter = filterByScore(filterSameDataResults);
const finalResults = filterResultsByMaxTokens(scoreFilter, maxTokens);

实现完整覆盖如下流程:

  1. 多种搜索模式(向量/全文/混合)
  2. 多查询并行检索
  3. 查询结果RRF合并
  4. 重排序优化
  5. 结果过滤和限制

整个过程保证了搜索的全面性(多种召回方式)和准确性(重排序和过滤)。


http://www.ppmy.cn/news/1577125.html

相关文章

【Nest】中间件

一、中间件的创建与使用 1. 类中间件 通过实现 NestMiddleware 接口创建类中间件&#xff0c;需定义 use 方法&#xff1a; import { Injectable, NestMiddleware } from nestjs/common; import { Request, Response, NextFunction } from express;Injectable() export clas…

QDBus:Qt对DBus的封装支持

QDBus&#xff1a;Qt对DBus的封装支持 引言 在Qt应用程序开发中&#xff0c;进程间通信&#xff08;IPC&#xff09;是实现模块化、服务化和分布式架构的关键技术。QDBus是Qt框架对DBus&#xff08;Desktop Bus&#xff09;协议的封装&#xff0c;为开发者提供了一种高效、便捷…

The Rust Programming Language 学习 (二)

通用编程概念 变量和可变性 默认情况下变量是不可变的&#xff08;immutable&#xff09;,不过你也可以选择让变量是可变的&#xff08;mutable&#xff09;. 变量的遮蔽 你可以声明和前面变量具有相同名称的新变量,说这个是第一个变量被第二个变量遮蔽&#xff08;shadow&…

Java TCP 通信:实现简单的 Echo 服务器与客户端

TCP&#xff08;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的传输层协议。与 UDP 不同&#xff0c;TCP 保证了数据的顺序、可靠性和完整性&#xff0c;适用于需要可靠传输的应用场景&#xff0c;如文件传输、网页浏览等。本文将基于 Java 实现一个简单的…

【GB28181】 SIP信令服务器

概述 本文仅总结关于GB28181下的注册、心跳维持等与推流拉流相配合的SIP信令&#xff0c;主要基于eXosip库实现&#xff1b;其中搭建信令服务器参考了开源代码以及B站up北小菜&#xff0c;文章结尾有链接 主要逻辑梳理 配置自身SIP服务器&#xff0c;同时配置自己想要访问的SI…

6.从零开始学会Vue--{{路由}}

1.路由简介 Vue 作为一个渐进式框架&#xff0c;在使用 vue-router 之后可以是程序变为一个 SPA 的单页面应用, 它的本质是使用了 js 的 History API&#xff1a; Vue Router 利用浏览器的 History API&#xff08;如 pushState 和 replaceState&#xff09;&#xff0c;实现…

自学微信小程序的第八天

DAY8 1、使用动画API即可完成动画效果的制作,先通过wx.createAnimation()方法获取Animation实例,然后调用Animation实例的方法实现动画效果。 表40:wx.createAnimation()方法的常用选项 选项 类型 说明 duration number 动画持续时间,单位为毫秒,默认值为400毫秒 timing…

【计算机视觉】手势识别

手势识别是计算机视觉领域中的重要方向&#xff0c;通过对摄像机采集的手部相关的图像序列进行分析处理&#xff0c;进而识别其中的手势&#xff0c;手势被识别后用户就可以通过手势来控制设备或者与设备交互。完整的手势识别一般有手的检测和姿态估计、手部跟踪和手势识别等。…