适配框架时发现工厂注册链上存在一些执行顺序上的错误,于是尝试修复问题,为Agent启动链添加了完整的注释,并做出了必要的修复与调整

This commit is contained in:
2025-09-13 23:37:35 +08:00
parent c1018d6b54
commit 7f9d007f07
17 changed files with 315 additions and 179 deletions

View File

@@ -12,6 +12,10 @@ import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* <h2>Agent 启动入口</h2>
* 详细启动流程请参阅{@link AgentRegisterFactory}
*/
public final class Agent {
public static AgentGatewayStep newAgent(Class<?> clazz) {

View File

@@ -16,12 +16,20 @@ import work.slhaf.partner.api.agent.factory.module.ModuleRegisterFactory;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.runtime.data.AgentContext;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.interaction.flow.AgentRunningFlow;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* <h2>Agent 注册工厂</h2>
*
* <p>
* 具体流程依次按照 {@link AgentRegisterFactory#launch(String)} 方法顺序执行,最终将执行模块列表对应实例交给 {@link AgentConfigManager} ,传递给 {@link AgentRunningFlow} 针对交互做出调用
* <p/>
*/
public class AgentRegisterFactory {
private static final List<URL> urls = new ArrayList<>();
@@ -35,14 +43,14 @@ public class AgentRegisterFactory {
//流程
//0. 加载配置
new ConfigLoaderFactory().execute(registerContext);
//1. 注册并检查Capability
new CapabilityRegisterFactory().execute(registerContext);
new CapabilityCheckFactory().execute(registerContext);
//2. 注册并检查Module
//1. 注册并检查Module
new ModuleCheckFactory().execute(registerContext);
new ModuleRegisterFactory().execute(registerContext);
//3. 为module通过动态代理添加PostHook逻辑并进行实例化
//2. 为module通过动态代理添加PostHook逻辑并进行实例化
new ModuleProxyFactory().execute(registerContext);
//3. 加载检查Capability层内容后进行能力层的内容注册
new CapabilityCheckFactory().execute(registerContext);
new CapabilityRegisterFactory().execute(registerContext);
//. 先一步注入Capability,避免因前hook逻辑存在针对能力的引用而报错
new CapabilityInjectFactory().execute(registerContext);
//. 执行模块PreHook逻辑

View File

@@ -9,6 +9,9 @@ import work.slhaf.partner.api.agent.factory.capability.exception.UnMatchedCapabi
import work.slhaf.partner.api.agent.factory.capability.exception.UnMatchedCoordinatedMethodException;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.module.ModuleCheckFactory;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import work.slhaf.partner.api.agent.util.AgentUtil;
import java.lang.reflect.Method;
@@ -18,7 +21,34 @@ import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* 执行<code>Capability</code>相关检查
* <h2>Agent启动流程 4</h2>
*
* <p>负责通过反射收集 {@link Capability} 和 {@link CapabilityCore} 注解所在类,并判断是否存在被错误忽略的方法</p>
*
* <ol>
* <li>
* <p>{@link CapabilityCheckFactory#loadCoresAndCapabilities()}</p>
* 通过反射收集 {@link Capability} 和 {@link CapabilityCore} 注解所在类为对应集合
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkCountAndCapabilities()}</p>
* 检测 {@link Capability} 与 {@link CapabilityCore} 的数量、对应的能力是否相等。每一个core都将对应一个capability并通过value属性进行匹配
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkCapabilityMethods()}</p>
* 检测在 {@link Capability} 与 {@link CapabilityCore} 中是否存在对方尚未实现/注册的方法
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkCoordinatedMethods()}</p>
* 检查是否包含协调方法({@link ToCoordinated}),如果存在,则进一步检查在 {@link CoordinateManager} 所注类中是否有提供对应的实现
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkInjectCapability()}</p>
* 检查 {@link InjectCapability} 注解是否只用在 {@link CapabilityHolder} 所标识类的字段上。{@link AgentModule} 与 {@link AgentSubModule} 已经被 {@link CapabilityHolder} 标注
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link CapabilityRegisterFactory}</p>
*/
public class CapabilityCheckFactory extends AgentBaseFactory {
@@ -37,12 +67,18 @@ public class CapabilityCheckFactory extends AgentBaseFactory {
@Override
protected void run() {
loadCoresAndCapabilities();
checkCountAndCapabilities();
checkCapabilityMethods();
checkCoordinatedMethods();
checkInjectCapability();
}
private void loadCoresAndCapabilities() {
cores.addAll(reflections.getTypesAnnotatedWith(CapabilityCore.class));
capabilities.addAll(reflections.getTypesAnnotatedWith(Capability.class));
}
/**
* 检查<code>@InjectCapability</code>注解是否只用在<code>@CapabilityHolder</code>所标识类的字段上
*/

View File

@@ -8,6 +8,9 @@ import work.slhaf.partner.api.agent.factory.capability.annotation.ToCoordinated;
import work.slhaf.partner.api.agent.factory.capability.exception.ProxySetFailedExceptionCapability;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.module.ModuleInitHookExecuteFactory;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
@@ -18,9 +21,23 @@ import java.util.function.Function;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* 负责执行<code>Capability</code>的注入逻辑
*/
public class CapabilityInjectFactory extends AgentBaseFactory {
* <h2>Agent启动流程 6</h2>
*
* <p>负责执行 {@link Capability} 的注入逻辑。</p>
*
* <p>实现方式:</p>
* <ol>
* <li>通过动态代理,为 {@link AgentModule} 与 {@link AgentSubModule} 中待注入的
* <b>能力接口</b> 类型(即 {@link Capability} 标注的接口类)生成代理对象。
* </li>
* <li>在代理对象内部,根据调用方法的签名确定路由,将调用转发至对应的具体函数。
* </li>
* <li>通过此机制,实现了 {@link Capability} 单一语义层面上普通方法与协调方法的统一入口。
* </li>
* </ol>
*
* <p>下一步流程请参阅 {@link ModuleInitHookExecuteFactory}</p>
*/public class CapabilityInjectFactory extends AgentBaseFactory {
private Reflections reflections;
private HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable;

View File

@@ -8,6 +8,8 @@ import work.slhaf.partner.api.agent.factory.capability.exception.CoreInstancesCr
import work.slhaf.partner.api.agent.factory.capability.exception.DuplicateMethodException;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -17,19 +19,48 @@ import java.util.HashMap;
import java.util.Set;
import java.util.function.Function;
import static cn.hutool.core.util.ClassUtil.isNormalClass;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* 负责获取<code>@Capability</code>和<code>@CapabilityCore</code>标识的类,并生成函数路由表、设置<code>Core</code>实例用于后续注入
* <h2>Agent启动流程 5</h2>
*
* <p>
* 负责收集注解 {@link Capability} 和 {@link CapabilityCore} 标识的类并生成函数路由表、创建core、capability实例以及放入instanceMap供后续进行注入操作
* </p>
*
* <ol>
* <li>
* <p>{@link CapabilityRegisterFactory#setCoreInstances()}</p>
* 通过反射调用无参构造函数创建core实例并将实例放入instanceMap供后续使用
* </li>
* <li>
* <p>{@link CapabilityRegisterFactory#generateRouterTable()}</p>
* 生成函数路由表:
* <ul>
* <li>
* <p>{@link CapabilityRegisterFactory#generateMethodsRouterTable()}</p>
* 生成普通方法对应的函数路由表
* </li>
* <li>
* <p>{@link CapabilityRegisterFactory#generateCoordinatedMethodsRouterTable()}</p>
* 生成协调方法对应的函数路由表
* </li>
* </ul>
* </li>
* <li>
* 函数路由表生成完毕、core实例创建完毕之后将交由下一工厂完成能力(Capability)注入操作,注入到 {@link AgentModule} 与 {@link AgentSubModule} 对应的实例中
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link CapabilityInjectFactory}</p>
*/
public final class CapabilityRegisterFactory extends AgentBaseFactory {
public class CapabilityRegisterFactory extends AgentBaseFactory {
private Reflections reflections;
private HashMap<String, Function<Object[], Object>> methodsRouterTable;
private HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable;
private HashMap<Class<?>, Object> capabilityCoreInstances;
private HashMap<Class<?>, Object> coreInstances;
private HashMap<Class<?>, Object> capabilityHolderInstances;
private Set<Class<?>> cores;
private Set<Class<?>> capabilities;
@@ -40,38 +71,18 @@ public final class CapabilityRegisterFactory extends AgentBaseFactory {
reflections = context.getReflections();
methodsRouterTable = factoryContext.getMethodsRouterTable();
coordinatedMethodsRouterTable = factoryContext.getCoordinatedMethodsRouterTable();
capabilityCoreInstances = factoryContext.getCapabilityCoreInstances();
coreInstances = factoryContext.getCapabilityCoreInstances();
cores = factoryContext.getCores();
capabilities = factoryContext.getCapabilities();
capabilityHolderInstances = factoryContext.getCapabilityHolderInstances();
}
@Override
protected void run() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
setCapabilityCoreInstances();
setAnnotatedClasses();
protected void run() {
setCoreInstances();
generateRouterTable();
}
/**
* 设置<code>CapabilityCore</code>、<code>Capability</code>注解标识类
*/
private void setAnnotatedClasses() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
cores.addAll(reflections.getTypesAnnotatedWith(CapabilityCore.class));
capabilities.addAll(reflections.getTypesAnnotatedWith(Capability.class));
setCapabilityHolderInstances();
}
private void setCapabilityHolderInstances() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
for (Class<?> clazz : reflections.getTypesAnnotatedWith(CapabilityHolder.class)) {
if (!isNormalClass(clazz)){
continue;
}
Object o = clazz.getDeclaredConstructor().newInstance();
capabilityHolderInstances.put(clazz, o);
}
}
/**
* 生成函数路由表
*/
@@ -128,17 +139,16 @@ public final class CapabilityRegisterFactory extends AgentBaseFactory {
}
/**
* 生成普通方法对应的函数路由表
* 扫描`@Capability`与`@CapabilityMethod`注解的类与方法
* 将`capabilityValue.methodSignature`作为key,函数对象为通过反射拿到的core实例对应的方法
*/
private void generateMethodsRouterTable() {
//扫描`@Capability`与`@CapabilityMethod`注解的类与方法
//将`capabilityValue.methodSignature`作为key,函数对象为通过反射拿到的core实例对应的方法
cores.forEach(core -> Arrays.stream(core.getMethods())
.filter(method -> method.isAnnotationPresent(CapabilityMethod.class))
.forEach(method -> {
Function<Object[], Object> function = args -> {
try {
return method.invoke(capabilityCoreInstances.get(core), args);
return method.invoke(coreInstances.get(core), args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
@@ -154,12 +164,12 @@ public final class CapabilityRegisterFactory extends AgentBaseFactory {
/**
* 反射获取<code>CapabilityCore</code>实例
*/
private void setCapabilityCoreInstances() {
private void setCoreInstances() {
try {
for (Class<?> core : cores) {
Constructor<?> constructor = core.getDeclaredConstructor();
constructor.setAccessible(true);
capabilityCoreInstances.put(core, constructor.newInstance());
coreInstances.put(core, constructor.newInstance());
}
} catch (InvocationTargetException | NoSuchMethodException | InstantiationException |
IllegalAccessException e) {

View File

@@ -4,6 +4,7 @@ import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.ConfigFactoryContext;
import work.slhaf.partner.api.agent.factory.module.ModuleCheckFactory;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.config.FileAgentConfigManager;
import work.slhaf.partner.api.chat.pojo.Message;
@@ -11,6 +12,14 @@ import work.slhaf.partner.api.chat.pojo.Message;
import java.util.HashMap;
import java.util.List;
/**
* <h2>Agent启动流程 0</h2>
* <p>
* 通过指定的 {@link AgentConfigManager} 或者默认的 {@link FileAgentConfigManager} 加载配置文件
* <p/>
*
* <p>下一步流程请参阅{@link ModuleCheckFactory}</p>
*/
public class ConfigLoaderFactory extends AgentBaseFactory {
private AgentConfigManager agentConfigManager;

View File

@@ -4,10 +4,7 @@ import cn.hutool.core.util.ClassUtil;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
import work.slhaf.partner.api.agent.factory.module.annotation.*;
import work.slhaf.partner.api.agent.factory.module.exception.ModuleCheckException;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
@@ -21,6 +18,30 @@ import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.getMethodAnnotationTypeSet;
/**
* <h2>Agent启动流程 1</h2>
*
* <p>
* 检查模块部分抽象类与注解、接口的使用方式
* </p>
*
* <ol>
* <li>
* <p>{@link ModuleCheckFactory#annotationAbstractCheck(Set, Class)}</p>
* 所有添加了 {@link AgentModule} 注解的类都将作为Agent的执行模块为规范模块入口都必须实现抽象类: {@link AgentRunningModule}; {@link AgentSubModule} 注解所在类则必须实现 {@link AgentRunningSubModule}
* </li>
* <li>
* <p>{@link ModuleCheckFactory#moduleConstructorsCheck(Set)}</p>
* 所有 {@link AgentModule} 与 {@link AgentSubModule} 注解所在类都必须具备空参构造方法,初始化逻辑可放在 @Init 注解所处方法中,将在 Capability 与 subModules 注入后才会执行
* </li>
* <li>
* <p>{@link ModuleCheckFactory#activateModelImplCheck()}</p>
* 检查实现了 {@link ActivateModel} 的模块数量、名称与prompt是否一致
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link ModuleRegisterFactory}</p>
*/
public class ModuleCheckFactory extends AgentBaseFactory {
private Reflections reflections;
@@ -32,13 +53,14 @@ public class ModuleCheckFactory extends AgentBaseFactory {
@Override
protected void run() {
Set<Class<?>> types = reflections.getTypesAnnotatedWith(AgentModule.class);
//检查注解AgentModule所在类是否继承了AgentInteractionModule
agentModuleAnnotationCheck(types);
Set<Class<?>> moduleTypes = reflections.getTypesAnnotatedWith(AgentModule.class);
Set<Class<?>> subModuleTypes = reflections.getTypesAnnotatedWith(AgentSubModule.class);
//检查注解AgentModule或AgentSubModule所在类是否继承了对应的抽象类
annotationAbstractCheck(moduleTypes, AgentRunningModule.class);
annotationAbstractCheck(subModuleTypes, AgentRunningSubModule.class);
//检查AgentModule是否具备无参构造方法
moduleConstructorsCheck(types);
//检查hook注解所在方法是否位于AgentInteractionModule子类/AgentInteractionSubModule子类/ActivateModel子类
hookLocationCheck();
moduleConstructorsCheck(moduleTypes);
moduleConstructorsCheck(subModuleTypes);
//检查实现了ActivateModel的模块数量、名称与prompt是否一致
activateModelImplCheck();
}
@@ -128,12 +150,12 @@ public class ModuleCheckFactory extends AgentBaseFactory {
}
}
private void agentModuleAnnotationCheck(Set<Class<?>> types) {
private void annotationAbstractCheck(Set<Class<?>> types, Class<?> clazz) {
for (Class<?> type : types) {
if (type.isAnnotation()) {
continue;
}
if (AgentRunningModule.class.isAssignableFrom(type) && ClassUtil.isNormalClass(type)) {
if (clazz.isAssignableFrom(type) && ClassUtil.isNormalClass(type)) {
continue;
}
throw new ModuleCheckException("存在未继承AgentInteractionModule.class的AgentModule实现: " + type.getSimpleName());

View File

@@ -1,6 +1,7 @@
package work.slhaf.partner.api.agent.factory.module;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.AgentRegisterFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.ModuleFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
@@ -10,6 +11,7 @@ import work.slhaf.partner.api.agent.factory.module.pojo.MetaMethod;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.util.AgentUtil;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
@@ -19,7 +21,22 @@ import static work.slhaf.partner.api.agent.util.AgentUtil.collectExtendedClasses
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* 负责执行前hook逻辑
* <h2>Agent启动流程 7</h2>
*
* <p>负责执行初始化hook逻辑即 {@link Init} 注解所在方法</p>
*
* <ol>
* <li>
* <p>{@link ModuleInitHookExecuteFactory#collectInitHookMethods(Class)}</p>
* 分别遍历前置模块拿到的模块列表({@link ModuleInitHookExecuteFactory#moduleList}, {@link ModuleInitHookExecuteFactory#subModuleList}),通过 {@link AgentUtil#collectExtendedClasses(Class, Class)} 收集到当前模块类的继承链上的所有类后,收集其所有带有 {@link Init} 注解的方法
* </li>
* <li>
* <p>{@link ModuleInitHookExecuteFactory#proceedInitMethods(BaseMetaModule, List)}</p>
* 收集好初始化方法后,将通过反射执行该方法,所用实例即为前置模块中收集到的执行模块与子模块的 {@link MetaModule} 与 {@link MetaSubModule} 内容
* </li>
* </ol>
*
* <p>Agent启动流程到此进行完毕。整个工厂执行链中均为针对 {@link AgentRegisterContext} 进行的操作,在 {@link AgentRegisterFactory} 中,将进行最终处理以及将必要内容进行传递。</p>
*/
public class ModuleInitHookExecuteFactory extends AgentBaseFactory {
@@ -36,15 +53,15 @@ public class ModuleInitHookExecuteFactory extends AgentBaseFactory {
@Override
protected void run() {
//遍历模块列表,并向上查找@Init注解
for (MetaModule metaModule : moduleList) {
List<MetaMethod> initHookMethods = collectInitHookMethods(metaModule.getClazz());
proceedInitMethods(metaModule, initHookMethods);
}
for (MetaSubModule metaSubModule : subModuleList) {
List<MetaMethod> initHookMethods = collectInitHookMethods(metaSubModule.getClazz());
proceedInitMethods(metaSubModule, initHookMethods);
}
for (MetaModule metaModule : moduleList) {
List<MetaMethod> initHookMethods = collectInitHookMethods(metaModule.getClazz());
proceedInitMethods(metaModule, initHookMethods);
}
}
private void proceedInitMethods(BaseMetaModule metaModule, List<MetaMethod> initHookMethods) {

View File

@@ -4,9 +4,10 @@ import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.*;
import net.bytebuddy.matcher.ElementMatchers;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.context.ModuleFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute;
@@ -18,10 +19,9 @@ import work.slhaf.partner.api.agent.factory.module.pojo.MetaMethod;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.Module;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.Callable;
@@ -30,46 +30,85 @@ import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.collectExtendedClasses;
/**
* 通过扫描注解<code>@BeforeExecute</code>获取到各个模块的后hook逻辑并通过动态代理添加到执行逻辑之后
* <h2>Agent启动流程 3</h2>
*
* <p>
* 扫描前置模块各个hook注解生成代理对象放入对应的list中并按照类型为键放入 {@link ModuleProxyFactory#capabilityHolderInstances} 中供后续完成能力(capability)注入
* <p/>
*
* <ol>
*
* <li>
* <p>{@link ModuleProxyFactory#createProxiedInstances()}</p>
* 根据moduleList中的类型信息向上查找继承链获取所有hook方法收集为{@link MethodsListRecord}然后通过ByteBuddy根据收集到的preHook与postHook生成代理对象放入对应的 {@link MetaModule} 对象以及 instanceMap 中
* </li>
* <li>
* <p>{@link ModuleProxyFactory#injectSubModule()}</p>
* 通过反射将子模块实例注入到执行模块中带有注解 {@link InjectModule} 的字段
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link CapabilityCheckFactory}</p>
*/
public class ModuleProxyFactory extends AgentBaseFactory {
private List<MetaModule> moduleList;
private List<MetaSubModule> subModuleList;
private Reflections reflections;
private HashMap<Class<?>, Object> capabilityHolderInstances;
private final HashMap<Class<?>, Object> subModuleInstances = new HashMap<>();
private final HashMap<Class<?>, Object> moduleInstances = new HashMap<>();
@Override
protected void setVariables(AgentRegisterContext context) {
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
CapabilityFactoryContext capabilityFactoryContext = context.getCapabilityFactoryContext();
moduleList = factoryContext.getAgentModuleList();
subModuleList = factoryContext.getAgentSubModuleList();
reflections = context.getReflections();
capabilityHolderInstances = capabilityFactoryContext.getCapabilityHolderInstances();
}
@Override
protected void run() {
generateInstances();
createProxy();
createProxiedInstances();
injectSubModule();
}
private void injectSubModule() {
Set<Field> fields = reflections.getFieldsAnnotatedWith(InjectModule.class);
for (MetaModule module : moduleList) {
Arrays.stream(module.getClazz().getFields())
.filter(field -> field.isAnnotationPresent(InjectModule.class))
.forEach(field -> {
try {
for (Field field : fields) {
field.setAccessible(true);
field.set(moduleInstances.get(field.getDeclaringClass()), subModuleInstances.get(field.getType()));
}
} catch (Exception e) {
field.set(
moduleInstances.get(module.getClazz()),
subModuleInstances.get(field.getType())
);
} catch (IllegalAccessException e) {
throw new ModuleInstanceGenerateFailedException("模块实例注入失败", e);
}
});
}
private void createProxy() {
}
private void createProxiedInstances() {
generateModuleProxy(moduleList);
generateModuleProxy(subModuleList);
updateInstanceMap(moduleInstances, moduleList);
updateInstanceMap(subModuleInstances, subModuleList);
updateCapabilityHolderInstances();
}
private void updateCapabilityHolderInstances() {
capabilityHolderInstances.putAll(moduleInstances);
capabilityHolderInstances.putAll(subModuleInstances);
}
private void updateInstanceMap(HashMap<Class<?>, Object> instanceMap, List<? extends BaseMetaModule> list) {
for (BaseMetaModule baseMetaModule : list) {
instanceMap.put(baseMetaModule.getClazz(), baseMetaModule.getInstance());
}
}
@@ -88,8 +127,8 @@ public class ModuleProxyFactory extends AgentBaseFactory {
private void generateProxiedInstances(MethodsListRecord record, BaseMetaModule module) {
try {
Class<? extends AgentRunningModule> clazz = module.getClazz();
Class<? extends AgentRunningModule> proxyClass = new ByteBuddy()
Class<? extends Module> clazz = module.getClazz();
Class<? extends Module> proxyClass = new ByteBuddy()
.subclass(clazz)
.method(ElementMatchers.isOverriddenFrom(AgentRunningModule.class))
.intercept(MethodDelegation.to(new ModuleProxyInterceptor(record.post, record.pre)))
@@ -165,30 +204,6 @@ public class ModuleProxyFactory extends AgentBaseFactory {
}
}
private void generateInstances() {
for (MetaModule module : moduleList) {
try {
Class<? extends AgentRunningModule> clazz = module.getClazz();
AgentRunningModule instance = clazz.getConstructor().newInstance();
module.setInstance(instance);
moduleInstances.put(module.getClazz(), instance);
} catch (Exception e) {
throw new ModuleInstanceGenerateFailedException("模块实例构造失败:" + e.getMessage());
}
}
for (MetaSubModule module : subModuleList) {
try {
Class<? extends AgentRunningSubModule> clazz = module.getClazz();
AgentRunningSubModule instance = clazz.getConstructor().newInstance();
module.setInstance(instance);
subModuleInstances.put(module.getClazz(), instance);
} catch (Exception e) {
throw new ModuleInstanceGenerateFailedException("模块实例构造失败:" + e.getMessage());
}
}
}
private record ModuleProxyInterceptor(List<MetaMethod> postHookMethods, List<MetaMethod> preHookMethods) {
@RuntimeType
public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper, @This Object proxy) throws Exception {

View File

@@ -17,7 +17,27 @@ import java.util.List;
import java.util.Set;
/**
* 负责扫描<code>@Module</code>注解获取模块实例
* <h2>Agent启动流程 2</h2>
*
* <p>
* 负责收集 {@link AgentModule} 与 {@link AgentSubModule} 注解所在类的信息,供后续工厂完成动态代理、模块与能力注入
* <p/>
*
* <ol>
* <li>
* <p>{@link ModuleRegisterFactory#setModuleList()}</p>
* 扫描 {@link AgentModule} 注解,获取执行模块信息: 类型、模块名称({@link AgentModule#name()}),执行顺序。并按照注解的 {@link AgentModule#order()} 字段进行排序
* </li>
* <li>
* <p>{@link ModuleRegisterFactory#setSubModuleList()}</p>
* 扫描 {@link AgentSubModule} 注册,获取子模块类型信息
* </li>
* <li>
* 两种模块都将存入各自的list中供后续模块完成注册与注入
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link ModuleProxyFactory}</p>
*/
public class ModuleRegisterFactory extends AgentBaseFactory {

View File

@@ -1,7 +1,7 @@
package work.slhaf.partner.common.util;
import com.alibaba.fastjson2.JSONArray;
import work.slhaf.partner.Agent;
import work.slhaf.partner.api.agent.Agent;
import work.slhaf.partner.api.chat.pojo.Message;
import java.io.InputStream;

View File

@@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.InjectModule;
import work.slhaf.partner.core.cognation.CognationCapability;
import work.slhaf.partner.core.common.pojo.MemoryResult;
import work.slhaf.partner.core.submodule.cache.CacheCapability;
@@ -36,8 +37,6 @@ import java.util.List;
@AgentModule(name="memory_selector",order=1)
public class MemorySelector extends PreRunningModule {
private static volatile MemorySelector memorySelector;
@InjectCapability
private CacheCapability cacheCapability;
@InjectCapability
@@ -45,26 +44,10 @@ public class MemorySelector extends PreRunningModule {
@InjectCapability
private CognationCapability cognationCapability;
@InjectModule
private SliceSelectEvaluator sliceSelectEvaluator;
@InjectModule
private MemorySelectExtractor memorySelectExtractor;
private SessionManager sessionManager;
private MemorySelector() {
}
public static MemorySelector getInstance() throws IOException, ClassNotFoundException {
if (memorySelector == null) {
synchronized (MemorySelector.class) {
if (memorySelector == null) {
memorySelector = new MemorySelector();
memorySelector.setSliceSelectEvaluator(SliceSelectEvaluator.getInstance());
memorySelector.setMemorySelectExtractor(MemorySelectExtractor.getInstance());
memorySelector.setSessionManager(SessionManager.getInstance());
}
}
}
return memorySelector;
}
@Override
public void execute(PartnerRunningFlowContext runningFlowContext) throws IOException, ClassNotFoundException {

View File

@@ -6,6 +6,8 @@ import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import work.slhaf.partner.common.thread.InteractionThreadPoolExecutor;
@@ -30,21 +32,14 @@ import static work.slhaf.partner.common.util.ExtractUtil.extractJson;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
@AgentSubModule
public class SliceSelectEvaluator extends AgentRunningSubModule<EvaluatorInput, List<EvaluatedSlice>> implements ActivateModel {
private static volatile SliceSelectEvaluator sliceSelectEvaluator;
private InteractionThreadPoolExecutor executor;
public static SliceSelectEvaluator getInstance() throws IOException, ClassNotFoundException {
if (sliceSelectEvaluator == null) {
synchronized (SliceSelectEvaluator.class) {
if (sliceSelectEvaluator == null) {
sliceSelectEvaluator = new SliceSelectEvaluator();
sliceSelectEvaluator.setExecutor(InteractionThreadPoolExecutor.getInstance());
log.info("SliceEvaluator注册完毕...");
}
}
}
return sliceSelectEvaluator;
@Init
public void init() {
executor = InteractionThreadPoolExecutor.getInstance();
}
@Override

View File

@@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import work.slhaf.partner.api.chat.pojo.Message;
@@ -21,7 +22,6 @@ import work.slhaf.partner.module.modules.memory.selector.extractor.data.Extracto
import work.slhaf.partner.module.modules.memory.selector.extractor.data.ExtractorMatchData;
import work.slhaf.partner.module.modules.memory.selector.extractor.data.ExtractorResult;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -31,30 +31,19 @@ import static work.slhaf.partner.common.util.ExtractUtil.fixTopicPath;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class MemorySelectExtractor extends AgentRunningSubModule<PartnerRunningFlowContext, ExtractorResult> implements ActivateModel {
private static volatile MemorySelectExtractor memorySelectExtractor;
public class MemorySelectExtractor extends AgentRunningSubModule<PartnerRunningFlowContext, ExtractorResult>
implements ActivateModel {
@InjectCapability
private MemoryCapability memoryCapability;
@InjectCapability
private CognationCapability cognationCapability;
private SessionManager sessionManager;
private MemorySelectExtractor() {
modelSettings();
}
public static MemorySelectExtractor getInstance() throws IOException, ClassNotFoundException {
if (memorySelectExtractor == null) {
synchronized (MemorySelectExtractor.class) {
if (memorySelectExtractor == null) {
memorySelectExtractor = new MemorySelectExtractor();
memorySelectExtractor.setSessionManager(SessionManager.getInstance());
}
}
}
return memorySelectExtractor;
@Init
public void init() {
sessionManager = SessionManager.getInstance();
}
@Override

View File

@@ -5,6 +5,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
import work.slhaf.partner.api.agent.factory.module.annotation.InjectModule;
import work.slhaf.partner.api.chat.constant.ChatConstant;
import work.slhaf.partner.api.chat.pojo.Message;
import work.slhaf.partner.common.thread.InteractionThreadPoolExecutor;
@@ -32,6 +35,7 @@ import static work.slhaf.partner.common.util.ExtractUtil.extractUserId;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
@AgentModule(name="memory_updater",order=6)
public class MemoryUpdater extends PostRunningModule {
private static volatile MemoryUpdater memoryUpdater;
@@ -47,25 +51,24 @@ public class MemoryUpdater extends PostRunningModule {
private CacheCapability cacheCapability;
@InjectCapability
private PerceiveCapability perceiveCapability;
private InteractionThreadPoolExecutor executor;
@InjectModule
private MemorySelectExtractor memorySelectExtractor;
@InjectModule
private MemorySummarizer memorySummarizer;
private SessionManager sessionManager;
private InteractionThreadPoolExecutor executor;
/**
* 用于临时存储完整对话记录在MemoryManager的分离后
*/
private List<Message> tempMessage;
private MemoryUpdater() {
}
public static MemoryUpdater getInstance() throws IOException, ClassNotFoundException {
if (memoryUpdater == null) {
synchronized (MemoryUpdater.class) {
if (memoryUpdater == null) {
memoryUpdater = new MemoryUpdater();
memoryUpdater.setMemorySelectExtractor(MemorySelectExtractor.getInstance());
memoryUpdater.setMemorySummarizer(MemorySummarizer.getInstance());
memoryUpdater.setSessionManager(SessionManager.getInstance());
memoryUpdater.setExecutor(InteractionThreadPoolExecutor.getInstance());
memoryUpdater.setScheduledUpdater();
@@ -75,6 +78,13 @@ public class MemoryUpdater extends PostRunningModule {
return memoryUpdater;
}
@Init
public void init() {
executor = InteractionThreadPoolExecutor.getInstance();
sessionManager = SessionManager.getInstance();
setScheduledUpdater();
}
private void setScheduledUpdater() {
executor.execute(() -> {
log.info("[MemoryUpdater] 记忆自动更新线程启动");

View File

@@ -2,15 +2,16 @@ package work.slhaf.partner.module.modules.task;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import work.slhaf.partner.runtime.interaction.module.InteractionFlow;
@Data
@Slf4j
public class TaskScheduler implements InteractionFlow {
public class TaskScheduler extends AgentRunningModule {
private static TaskScheduler taskScheduler;
private TaskScheduler(){}
private TaskScheduler() {
}
public static TaskScheduler getInstance() {
if (taskScheduler == null) {

View File

@@ -69,7 +69,7 @@ Partner 的目标不是复现某种单一能力,而是尝试在结构中形成
- 系统的正常运作效果取决于各模块中大模型对于`prompt`的遵循能力,目前来看`qwen3`的遵循效果明显较好,但在轮次较多时,也容易出现不遵循的情况。
## 规划
- [ ]善注解驱动的注册机制
- [ ]成框架与本体的适配工作
- [ ] 实现任务与主动调度模块,目前打算用 `时间轮算法` 实现定时操作
- [ ] 完善具备‘记忆切片、实体图谱、向量召回’的三维记忆融合架构,包含 Episodic + Semantic + Fuzzy 三类记忆
- [ ] 服务端与客户端的通信加上消息队列,防止消息因连接断开而丢失。