FastGPT
labring/FastGPT项目目录
项目简介
FastGPT 是基于 TypeScript 的 AI 应用平台,提供知识库、模型调用和可视化工作流。应用可以作为子流程复用,通过变量、历史和文件输入连接业务处理,并返回回答、交互状态与用量。
如何写进简历
采齐 · 供应商资料预审平台 | 场景化示例
项目描述:基于 FastGPT,面向采购人员按资料清单预审供应商执照与资质附件,汇总缺件、信息不一致及待核验项,由人工决定是否通过。
技术栈:TypeScript、Next.js、MongoDB
主要工作:
- 预审子流程数据交接:基于
FastGPT将执照与资质预审拆为子应用,显式映射字段、所选历史和附件,以独立变量状态运行子流程;回收回答、交互状态与用量,汇总缺件及待核验项。 - 文件身份与附件上下文:以对象 key 区分供应商文件身份和临时访问链接,按子任务派生附件上下文并去重、限量;将预审项关联回原附件,减少历史材料混入本次预审。
- 资质条款混合检索:通过加权
RRF融合向量与全文候选,分别控制候选池、重排权重和引用Token预算,兼顾证书编号精确检索与口语化资质要求的匹配。
面试题与回答
如何说明 Agent 工作流各节点的输入、输出和数据流?
展开收起
核心回答
我会以“父工作流调用一个子应用”为例,讲清父节点选取输入、子应用创建运行状态、内部节点沿边执行、结果再回到父流程这条链。
FastGPT的应用调用节点把子应用当作一个可组合的执行单元,传递的不只是问题字符串,还包括所选历史、文件、变量和交互恢复信息;回传的也不只是回答文本,还有历史、用量和交互状态。例如父流程已取得用户问题和附件,需要调用一个已有分析子应用:父节点把问题接到
userChatInput,把附件接到fileUrlList,再映射子应用需要的变量。子应用内部完成解析与分析后,父流程继续引用它的回答或历史输出。具体流程应以各节点的字段交接说明,不能只列“解析、分析、回答”三个名称。1. 父节点选哪些数据传进去?
dispatchRunAppNode()将节点参数分成问题、历史配置、文件列表、流式开关以及其余子应用变量。- 问题:普通调用根据
userChatInput和选定文件构造子查询;交互恢复则沿用当前查询,并传入子流程恢复信息。 - 历史:
getHistories()根据history选取上下文。传数组表示明确引用这些历史,数字表示按窗口选择,压缩检查点另有保留规则;没有配置时不会直接把父流程全部历史传入。 - 文件:显式
fileUrlList先转换为运行时文件;未指定时兼容使用当前查询里的文件。随后派生子文件上下文,对当前输入、文件变量和历史文件做去重与数量筛选。子应用拿到的是筛选后的查询和历史,不是父流程所有附件的无条件集合。
因此,文件 URL、持久化文件元数据和文件正文要分开:传入 URL 代表子流程可以继续引用该文件,真正解析正文仍由相应节点完成。
2. 子应用怎样变成可执行的图?
节点先加载目标应用、所选版本及其资源上下文,再读取该版本的
nodes、edges、chatConfig。存储节点转换成运行时节点,入口根据普通启动或交互恢复选择;普通边初始化为waiting,恢复时可使用保存的边状态和节点输出。边决定调度关系,节点输入中的变量引用决定实际读取哪些值。子流程随后创建独立的
WorkflowVariableState,按自己的变量配置初始化输入,并加入当前用户、会话、历史和时间等运行时信息。传入父variableState的一个用途,是让子流程通过运行时文件 URL 找回原始文件元数据;它并不表示父子所有变量共用一个可任意覆盖的字典。准备完成后,runWorkflow()接收运行时图、筛选后的查询与历史,以及子变量状态执行。父子调用的实际数据映射。3. 子流程结束后,哪些结果回到父流程?
包装节点从
assistantResponses提取文本,放入data.answerText;data.history则由筛选后的历史、本次用户输入和子流程回答组成。交互恢复时不重复添加同一条用户输入。后续节点引用这些输出,不需要读取子流程所有内部节点状态。运行统计走另一条交接:汇总
flowUsages的点数,通过usagePush记入父节点,并从子流程运行摘要合并输入/输出 Token、引用集合和子响应数量。runTimes、反馈与记忆更新也分别返回,不能把界面显示的回答文字当成完整运行结果。如果子流程停在交互节点,返回的
workflowInteractiveResponse会包装成childrenInteractive,下一次调用再取出childrenResponse恢复执行。关闭子应用流式输出只影响对外流式内容,子工作流仍会运行,回答文本仍可作为节点数据返回。输出、用量与交互包装。4. 版本、资源和异常怎样影响这条数据流?
loadChildWorkflowWithResource()先取得目标应用,再取得工作流版本,并为子版本创建资源上下文。命中资源快照也会实时读取应用实体;未命中时按运行人成员身份校验读取权限。指定的有效版本 ID 若能匹配目标应用,就读取该版本;无有效匹配时回到正式版本读取逻辑,优先正式版本指针,再取最新发布版本,历史应用另有兼容。因此不能把“配置过版本 ID”直接说成“任何情况下都严格锁定这一版本”。子应用资源与版本加载、版本选择。空输入或缺少目标应用 ID 会直接返回节点错误;应用加载、变量初始化和子流程执行等异常由该节点的异常分支转换成错误结果,而不是正常回答。排查时沿四个位置检查就能缩小范围:父节点实际映射的字段、筛选后交给子流程的输入、实际读取的版本与资源,以及回传的是普通结果还是交互/错误状态。
这种封装让同一子应用可以被多个流程复用,但也增加了一层输入映射和结果包装。接口应明确哪些值传入、哪些值回传;需要父流程继续使用的数据,应通过显式输出交接,不能依赖子应用内部状态自动回写。
参考资料
- 国内:FastGPT:工作流与插件:依据节点输入可引用全局变量或前序输出、连线状态控制执行的说明,组织父节点输入与子图调度的解释;子应用具体映射按固定源码展开。
- 国内:JavaGuide:Workflow、Graph 和 Loop:采用节点读取和更新数据、边决定执行路径的划分,解释数据交接与控制流的区别。
- 国内:zero2Agent:并行执行 Fan-out / Fan-in:采用分支结果需要明确汇总规则的解释,支撑原通用答案中并行更新不能默认安全覆盖的说明。
- 国内:WeThinkIn:Agent 设计模式与工作流编排:采用状态契约、执行节点和运行依赖分别管理的思路,解释子变量状态与真实工具执行的职责。
- 国外:LangChain:Graph API overview:依据节点局部更新、状态 Schema 与 reducer 的约定,保留通用答案中的状态合并解释;FastGPT 的运行时实现按自身源码说明。
- 国外:LangChain:Streaming:依据完整状态、局部更新和自定义事件的区别,说明通用答案中流式内容为何不等于完整状态或最终结果。
- 问题:普通调用根据
AI 工作流有哪些与节点、状态和恢复机制相关的安全风险?
展开收起
核心回答
FastGPT的子应用调用需要同时控制子应用能使用哪些资源和这次能看到哪些文件。父流程能运行,不表示子应用可以读取父流程所有附件;一个 URL 能被解析,也不表示它就是已经授权的内部文件。该版本通过版本资源上下文和派生文件上下文分别处理这两件事。子应用会继承父应用的全部权限吗?
loadChildWorkflowWithResource()先加载子应用及实际取得的版本,再根据该版本的资源清单创建独立resourceContext。资源加载也有两条路径:命中版本快照清单的应用,按数据库实时存在、未删除及团队条件读取;未命中清单的动态资源,则按运行人的读权限检查,并限制团队范围。应用资源加载、子应用资源上下文。这是一种版本资源授权与动态访问分开的设计,不能描述成“所有资源每次都按最终聊天用户的 ACL 重新验证”。如果业务要求权限撤销立刻影响已发布流程,应进一步核对发布授权、资源快照和当前执行身份之间的产品规则。
怎样防止父流程附件全部进入子流程?
在根文件上下文已经准备好的执行路径中,
runWithDerivedWorkflowFileContext()从本次问题、显式文件变量和所选历史挑选文件,按稳定身份去重并限制数量;当前输入优先于历史附件,再由父上下文derive()创建子文件上下文。从子文件上下文取得未被选入的文件引用会被拒绝;另行输入的 URL 仍可能走外链下载器,不代表所有网络读取都受这份名单控制。文件选择与隔离、未登记 URL 的外链路径。内部文件的可信身份来自对象 key。根入口先校验 key 所属的来源、用户和会话范围,再生成模型可用链接;子流程只能继承父上下文已登记的私有文件引用,不能通过陌生 key 或伪造 URL 获得对象访问能力。签名 URL 是访问地址,文件身份和权限则保留在服务端引用中。根入口登记、子文件准入。
交互恢复和外链读取还能怎样追问?
子应用交互恢复会根据保存的交互信息重建运行节点、连线,并再次建立子变量及文件上下文。这不自动保证业务写操作只执行一次;如果子流程连接创建工单等工具,仍应由工具服务维护动作幂等和资源状态检查。恢复与上下文重建。
外链下载走 HTTP(S) 检查、超时和流式大小限制,并使用统一安全请求器:逐跳检查重定向,直连时复核 DNS 解析地址并将连接固定到已验证 IP。域名白名单是另一层可配置策略,留空会放行该层检查,不能据此忽略下游已有防护。外链下载、重定向处理、直连地址固定。
这些能力仍有部署边界:生产环境对回环、未指定地址和云元数据目标有基础阻断,其他私网限制受
CHECK_INTERNAL_IP控制;开发和代理路径还需分别核验,代理最终解析不能由本机的地址固定保证。因此应按实际环境测试外链和恢复场景,不能声称所有部署都已安全验收。网络策略、代理分支。混合检索权重如何配置?
展开收起
核心回答
FastGPT的默认文本检索流程在选择mixedRecall后,同时召回向量结果与全文结果,通过embeddingWeight控制加权RRF:向量一路用 $w$,全文一路用 $1-w$。它融合的是名次贡献,不是把原始向量分数与全文分数按比例相加。调参时需要把两种权重分开:
embeddingWeight控制向量与全文的融合;rerankWeight控制原召回排名与模型重排排名的融合。最低相关度similarity是否生效,还取决于搜索模式和重排是否成功;最终引用量由limit的Token预算控制。双路召回与融合
countRecallLimit()在混合模式中将向量和全文候选上限分别设为80、60;多查询结果先在各自通道内合并,再分别截到该上限。这些是当前实现的候选配置,不是最终引用条数。候选数量、通道内合并。服务函数中
embeddingWeight缺省为0.5。两路都有结果且参与融合时,datasetSearchResultConcat()按数据块标识合并,累加:$$ S(d)=\frac{w}{60+r_{\text{vector}}(d)}+\frac{1-w}{60+r_{\text{fulltext}}(d)} $$
其中,$r$ 表示该通道中从 1 开始的名次,只计入该数据块实际出现的通道。这里的
60是源码中的平滑常数;若仅剩一路有效列表,函数直接返回该列表。权重传入、RRF 实现。重排、阈值和引用上限
重排需要开启
usingReRank,并有有效查询和重排模型。文本候选去重后交给模型;rerankWeight缺省为0.5,模型重排结果与原融合结果再做一次加权RRF。设为1时采用模型重排列表;重排失败则回退到原召回列表,并返回usingReRank=false。重排启用条件、重排融合与失败回退。最终先做内容去重,再处理阈值和引用预算。有效重排时,带
reRank分数的结果按该分数与similarity比较,缺少这类分数的结果保留;未有效重排时,只有纯向量模式按向量分数过滤,混合模式不启用这项最低相关度过滤。因此,混合搜索里只提高similarity,未必会减少结果,需要同时检查实际返回的usingReRank和usingSimilarityFilter。过滤条件。随后按
limit控制引用的Token预算。该实现按块累计并保留跨过预算的当前块,因此不是严格逐Token截断,也不能用增大limit代替扩大召回候选池。最终处理顺序、引用预算处理。用什么问题验证
例如在供应商准入资料库中,分别准备“
ISO 9001证书需要提交哪些材料”和“质量管理资质怎么准备”这类问题。先固定重排、问题扩展与引用预算,只调整embeddingWeight,检查对应资料条款能否进入前列;再独立调整rerankWeight,观察精确标准名称有没有被相近资质说明挤掉。如果文档已在候选池中但融合后靠后,才针对权重比较;若候选池没有对应文档,则回查索引、全文分词、查询与集合过滤。上述答法针对文本混合检索,图片描述和图片向量在该版本中还有独立融合分支。