这是我第一次接触ai的项目,所以可能会有很多理解错误的点,大部分只是自己对ai的认识,所以如果有错误的地方,可以直接指出。
根据我对xfg这个项目的学习,首先是先通过API功能测试,使用 Spring AI、LangChain4J、Google ADK 框架对接 AI 服务,完成功能验证。先感受一下不同框架下的ai测试效果。

这里分了不同的包,进行不同场景下的测试。
agent包中,我们进行了Agent智能体编排,主要进行agent流程,执行逻辑的测试。
model包中,我们使用AI模型底层API层,通过调用大模型接口,是SDK原生能力的测试。
tool包下的mcp包中,进行能力的扩展,是对Agent调用工具,函数调用能力的测试。
感受完在不同条件下的ai测试后,我们正式开始搭建一个可以动态配置的Agent智能体。
我们定义使用工程 YML 文件方式,配置的通用的智能体配置表。允许用户在使用脚手架创建完成智能体后工程后,通过 YML 配置出自己需要的智能体,在结合业务场景做对应的衔接开发。

AiAgentAutoConfig类来加载YML配置。

public class AiAgentConfigTableVO { / * 应用名称 */ private String appName; / * 智能体配置 */ private Agent agent; / * 智能体模块 */ private Module module; @Data public static class Agent { / * 智能体ID */ private String agentId; / * 智能体名称 */ private String agentName; / * 智能体描述 */ private String agentDesc; } @Data public static class Module { private AiApi aiApi; private ChatModel chatModel; private List
agents; private List
agentWorkflows; private Runner runner; @Data public static class AiApi { private String baseUrl; private String apiKey; private String completionsPath = "/v1/chat/completions"; private String embeddingsPath = "/v1/embeddings"; } @Data public static class ChatModel { private String model; private List
toolMcpList; private List
toolSkillsList; @Data public static class ToolMcp { private SSEServerParameters sse; private StdioServerParameters stdio; private LocalParameters local; @Data public static class SSEServerParameters { private String name; private String baseUri; private String sseEndpoint; private Integer requestTimeout = 3000; } @Data public static class StdioServerParameters { private String name; private Integer requestTimeout = 3000; private ServerParameters serverParameters; @Data public static class ServerParameters { private String command; private List
args; private Map
env; } } @Data public static class LocalParameters{ private String name; } } @Data public static class ToolSkills{ / * 类型;directory(用户配置的,映射进来的)、resource(放到工程下的) */ private String type="directory"; / * 路径; */ private String path; } } @Data public static class Agent { private String name; private String instruction; private String description; private String outputKey; } @Data public static class AgentWorkflow{ / * 类型;loop、parallel、sequential */ private String type; private String name; private List
subAgents; private String description; private Integer maxIterations = 3; } @Data public static class Runner{ private String agentName; private List
pluginNameList; } } }
这两个类为配置表对象类,AiAgentConfigTableVO用来接收,存储,传递你在配置文件里所写的所有AI智能体配置。AiAgentAutoConfigProperties把 application.yml 配置文件里 ai.agent.config 开头的所有配置,自动映射成 Java 对象,是整个 AI Agent 自动装配体系的配置入口顶层类。
我们来梳理一下流程:
1. Spring Boot 启动初始化阶段
- 扫描并加载配置类
AiAgentAutoConfig被@Configuration标记,Spring 会在启动时扫描到它。- 同时
@EnableConfigurationProperties(AiAgentAutoConfigProperties.class)生效,告诉 Spring:把AiAgentAutoConfigProperties当成一个配置属性类,进行绑定。
- 绑定配置属性
- Spring 会读取
application.yml/application.properties中所有ai.agent.config.*开头的配置。 - 把配置值绑定到
AiAgentAutoConfigProperties的字段上:ai.agent.config.enabled→private boolean enabled(默认值 false)ai.agent.config.tables→private Maptables
- 绑定完成后,
AiAgentAutoConfigProperties会被注册为一个 Bean。
- Spring 会读取
- 依赖注入
- Spring 会把
AiAgentAutoConfigProperties和IArmoryService这两个 Bean,注入到AiAgentAutoConfig中被@Resource标记的字段里。 - 此时
AiAgentAutoConfig实例已经创建完成,但它的业务方法还没执行。
- Spring 会把
2. 应用就绪事件触发阶段(ApplicationReadyEvent)
Spring Boot 启动完成后,会发布 ApplicationReadyEvent 事件。因为 AiAgentAutoConfig 实现了 ApplicationListener
,所以它的 onApplicationEvent 方法会被触发。
事件触发后,开始装配agent节点,在装配agent所有节点中,通过引用xfg的扳手工程中的规则树(组合模式)来进行流转实现。
之后,定义了单一职责的 IArmoryService 装配服务接口,并通过工厂管理节点衔接服务,以及定义上下文对象。这个上下文对象,会在各个节点间记录数据并流转使用。
public void acceptArmoryAgents(List
tables) throws Exception { for (AiAgentConfigTableVO table : tables) { StrategyHandler
handler = defaultArmoryFactory.armoryStrategyHandler(); handler.apply(ArmoryCommandEntity.builder() .aiAgentConfigTableVO(table).build(), new DefaultArmoryFactory.DynamicContext()); } }
接下来,我们介绍一下xfg扳手工程项目中的一个通用组件--规则树。
我们在做产品项目时,肯定会遇到某些场景,需要经过很多流程,这些流程牵扯着不同的业务属性,如:授信,账户,风控,配置,营销,推荐,之后又要到,不同的产品线上,如A产品功能,B产品功能。
那么,规则树的编排就很适合这样的场景使用。它的设计可以像组装乐高积木,改一个大楼一样,有非常多的延展,来满足我们的场景诉求。

- 左侧,是复杂的业务流程节点编排,可以通过【路由】,拿到 get 方法中的节点判断和处理,走到下一个节点。与责任链相比,单链路执行适合固定的流程,如一些规则过滤。而规则树则适合编排复杂业务流程。
- 右侧,是流程过滤提供的方法,包括了;多线程异步数据加载、业务受理、get负责路由执行时做的一些判断。而受理前、受理后、受理后异常,则在流程中进行穿插处理。
1.StrategyHandler 策略处理接口
StrategyHandler 是一个泛型接口,定义了策略处理的核心方法。它包含一个默认实现,当没有匹配的策略时使用默认处理。该接口的泛型参数包括请求参数类型(T)、动态上下文类型(D)和返回结果类型(R)。
/ * @description 受理策略处理 * T 入参类型 * D 上下文参数 * R 返参类型 */ public interface StrategyHandler
{ StrategyHandler DEFAULT = (T, D) -> null; R apply(T requestParameter, D dynamicContext) throws Exception; }
2.StrategyMapper 策略映射器
StrategyMapper 是一个泛型接口,用于根据请求参数和动态上下文获取待执行的策略处理器。它定义了一个方法,根据传入的参数返回对应的策略处理器。
/ * @description 策略映射器 * T 入参类型 * D 上下文参数 * R 返参类型 */ public interface StrategyMapper
3.AbstractStrategyRouter 策略路由抽象类
AbstractStrategyRouter 是一个抽象类,结合了策略处理器和策略映射器的功能,提供了灵活的策略路由机制。它实现了 StrategyMapper 和 StrategyHandler 接口,兼具映射和执行能力。该类还提供了一个默认策略处理器,当没有匹配的策略时使用默认处理。
/ * @author Fuzhengwei bugstack.cn @小傅哥 * @description 策略路由抽象类 * @create 2024-12-14 13:25 */ public abstract class AbstractStrategyRouter
implements StrategyMapper
, StrategyHandler
}
/ * @author Fuzhengwei bugstack.cn @小傅哥 * @description 异步资源加载策略 * @create 2024-12-21 08:48 */ public abstract class AbstractMultiThreadStrategyRouter
implements StrategyMapper
, StrategyHandler
@Override public R apply(T requestParameter, D dynamicContext) throws Exception catch (Exception e) { // 后置处理(异常) applyAfterException(requestParameter, dynamicContext, e); throw e; } } / * 异步加载数据 */ protected abstract void multiThread(T requestParameter, D dynamicContext) throws ExecutionException, InterruptedException, TimeoutException; / * 业务流程受理 */ protected abstract R doApply(T requestParameter, D dynamicContext) throws Exception; protected R applyBefore(T requestParameter, D dynamicContext) { return proceed(requestParameter, dynamicContext); } protected void applyAfter(T requestParameter, D dynamicContext, R r) { } protected void applyAfterException(T requestParameter, D dynamicContext, Exception e) { } }
在项目中我们使用在策略路由抽象类上进行优化后的AbstractMultiThreadStrategyRouter。
xfg的规则树模型设计的核心组件就是这些,我们只需要在项目中再加入一个默认工厂类(上文已提及),用它来负责创建和管理策略处理器,提供策略模式的统一入口。它维护策略执行的上下文信息,支持数据在不同策略节点间传递。
public class DefaultArmoryFactory { @Resource private RootNode rootNode; @Resource private ApplicationContext applicationContext; public StrategyHandler
armoryStrategyHandler(){ return rootNode; } public AiAgentRegisterVO getAiAgentRegisterVO(String agentId) / * 定义一个上下文对象,用于各个节点串联的时候,写入数据和使用数据 */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public static class DynamicContext public
T getValue(String key) public List
queryAgentList(List
agentNames) List
agents=new ArrayList<>(); for (String agentName : agentNames) } return agents; } } }
然后在提供一个规则树抽象支持类,它继承了AbstractMultiThreadStrategyRouter,为具体业务实现提供了支持。
public abstract class AbstractArmorySupport extends AbstractMultiThreadStrategyRouter
{ @Resource protected ApplicationContext applicationContext; @Override protected void multiThread(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws ExecutionException, InterruptedException, TimeoutException { } / * 通用的Bean注册方法 * * @param beanName Bean名称 * @param beanClass Bean类型 * @param
Bean类型 */ protected synchronized
void registerBean(String beanName, Class
beanClass, T beanInstance) // 注册新的Bean beanFactory.registerBeanDefinition(beanName, beanDefinition); log.info("成功注册Bean: {}", beanName); } protected
T getBean(String beanName) }
通过规则树模型的设计,为之后的各个节点装配,流转,节点之间的通信和Bean对象的注册,获取Bean对象等等,提供了极大的便利。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/271107.html