mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
refactor(framework): replace legacy module check/register/proxy flow with unified AgentComponentRegisterFactory
This commit is contained in:
@@ -4,10 +4,8 @@ import org.reflections.util.ClasspathHelper;
|
|||||||
import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory;
|
import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory;
|
||||||
import work.slhaf.partner.api.agent.factory.capability.CapabilityInjectFactory;
|
import work.slhaf.partner.api.agent.factory.capability.CapabilityInjectFactory;
|
||||||
import work.slhaf.partner.api.agent.factory.capability.CapabilityRegisterFactory;
|
import work.slhaf.partner.api.agent.factory.capability.CapabilityRegisterFactory;
|
||||||
import work.slhaf.partner.api.agent.factory.component.ModuleCheckFactory;
|
import work.slhaf.partner.api.agent.factory.component.AgentComponentRegisterFactory;
|
||||||
import work.slhaf.partner.api.agent.factory.component.ModuleInitHookExecuteFactory;
|
import work.slhaf.partner.api.agent.factory.component.ModuleInitHookExecuteFactory;
|
||||||
import work.slhaf.partner.api.agent.factory.component.ModuleProxyFactory;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.ModuleRegisterFactory;
|
|
||||||
import work.slhaf.partner.api.agent.factory.config.ConfigLoaderFactory;
|
import work.slhaf.partner.api.agent.factory.config.ConfigLoaderFactory;
|
||||||
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
|
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
|
||||||
import work.slhaf.partner.api.agent.factory.exception.ExternalModuleLoadFailedException;
|
import work.slhaf.partner.api.agent.factory.exception.ExternalModuleLoadFailedException;
|
||||||
@@ -40,11 +38,8 @@ public class AgentRegisterFactory {
|
|||||||
//流程
|
//流程
|
||||||
//0. 加载配置
|
//0. 加载配置
|
||||||
new ConfigLoaderFactory().execute(registerContext);
|
new ConfigLoaderFactory().execute(registerContext);
|
||||||
//1. 注册并检查Module
|
//1. 收集所有的 AgentComponent 实例
|
||||||
new ModuleCheckFactory().execute(registerContext);
|
new AgentComponentRegisterFactory().execute(registerContext);
|
||||||
new ModuleRegisterFactory().execute(registerContext);
|
|
||||||
//2. 为module通过动态代理添加PostHook逻辑并进行实例化
|
|
||||||
new ModuleProxyFactory().execute(registerContext);
|
|
||||||
//3. 加载检查Capability层内容后进行能力层的内容注册
|
//3. 加载检查Capability层内容后进行能力层的内容注册
|
||||||
new CapabilityCheckFactory().execute(registerContext);
|
new CapabilityCheckFactory().execute(registerContext);
|
||||||
new CapabilityRegisterFactory().execute(registerContext);
|
new CapabilityRegisterFactory().execute(registerContext);
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package work.slhaf.partner.api.agent.factory.component
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray
|
||||||
|
import com.alibaba.fastjson2.JSONObject
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import work.slhaf.partner.api.agent.factory.AgentBaseFactory
|
||||||
|
import work.slhaf.partner.api.agent.factory.component.abstracts.AbstractAgentModule
|
||||||
|
import work.slhaf.partner.api.agent.factory.component.abstracts.ActivateModel
|
||||||
|
import work.slhaf.partner.api.agent.factory.component.annotation.AgentComponent
|
||||||
|
import work.slhaf.partner.api.agent.factory.component.exception.ModuleFactoryInitFailedException
|
||||||
|
import work.slhaf.partner.api.agent.factory.config.exception.PromptNotExistException
|
||||||
|
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.ModuleContextData
|
||||||
|
import work.slhaf.partner.api.chat.pojo.Message
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
import java.time.ZonedDateTime
|
||||||
|
|
||||||
|
class AgentComponentRegisterFactory : AgentBaseFactory() {
|
||||||
|
companion object {
|
||||||
|
private val log = LoggerFactory.getLogger(AgentComponentRegisterFactory::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(context: AgentRegisterContext) {
|
||||||
|
val reflections = context.reflections
|
||||||
|
val configFactoryContext = context.configFactoryContext
|
||||||
|
val agentContext = context.agentContext
|
||||||
|
|
||||||
|
val modelConfigMap = configFactoryContext.modelConfigMap
|
||||||
|
val modelPromptMap = configFactoryContext.modelPromptMap
|
||||||
|
val defaultConfig = modelConfigMap["default"]!!
|
||||||
|
|
||||||
|
reflections.getTypesAnnotatedWith(AgentComponent::class.java)
|
||||||
|
.asSequence()
|
||||||
|
.filter { isConcreteClass(it) }
|
||||||
|
.forEach { componentClass ->
|
||||||
|
val componentInstance = try {
|
||||||
|
val constructor = componentClass.getDeclaredConstructor()
|
||||||
|
constructor.isAccessible = true
|
||||||
|
constructor.newInstance()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw ModuleFactoryInitFailedException("AgentComponent 实例化失败: ${componentClass.name}", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (componentInstance is AbstractAgentModule) {
|
||||||
|
registerModule(
|
||||||
|
agentContext,
|
||||||
|
componentClass,
|
||||||
|
componentInstance,
|
||||||
|
modelConfigMap,
|
||||||
|
modelPromptMap,
|
||||||
|
defaultConfig
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
addAdditionalComponent(agentContext, componentClass, componentInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private fun registerModule(
|
||||||
|
agentContext: work.slhaf.partner.api.agent.factory.context.AgentContext,
|
||||||
|
componentClass: Class<*>,
|
||||||
|
module: AbstractAgentModule,
|
||||||
|
modelConfigMap: Map<String, ModelConfig>,
|
||||||
|
modelPromptMap: Map<String, List<Message>>,
|
||||||
|
defaultConfig: ModelConfig
|
||||||
|
) {
|
||||||
|
val launchTime = ZonedDateTime.now()
|
||||||
|
val modelInfo = if (module is ActivateModel) {
|
||||||
|
val modelKey = module.modelKey()
|
||||||
|
val modelConfig = modelConfigMap[modelKey] ?: defaultConfig
|
||||||
|
val modelPrompt = modelPromptMap[modelKey]
|
||||||
|
?: throw PromptNotExistException("不存在的modelPrompt: $modelKey")
|
||||||
|
ModuleContextData.ModelInfo(
|
||||||
|
modelConfig.baseUrl,
|
||||||
|
modelConfig.model,
|
||||||
|
JSONArray.parseArray(JSONObject.toJSONString(modelPrompt))
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
when (module) {
|
||||||
|
is AbstractAgentModule.Running<*> -> {
|
||||||
|
val moduleContext = ModuleContextData.Running(
|
||||||
|
clazz = componentClass as Class<AbstractAgentModule.Running<*>>,
|
||||||
|
instance = module,
|
||||||
|
launchTime = launchTime,
|
||||||
|
modelInfo = modelInfo,
|
||||||
|
order = module.order(),
|
||||||
|
enabled = true
|
||||||
|
)
|
||||||
|
agentContext.addModule(module.moduleName, moduleContext as ModuleContextData<AbstractAgentModule>)
|
||||||
|
}
|
||||||
|
|
||||||
|
is AbstractAgentModule.Sub<*, *> -> {
|
||||||
|
val moduleContext = ModuleContextData.Sub(
|
||||||
|
clazz = componentClass as Class<AbstractAgentModule.Sub<*, *>>,
|
||||||
|
instance = module,
|
||||||
|
launchTime = launchTime,
|
||||||
|
modelInfo = modelInfo
|
||||||
|
)
|
||||||
|
agentContext.addModule(module.moduleName, moduleContext as ModuleContextData<AbstractAgentModule>)
|
||||||
|
}
|
||||||
|
|
||||||
|
is AbstractAgentModule.Standalone -> {
|
||||||
|
val moduleContext = ModuleContextData.Standalone(
|
||||||
|
clazz = componentClass as Class<AbstractAgentModule.Standalone>,
|
||||||
|
instance = module,
|
||||||
|
launchTime = launchTime,
|
||||||
|
modelInfo = modelInfo
|
||||||
|
)
|
||||||
|
agentContext.addModule(module.moduleName, moduleContext as ModuleContextData<AbstractAgentModule>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addAdditionalComponent(
|
||||||
|
agentContext: work.slhaf.partner.api.agent.factory.context.AgentContext,
|
||||||
|
componentClass: Class<*>,
|
||||||
|
componentInstance: Any
|
||||||
|
) {
|
||||||
|
val added = agentContext.addAdditionalComponent(componentInstance)
|
||||||
|
if (!added) {
|
||||||
|
log.error("AgentComponent追加注册失败(被拒绝): {}", componentClass.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isConcreteClass(type: Class<*>): Boolean {
|
||||||
|
if (type.isInterface || type.isAnnotation || type.isEnum || type.isArray || type.isPrimitive) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (type.isSynthetic || type.isAnonymousClass || type.isLocalClass) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !Modifier.isAbstract(type.modifiers)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
package work.slhaf.partner.api.agent.factory.component;
|
|
||||||
|
|
||||||
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.component.abstracts.ActivateModel;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.annotation.Init;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.exception.ModuleCheckException;
|
|
||||||
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
|
|
||||||
import work.slhaf.partner.api.agent.runtime.config.AgentConfigLoader;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>Agent启动流程 1</h2>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 检查模块部分抽象类与注解、接口的使用方式
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li>
|
|
||||||
* <p>{@link ModuleCheckFactory#annotationAbstractCheck(Set, Class)}</p>
|
|
||||||
* 所有添加了 {@link AgentRunningModule} 注解的类都将作为Agent的执行模块,为规范模块入口,都必须实现抽象类: {@link AbstractAgentRunningModule}; {@link AgentSubModule} 注解所在类则必须实现 {@link AbstractAgentSubModule}
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* <p>{@link ModuleCheckFactory#moduleConstructorsCheck(Set)}</p>
|
|
||||||
* 所有 {@link AgentRunningModule} 与 {@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;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setVariables(AgentRegisterContext context) {
|
|
||||||
reflections = context.getReflections();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void run() {
|
|
||||||
AnnotatedModules annotatedModules = getAnnotatedModules();
|
|
||||||
ExtendedModules extendedModules = getExtendedModules();
|
|
||||||
checkIfClassCorresponds(annotatedModules, extendedModules);
|
|
||||||
//检查注解AgentModule或AgentSubModule所在类是否继承了对应的抽象类
|
|
||||||
annotationAbstractCheck(annotatedModules.moduleTypes(), AbstractAgentRunningModule.class);
|
|
||||||
annotationAbstractCheck(annotatedModules.subModuleTypes(), AbstractAgentSubModule.class);
|
|
||||||
//检查AgentModule是否具备无参构造方法
|
|
||||||
moduleConstructorsCheck(annotatedModules.moduleTypes());
|
|
||||||
moduleConstructorsCheck(annotatedModules.subModuleTypes());
|
|
||||||
//检查实现了ActivateModel的模块数量、名称与prompt是否一致
|
|
||||||
activateModelImplCheck();
|
|
||||||
//检查hook注解所在位置是否正确
|
|
||||||
initHookLocationCheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExtendedModules getExtendedModules() {
|
|
||||||
Set<Class<?>> moduleTypes = reflections.getSubTypesOf(AbstractAgentRunningModule.class)
|
|
||||||
.stream()
|
|
||||||
.filter(ClassUtil::isNormalClass)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
Set<Class<?>> subModuleTypes = reflections.getSubTypesOf(AbstractAgentSubModule.class)
|
|
||||||
.stream()
|
|
||||||
.filter(ClassUtil::isNormalClass)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
return new ExtendedModules(moduleTypes, subModuleTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AnnotatedModules getAnnotatedModules() {
|
|
||||||
Set<Class<?>> moduleTypes = reflections.getTypesAnnotatedWith(AgentRunningModule.class)
|
|
||||||
.stream()
|
|
||||||
.filter(ClassUtil::isNormalClass)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
Set<Class<?>> subModuleTypes = reflections.getTypesAnnotatedWith(AgentSubModule.class)
|
|
||||||
.stream()
|
|
||||||
.filter(ClassUtil::isNormalClass)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
return new AnnotatedModules(moduleTypes, subModuleTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moduleConstructorsCheck(Set<Class<?>> types) {
|
|
||||||
for (Class<?> type : types) {
|
|
||||||
try {
|
|
||||||
type.getConstructor();
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
throw new ModuleCheckException("缺少无参构造方法的模块: " + type.getSimpleName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void activateModelImplCheck() {
|
|
||||||
try {
|
|
||||||
Set<Class<? extends ActivateModel>> types = reflections.getSubTypesOf(ActivateModel.class);
|
|
||||||
Set<String> modelKeySet = new HashSet<>();
|
|
||||||
for (Class<? extends ActivateModel> type : types) {
|
|
||||||
ActivateModel instance = type.getConstructor().newInstance();
|
|
||||||
modelKeySet.add(instance.modelKey());
|
|
||||||
}
|
|
||||||
Set<String> promptKeySet = AgentConfigLoader.INSTANCE.getModelPromptMap().keySet();
|
|
||||||
if (!promptKeySet.containsAll(modelKeySet)) {
|
|
||||||
modelKeySet.removeAll(promptKeySet);
|
|
||||||
throw new ModuleCheckException("存在未配置Prompt的ActivateModel实现! 缺少Prompt的ModelKey列表: " + modelKeySet);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ModuleCheckException("ActivateModel 检测出错", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initHookLocationCheck() {
|
|
||||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(Init.class);
|
|
||||||
Set<Class<?>> types = methods.stream()
|
|
||||||
.map(Method::getDeclaringClass)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
checkLocation(types);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkLocation(Set<Class<?>> types) {
|
|
||||||
for (Class<?> type : types) {
|
|
||||||
if (AbstractAgentRunningModule.class.isAssignableFrom(type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (AbstractAgentSubModule.class.isAssignableFrom(type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ActivateModel.class.isAssignableFrom(type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
throw new ModuleCheckException("在不支持的类中使用了hook注解: " + type.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void annotationAbstractCheck(Set<Class<?>> types, Class<?> clazz) {
|
|
||||||
for (Class<?> type : types) {
|
|
||||||
if (type.isAnnotation()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (clazz.isAssignableFrom(type) && ClassUtil.isNormalClass(type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
throw new ModuleCheckException("存在未继承AgentInteractionModule.class的AgentModule实现: " + type.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkIfClassCorresponds(AnnotatedModules annotatedModules, ExtendedModules extendedModules) {
|
|
||||||
// 检查是否有被@AgentModule注解但没有继承AgentRunningModule的类
|
|
||||||
checkSets(annotatedModules.moduleTypes(), extendedModules.moduleTypes(),
|
|
||||||
"存在被@AgentModule注解但未继承AgentRunningModule的类");
|
|
||||||
|
|
||||||
// 检查是否有继承AgentRunningModule但没有被@AgentModule注解的类
|
|
||||||
checkSets(extendedModules.moduleTypes(), annotatedModules.moduleTypes(),
|
|
||||||
"存在继承AgentRunningModule但未被@AgentModule注解的类");
|
|
||||||
|
|
||||||
// 检查是否有被@AgentSubModule注解但没有继承AgentRunningSubModule的类
|
|
||||||
checkSets(annotatedModules.subModuleTypes(), extendedModules.subModuleTypes(),
|
|
||||||
"存在被@AgentSubModule注解但未继承AgentRunningSubModule的类");
|
|
||||||
|
|
||||||
// 检查是否有继承AgentRunningSubModule但没有被@AgentSubModule注解的类
|
|
||||||
checkSets(extendedModules.subModuleTypes(), annotatedModules.subModuleTypes(),
|
|
||||||
"存在继承AgentRunningSubModule但未被@AgentSubModule注解的类");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查源集合中是否有不在目标集合中的元素
|
|
||||||
*
|
|
||||||
* @param source 源集合
|
|
||||||
* @param target 目标集合
|
|
||||||
* @param errorMessage 错误信息前缀
|
|
||||||
*/
|
|
||||||
private void checkSets(Set<Class<?>> source, Set<Class<?>> target, String errorMessage) {
|
|
||||||
// 只有在需要时才创建HashSet以节省内存
|
|
||||||
if (!target.containsAll(source)) {
|
|
||||||
// 使用流式处理找出差异部分,避免创建完整的中间集合
|
|
||||||
String classNames = source.stream()
|
|
||||||
.filter(clazz -> !target.contains(clazz))
|
|
||||||
.map(Class::getSimpleName)
|
|
||||||
.limit(10) // 限制显示数量,避免信息泄露
|
|
||||||
.collect(Collectors.joining(", ", "[", "]"));
|
|
||||||
|
|
||||||
throw new ModuleCheckException(errorMessage + ": " + classNames);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private record AnnotatedModules(Set<Class<?>> moduleTypes, Set<Class<?>> subModuleTypes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private record ExtendedModules(Set<Class<?>> moduleTypes, Set<Class<?>> subModuleTypes) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
package work.slhaf.partner.api.agent.factory.component;
|
|
||||||
|
|
||||||
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
|
|
||||||
import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.abstracts.AbstractAgentModule;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.annotation.InjectModule;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.exception.ModuleInstanceGenerateFailedException;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.exception.ModuleProxyGenerateFailedException;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.pojo.BaseMetaModule;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.pojo.MetaModule;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.pojo.MetaSubModule;
|
|
||||||
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 java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <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 final HashMap<Class<?>, Object> subModuleInstances = new HashMap<>();
|
|
||||||
private final HashMap<Class<?>, Object> moduleInstances = new HashMap<>();
|
|
||||||
private List<MetaModule> moduleList;
|
|
||||||
private List<MetaSubModule> subModuleList;
|
|
||||||
private HashMap<Class<?>, Object> capabilityHolderInstances;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setVariables(AgentRegisterContext context) {
|
|
||||||
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
|
||||||
CapabilityFactoryContext capabilityFactoryContext = context.getCapabilityFactoryContext();
|
|
||||||
moduleList = factoryContext.getAgentModuleList();
|
|
||||||
subModuleList = factoryContext.getAgentSubModuleList();
|
|
||||||
capabilityHolderInstances = capabilityFactoryContext.getCapabilityHolderInstances();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void run() {
|
|
||||||
createProxiedInstances();
|
|
||||||
// TODO 需要同样注入到 AgentStandaloneModule
|
|
||||||
injectSubModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void injectSubModule() {
|
|
||||||
for (MetaModule module : moduleList) {
|
|
||||||
//因为实际上ByteBuddy生成的是module.getClazz()的子类,所以应当使用getDeclaredFields()获取字段
|
|
||||||
Arrays.stream(module.getClazz().getDeclaredFields())
|
|
||||||
.filter(field -> field.isAnnotationPresent(InjectModule.class))
|
|
||||||
.forEach(field -> {
|
|
||||||
try {
|
|
||||||
field.setAccessible(true);
|
|
||||||
field.set(
|
|
||||||
moduleInstances.get(module.getClazz()),
|
|
||||||
subModuleInstances.get(field.getType())
|
|
||||||
);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new ModuleInstanceGenerateFailedException("模块实例注入失败", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createProxiedInstances() {
|
|
||||||
generateModuleProxy(moduleList, moduleInstances);
|
|
||||||
generateModuleProxy(subModuleList, subModuleInstances);
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void generateModuleProxy(List<? extends BaseMetaModule> list, HashMap<Class<?>, Object> instanceMap) {
|
|
||||||
for (BaseMetaModule module : list) {
|
|
||||||
try {
|
|
||||||
Class<? extends AbstractAgentModule> clazz = module.getClazz();
|
|
||||||
AbstractAgentModule instance = clazz.getConstructor().newInstance();
|
|
||||||
module.setInstance(instance);
|
|
||||||
instanceMap.put(module.getClazz(), instance);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ModuleProxyGenerateFailedException("模块Hook代理生成失败! 代理失败的模块名: " + module.getClazz().getSimpleName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
package work.slhaf.partner.api.agent.factory.component;
|
|
||||||
|
|
||||||
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.component.pojo.MetaModule;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.pojo.MetaSubModule;
|
|
||||||
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
|
|
||||||
import work.slhaf.partner.api.agent.factory.context.ModuleFactoryContext;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>Agent启动流程 2</h2>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 负责收集 {@link AgentRunningModule} 与 {@link AgentSubModule} 注解所在类的信息,供后续工厂完成动态代理、模块与能力注入
|
|
||||||
* <p/>
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li>
|
|
||||||
* <p>{@link ModuleRegisterFactory#setModuleList()}</p>
|
|
||||||
* 扫描 {@link AgentRunningModule} 注解,获取执行模块信息: 类型、模块名称({@link AgentRunningModule#name()}),执行顺序。并按照注解的 {@link AgentRunningModule#order()} 字段进行排序
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* <p>{@link ModuleRegisterFactory#setSubModuleList()}</p>
|
|
||||||
* 扫描 {@link AgentSubModule} 注册,获取子模块类型信息
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* 两种模块都将存入各自的list中,供后续模块完成注册与注入
|
|
||||||
* </li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* <p>下一步流程请参阅{@link ModuleProxyFactory}</p>
|
|
||||||
*/
|
|
||||||
public class ModuleRegisterFactory extends AgentBaseFactory {
|
|
||||||
|
|
||||||
private Reflections reflections;
|
|
||||||
private List<MetaModule> moduleList;
|
|
||||||
private List<MetaSubModule> subModuleList;
|
|
||||||
|
|
||||||
private static MetaModule getMetaModule(Class<? extends AbstractAgentRunningModule> clazz) {
|
|
||||||
MetaModule metaModule = new MetaModule();
|
|
||||||
AgentRunningModule agentRunningModule;
|
|
||||||
if (clazz.isAnnotationPresent(CoreModule.class)) {
|
|
||||||
agentRunningModule = CoreModule.class.getAnnotation(AgentRunningModule.class);
|
|
||||||
} else {
|
|
||||||
agentRunningModule = clazz.getAnnotation(AgentRunningModule.class);
|
|
||||||
}
|
|
||||||
metaModule.setName(agentRunningModule.name());
|
|
||||||
metaModule.setOrder(agentRunningModule.order());
|
|
||||||
metaModule.setClazz(clazz);
|
|
||||||
return metaModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setVariables(AgentRegisterContext context) {
|
|
||||||
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
|
||||||
reflections = context.getReflections();
|
|
||||||
moduleList = factoryContext.getAgentModuleList();
|
|
||||||
subModuleList = factoryContext.getAgentSubModuleList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void run() {
|
|
||||||
setModuleList();
|
|
||||||
setSubModuleList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSubModuleList() {
|
|
||||||
Set<Class<?>> subModules = reflections.getTypesAnnotatedWith(AgentSubModule.class);
|
|
||||||
for (Class<?> subModule : subModules) {
|
|
||||||
if (!ClassUtil.isNormalClass(subModule)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Class<? extends AbstractAgentSubModule> clazz = subModule.asSubclass(AbstractAgentSubModule.class);
|
|
||||||
MetaSubModule metaSubModule = new MetaSubModule();
|
|
||||||
metaSubModule.setClazz(clazz);
|
|
||||||
subModuleList.add(metaSubModule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setModuleList() {
|
|
||||||
//反射扫描获取@AgentModule所在类, 该部分为Agent流程执行模块
|
|
||||||
Set<Class<?>> modules = reflections.getTypesAnnotatedWith(AgentRunningModule.class);
|
|
||||||
for (Class<?> module : modules) {
|
|
||||||
if (!ClassUtil.isNormalClass(module)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Class<? extends AbstractAgentRunningModule> clazz = module.asSubclass(AbstractAgentRunningModule.class);
|
|
||||||
MetaModule metaModule = getMetaModule(clazz);
|
|
||||||
moduleList.add(metaModule);
|
|
||||||
}
|
|
||||||
moduleList.sort(Comparator.comparing(MetaModule::getOrder));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -38,14 +38,12 @@ object AgentContext {
|
|||||||
_capabilities[type] = value
|
_capabilities[type] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> addAdditionalComponent(type: Class<T>, value: T): Boolean {
|
fun addAdditionalComponent(instance: Any): Boolean {
|
||||||
|
val type = instance::class.java
|
||||||
if (type.isAnnotationPresent(AgentComponent::class.java)) {
|
if (type.isAnnotationPresent(AgentComponent::class.java)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (value == null) {
|
_additionalComponents.add(instance)
|
||||||
return false
|
|
||||||
}
|
|
||||||
_additionalComponents.add(value)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +62,7 @@ sealed class ModuleContextData<out T : AbstractAgentModule> {
|
|||||||
abstract val clazz: Class<out T>
|
abstract val clazz: Class<out T>
|
||||||
abstract val instance: T
|
abstract val instance: T
|
||||||
abstract val launchTime: ZonedDateTime
|
abstract val launchTime: ZonedDateTime
|
||||||
abstract val modelInfo: ModelInfo
|
abstract val modelInfo: ModelInfo?
|
||||||
|
|
||||||
val metadata = mutableMapOf<String, Any>()
|
val metadata = mutableMapOf<String, Any>()
|
||||||
|
|
||||||
@@ -72,7 +70,7 @@ sealed class ModuleContextData<out T : AbstractAgentModule> {
|
|||||||
override val clazz: Class<T>,
|
override val clazz: Class<T>,
|
||||||
override val instance: T,
|
override val instance: T,
|
||||||
override val launchTime: ZonedDateTime,
|
override val launchTime: ZonedDateTime,
|
||||||
override val modelInfo: ModelInfo,
|
override val modelInfo: ModelInfo?,
|
||||||
|
|
||||||
val order: Int,
|
val order: Int,
|
||||||
val enabled: Boolean
|
val enabled: Boolean
|
||||||
@@ -82,7 +80,7 @@ sealed class ModuleContextData<out T : AbstractAgentModule> {
|
|||||||
override val clazz: Class<T>,
|
override val clazz: Class<T>,
|
||||||
override val instance: T,
|
override val instance: T,
|
||||||
override val launchTime: ZonedDateTime,
|
override val launchTime: ZonedDateTime,
|
||||||
override val modelInfo: ModelInfo,
|
override val modelInfo: ModelInfo?,
|
||||||
|
|
||||||
val injectTarget: MutableSet<AbstractAgentModule> = mutableSetOf()
|
val injectTarget: MutableSet<AbstractAgentModule> = mutableSetOf()
|
||||||
) : ModuleContextData<T>()
|
) : ModuleContextData<T>()
|
||||||
@@ -91,7 +89,7 @@ sealed class ModuleContextData<out T : AbstractAgentModule> {
|
|||||||
override val clazz: Class<T>,
|
override val clazz: Class<T>,
|
||||||
override val instance: T,
|
override val instance: T,
|
||||||
override val launchTime: ZonedDateTime,
|
override val launchTime: ZonedDateTime,
|
||||||
override val modelInfo: ModelInfo,
|
override val modelInfo: ModelInfo?,
|
||||||
|
|
||||||
val injectTarget: MutableSet<AbstractAgentModule> = mutableSetOf()
|
val injectTarget: MutableSet<AbstractAgentModule> = mutableSetOf()
|
||||||
) : ModuleContextData<T>()
|
) : ModuleContextData<T>()
|
||||||
@@ -101,4 +99,4 @@ sealed class ModuleContextData<out T : AbstractAgentModule> {
|
|||||||
val model: String,
|
val model: String,
|
||||||
val basePrompt: JSONArray
|
val basePrompt: JSONArray
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user