资讯动态

FIT 框架 FEL 工具调用机制实战:从 Pattern 委托到插件化工具编排

发布时间:2026/10/14 2:26:03 来源:尧图企业网站定制
人工智能大模型AI 应用后端AI AgentRAG流程编排微服务【免费下载链接】fit-frameworkFIT: 企业级AI开发框架提供多语言函数引擎FIT、流式编排引擎WaterFlow及Java生态的LangChain替代方案FEL。原生/Spring双模运行支持插件热插拔与智能聚散部署无缝统一大模型与业务系统。项目地址https://gitcode.com/ModelEngine/fit-framework点击查看免费下载导读本文聚焦 FIT 框架中 FELFramework for Engineering LLM的**工具调用Tool Calling**能力。大模型受限于训练知识截止时间无法获取实时数据、执行精确计算或访问外部系统而 FEL 通过两套互补机制解决这一短板一是基于Pattern委托单元的代理模式让开发者以最小代码把任意业务逻辑如天气查询、计算、数据库访问接入 AI 流程二是基于 FIT 插件体系的工具插件化方案通过ToolMethod注解、编译期tools.json清单生成和运行期插件热插拔实现工具的自动发现、大模型自主选择与统一执行。读完本文你将掌握 FEL 中两种工具接入方式的工作原理、核心源码结构以及可运行的完整示例。为什么大模型需要工具调用大模型在语言生成与理解上能力极强但在以下场景中必须借助外部工具才能给出可靠答案获取最新信息模型训练数据存在知识截止时间无法提供实时数据通过调用浏览器或 API可查询最新事件与动态数据。精确计算模型虽可做简单数学推理却不擅长精确或复杂的数值运算调用计算工具更可靠。数据库/知识库查询通过工具连接外部数据库、知识库或搜索引擎查询结构化数据或更准确的答案。多步逻辑推理部分任务涉及多步骤推理、算法应用或代码执行可调用专门程序完成。FEL-Flow 提供两种接入方式见 fel-flow 模块 README 中的核心特点说明委托机制Pattern在 AI 流程中插入一个委托节点把输入数据交给外部函数处理后回流到流程中预定义工具调用的流程编排将工具封装为 FIT 插件由大模型在运行时自主选择工具通过流程编排轻松调用多个工具完成复杂任务如多智能体互通。委托机制用 Pattern 把任意逻辑接入 AI 流程委托机制本质上是一种代理模式大模型或流程本身根据任务内容与输入信息自动识别需要调用的工具并将任务分配出去。其工作流程分三步输入解析和识别任务模型分析用户输入上下文判断是否需要外部工具协助如检测到时间敏感信息、复杂计算等。工具选择和调用模型通过预定义策略或规则选择合适的工具。常见工具包括 API 工具浏览器、数据库查询接口、天气预报 API、计算工具计算器或数据处理工具以及嵌入模型文本检索或搜索工具。执行任务和结果返回工具完成任务并返回结果模型将结果整合进原始任务并反馈给用户。Pattern 与 SimplePattern委托单元的源码剖析Pattern是 FEL 定义的委托单元接口I表示输入数据类型O表示输出数据类型。其定义位于 Pattern.javapublic interface PatternI, O { O invoke(I input); }SimplePattern是该接口的简单实现位于 SimplePattern.java。它通过运行时传入的FunctionI, O即文档中的func实现动态行为委托——不直接定义具体逻辑而是接受外部传入的函数逻辑因此非常灵活public class SimplePatternI, O implements PatternI, O { private final FunctionI, O func; public SimplePattern(FunctionI, O func) { this.func Validation.notNull(func, The action function cannot be null.); } Override public O invoke(I input) { Validation.notNull(input, The input data cannot be null.); return this.func.apply(input); } }从源码可见两个关键约束构造函数与invoke方法均通过Validation.notNull做了空值校验分别保证委托函数和输入数据不为空。这是 FEL 对Pattern输入输出契约的强制要求。delegate 操作把 Pattern 编排进 AI 流程SimplePattern要真正参与 AI 应用需要通过 FEL-Flow 的delegate操作挂载到流程上。AiStart.java 中的实现说明了委托节点的语义/** * 将数据委托给 {link Pattern}{code }{link O}{code , }{link R}{code } * 处理然后自身放弃处理数据。处理后的数据会发送回该节点作为该节点的处理结果。 */ public R AiStateR, D, O, RF, F delegate(PatternO, R pattern) { Validation.notNull(pattern, Pattern operator cannot be null.); return this.delegate(new SimpleFlowPattern(pattern)); }即delegate节点接收上游数据交给Pattern处理后把结果发送回流程继续流转。除了接收Patterndelegate还有多个重载委托给Operators.ProcessMap在独立线程池执行适合 IO 密集型任务、委托给子流程AiProcessFlow甚至可以从子流程的指定节点开始处理delegate(AiProcessFlow, nodeId)。这为预定义工具调用流程提供了基础。对应的单元测试见 PatternTest.java其中shouldOkWhenDelegateSimplePattern验证了prompt → delegate(pattern) → close → converse → offer的完整链路SimplePatternPrompt, String pattern new SimplePattern(prompt - { String inputContextValue AiFlowSession.get() .map(target - ObjectUtils.Stringcast(target.getState(key))) .orElse(StringUtils.EMPTY); return prompt.text() inputContextValue; }); ConverseLatchString offer AiFlows.Tipcreate() .prompt(Prompts.human({{0}})) .delegate(pattern) .close() .converse(session) .offer(Tip.fromArray(human msg.)); String result offer.await(); assertThat(result).isEqualTo(human msg. value);测试还展示了Pattern可以通过AiFlowSession访问流程会话上下文session.getState(key)说明委托单元并非孤立的黑盒而是可以与Conversation绑定数据交互。委托示例天气查询以下代码创建一个简单的委托Pattern用户输入位置信息将调用委托给WeatherTool获取天气输出该位置的天气信息WeatherTool weatherTool new WeatherTool(); SimplePatternPrompt, String pattern new SimplePattern(prompt - { String userInput prompt.text(); String location getLocation(userInput); if (location ! null !location.isEmpty()) { return weatherTool.getWeather(location); } else { return Sorry, I couldnt identify the location.; } }); // 模型会话流程定义 AiFlows.Tipcreate() .prompt(Prompts.human({{0}})) // 以用户输入作为prompt .delegate(pattern) // 使用定义好的pattern进行委托调用 .close() .converse(session) // 开始对话 .offer(Tip.fromArray(Can you tell me the weather in Paris?)) // 模拟输入 .await(); // 等待结果输出流程节点依次为prompt将用户输入包装为提示词→delegate(pattern)调用天气工具→close终止→converse建立会话→offer注入输入→await阻塞等待结果。工具插件基于 FIT 插件化的工具发现与执行当工具数量增多、需要被大模型自主调度时委托机制就显得不够体系化。FEL-Flow 通过FIT 插件将工具封装为插件利用 FIT 插件化的优势支持工具的热插拔并监听所有插件的加载和卸载。整个链路分为插件扫描与插件选择和执行两个阶段。阶段一插件扫描编译期生成 tools.jsonFEL-Flow 提供一个 Maven 插件tool-maven-plugin源码位于 tool-maven-plugin 模块在编译期间扫描所有 Tool class 文件。其工作方式为开发者在工具方法上使用注解ToolMethod描述工具包括命名空间、工具名称、描述、方法参数等信息注解定义见 ToolMethod.java。编译期由GroupPluginCompiler见 GroupPluginCompiler.java驱动ByteBuddyGroupParser解析 class 文件中ToolMethod注解生成ToolEntity列表最终输出工具清单文件tools.json默认文件名常量见 ToolSchema.java 中的TOOL_MANIFEST tools.json。ToolMethod注解的核心属性如下属性类型默认值说明namespaceStringCommon工具的命名空间工具名在命名空间内需唯一nameString无必填工具方法名descriptionString空字符串工具方法描述供大模型理解工具用途extraParamsString[]{}工具的额外参数名returnConverterString空字符串输出转换器工具方法extensionsAttribute[]{}工具方法的扩展属性键值对其中Attribute注解见 Attribute.java由key()和value()组成。而方法参数的语义描述参数名、描述、是否必填、默认值、样例值由 FIT 框架的Property注解提供见 Property.java。tools.json的反序列化结构由 ToolJsonEntity.java 定义包含version、definitionGroups定义组和toolGroups工具组每个工具由 ToolEntity.java 表示携带namespace、schema含名称、描述、参数、顺序、返回值、参数扩展等、runnables、extensions和tags。阶段二插件选择和执行运行期应用启动后解析清单入仓库DefaultToolDiscoverer见 DefaultToolDiscoverer.java实现了 FIT 的PluginStartedObserver与PluginStoppingObserver在插件加载/卸载时扫描插件资源中的tools.json将ToolEntity转成ToolInfoEntity注册进ToolRepository加载时调用addTool卸载时调用deleteTool。它同时受tool.max-num配置约束限制单插件可注册的工具数量。工具仓库默认实现SimpleToolRepository见 SimpleToolRepository.java以ConcurrentHashMap缓存工具用ToolInfo.identify(namespace, name)生成的namespace:name唯一标识见 ToolInfo.java并在工具增删时通知ToolChangedObserver观察者。模型选择工具应用把用户请求和可用工具列表toolRepository.listTool(namespace)通过ChatOption.tools(...)传给大模型tools字段定义见 ChatOption.java模型返回要调用的工具。执行工具DefaultToolExecutor见 DefaultToolExecutor.java根据返回的namespace:name从仓库取出工具通过ToolFactoryRepository匹配runnables类型对应的工厂创建Tool实例再调用executeWithJson/executeWithJsonObject执行并返回结果。工具工厂按类型注册DefaultToolFactoryRepository见 DefaultToolFactoryRepository.java例如FitToolFactory负责把Genericable定义的 FIT 函数封装为工具见 FitToolFactory.java。完整可运行示例天气助手 Agent仓库中的 06-agent 示例 完整演示了插件化工具 Agent 自主调度的用法。示例定义一个天气助手将两个 FIT 函数get_current_temperature和get_rain_probability作为助手可调用的工具。步骤 1引入依赖。除fit-starter、fel-core、fel-flow、fel-model-openai-plugin外还需引入工具相关的插件与服务依赖!-- 工具自动发现服务 -- dependency groupIdorg.fitframework/groupId artifactIdfel-tool-discoverer/artifactId version${fel.version}/version /dependency !-- 工具执行服务 -- dependency groupIdorg.fitframework/groupId artifactIdfel-tool-executor/artifactId version${fel.version}/version /dependency !-- Fit 工具工厂 -- dependency groupIdorg.fitframework/groupId artifactIdfel-tool-factory-fit/artifactId version${fel.version}/version /dependency !-- 工具工厂存储 -- dependency groupIdorg.fitframework/groupId artifactIdfel-tool-factory-repository/artifactId version${fel.version}/version /dependency !-- 工具存储 -- dependency groupIdorg.fitframework/groupId artifactIdfel-tool-repository-simple/artifactId version${fel.version}/version /dependency同时在plugins中加入工具编译插件tool-maven-plugin绑定build-toolgoal 于 compile 阶段对应 BuildGroupPluginMojo.java 中的Mojo(name build-tool, defaultPhase LifecyclePhase.COMPILE)。步骤 2配置模型参数application.ymlfel: openai: api-base: ${api-base} api-key: ${your-api-key} example: model: ${model-name}步骤 3定义工具。接口使用Genericable声明可服务化的方法public interface WeatherService { Genericable(modelengine.example.weather.temperature) String getCurrentTemperature(String location, String unit); Genericable(modelengine.example.weather.rain) String getRainProbability(String location); }实现类通过ToolMethod提供工具元数据通过Property描述参数Component public class WeatherServiceImpl implements WeatherService { Override Fitable(default) ToolMethod(namespace example, name get_current_temperature, description 获取指定城市的当前温度) public String getCurrentTemperature(Property(description 城市名称, required true) String location, Property(description 使用的温度单位可选CelsiusFahrenheit, defaultValue Celsius) String unit) { return 26; } Override Fitable(default) ToolMethod(namespace example, name get_rain_probability, description 获取指定城市下雨的概率) public String getRainProbability(Property(description 城市名称, required true) String location) { return 0.06; } }步骤 4使用默认 Agent 调度。AgentExampleController.java 构建了DefaultAgent并把它作为Pattern通过delegate挂进 AI 流程DefaultAgent agent new DefaultAgent(new ChatFlowModel(chatModel, this.chatOption), example, toolExecuteService); this.agentFlow AiFlows.Stringcreate() .map(query - Tip.fromArray(query)) .prompt(Prompts.human({{0}})) .delegate(agent) .close();请求处理时把toolRepository.listTool(example)得到的工具列表绑定进会话模型即可在对话中自主选择工具GetMapping(/chat) public ChatMessage chat(RequestParam(query) String query) { ListToolInfo toolInfos asParent(toolRepository.listTool(example)); return this.agentFlow.converse() .bind(ChatOption.custom(this.chatOption).tools(toolInfos).build()) .offer(query) .await(); }DefaultAgent的内部实现见 DefaultAgent.java与基类 AbstractAgent.java 揭示了 Agent 的循环调度逻辑模型输出若包含工具调用ChatMessage::isToolCall则把toolCalls交给doToolCall执行DefaultAgent通过ToolExecuteService按命名空间执行工具并封装为ToolMessage再把工具结果合并进记忆后跳回检查点CHECK_POINT重新调用模型直到模型输出不含工具调用为止。这正是大模型选择工具 → 应用执行工具 → 结果回填 → 再次调用模型闭环的源码级体现。验证启动应用后访问http://localhost:8080/ai/example/chat?query北京下雨的概率是多少得到{ content: 北京下雨的概率是6%。, toolCalls: [] }可以看到大模型根据工具返回的原始概率数据0.06进行了自然语言回答。总结FEL 的工具调用能力覆盖了两类典型诉求轻量、确定性的工具接入使用SimplePattern把任意Function封装为委托单元通过delegate操作嵌入 AI 流程适合逻辑固定、无需模型决策的调用场景动态、模型驱动的工具编排通过ToolMethod注解 tool-maven-plugin编译期扫描生成tools.json运行期由DefaultToolDiscoverer随插件热插拔注册/注销工具ToolRepository统一管理DefaultAgent与ToolExecuteService完成模型选工具—执行—回填的循环调度适合需要大模型自主决策、多工具协作乃至多智能体互通的复杂场景。两种机制共享同一套Pattern抽象与 FEL-Flow 流程编排底座开发者可根据业务对确定性与智能性的需求灵活选用。赞分享人工智能大模型AI 应用后端AI AgentRAG流程编排微服务【免费下载链接】fit-frameworkFIT: 企业级AI开发框架提供多语言函数引擎FIT、流式编排引擎WaterFlow及Java生态的LangChain替代方案FEL。原生/Spring双模运行支持插件热插拔与智能聚散部署无缝统一大模型与业务系统。项目地址https://gitcode.com/ModelEngine/fit-framework点击查看免费下载相关推荐FIT 框架 FEL 指南检索增强生成RAG模块全解析与 AiFlows 实战编排FIT 框架 FEL 指南检索增强生成RAG模块全解析与 AiFlows 实战编排 本篇技术指南以 FIT 框架下 FELFunction Engine人工智能大模型AI 应用后端AI AgentRAG流程编排微服务HookLib²内存优化技巧4KB页面容纳39个钩子的实现HookLib²内存优化技巧4KB页面容纳39个钩子的实现 HookLib作为一款纯C语言编写的函数拦截库同时支持用户态和内核态操作其卓越的内存优化能力让ET框架UI事件系统实战指南从委托机制到高效交互的深度解析ET框架UI事件系统实战指南从委托机制到高效交互的深度解析 ET框架作为一款优秀的Unity3D客户端和C 服务器框架其事件系统设计巧妙且功能强大特别适合游戏开发后端微服务云原生上一篇5大亮点揭秘这款开源社交平台为何值得关注下一篇Umi-OCR免费离线OCR软件的完整解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑