完善配置加载逻辑.

- 在 AgentRegisterContext 中新增对应的配置字段,供后续与模块协同检验
- 调整 ActivateModel 接口中的 modelSettings 实现逻辑
- 可以通过 ConfigLoaderFactory 提供的静态方法设置所需的配置管理类,并提供加载逻辑实现
- 为 ModelConfigManager 提供了默认的实现,从运行目录下加载模型配置与模块对应的提示词
- 实现了 ModelConfigManager 中的初步检验,检测是否存在默认模型配置与基础提示词,以及是否存在多余的模型配置。
- 新增了两个实体类,对应从文件加载的原始配置、提示词数据。
This commit is contained in:
2025-08-02 23:04:15 +08:00
parent 64a7ed261e
commit 3c41abbba8
22 changed files with 257 additions and 125 deletions

View File

@@ -2,10 +2,10 @@ package work.slhaf.partner.api.factory;
import cn.hutool.core.bean.BeanUtil;
import work.slhaf.partner.api.entity.AgentContext;
import work.slhaf.partner.api.factory.config.ConfigLoaderFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import work.slhaf.partner.api.factory.capability.CapabilityCheckFactory;
import work.slhaf.partner.api.factory.capability.CapabilityRegisterFactory;
import work.slhaf.partner.api.factory.config.ConfigLoaderFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import work.slhaf.partner.api.factory.module.ModuleCheckFactory;
import work.slhaf.partner.api.factory.module.ModuleRegisterFactory;

View File

@@ -1,14 +1,14 @@
package work.slhaf.partner.api.factory.capability;
import org.reflections.Reflections;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import work.slhaf.partner.api.common.util.AgentUtil;
import work.slhaf.partner.api.factory.capability.annotation.*;
import work.slhaf.partner.api.factory.capability.exception.DuplicateCapabilityException;
import work.slhaf.partner.api.factory.capability.exception.UnMatchedCapabilityException;
import work.slhaf.partner.api.factory.capability.exception.UnMatchedCapabilityMethodException;
import work.slhaf.partner.api.factory.capability.exception.UnMatchedCoordinatedMethodException;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import java.lang.reflect.Method;
import java.util.*;

View File

@@ -1,12 +1,12 @@
package work.slhaf.partner.api.factory.capability;
import org.reflections.Reflections;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import work.slhaf.partner.api.factory.capability.annotation.Capability;
import work.slhaf.partner.api.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.factory.capability.annotation.ToCoordinated;
import work.slhaf.partner.api.factory.capability.exception.ProxySetFailedExceptionCapability;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

View File

@@ -1,12 +1,12 @@
package work.slhaf.partner.api.factory.capability;
import org.reflections.Reflections;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import work.slhaf.partner.api.factory.capability.annotation.*;
import work.slhaf.partner.api.factory.capability.exception.CapabilityFactoryExecuteFailedException;
import work.slhaf.partner.api.factory.capability.exception.CoreInstancesCreateFailedExceptionCapability;
import work.slhaf.partner.api.factory.capability.exception.DuplicateMethodException;
import work.slhaf.partner.api.factory.capability.exception.CapabilityFactoryExecuteFailedException;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

View File

@@ -1,22 +1,33 @@
package work.slhaf.partner.api.factory.config;
import lombok.Setter;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.factory.entity.AgentBaseFactory;
import work.slhaf.partner.api.factory.entity.AgentRegisterContext;
import java.util.HashMap;
import java.util.List;
public class ConfigLoaderFactory extends AgentBaseFactory {
@Setter
private static ModelConfigManager modelConfigManager = new DefaultModelConfigManager();
private HashMap<String, ModelConfig> modelConfigMap;
private HashMap<String, List<Message>> modelPromptMap;
@Override
protected void setVariables(AgentRegisterContext context) {
modelConfigMap = context.getModelConfigMap();
modelPromptMap = context.getModelPromptMap();
}
@Override
protected void run() {
//反射获取是否存在其他的ModelConfigFactory子类如果存在则不使用默认配置工厂
ModelConfigFactory factory;
if (){
}
factory.load();
modelConfigManager.load();
modelConfigManager.check();
modelConfigMap.putAll(modelConfigManager.getModelConfigMap());
modelPromptMap.putAll(modelConfigManager.getModelPromptMap());
}
}

View File

@@ -1,29 +0,0 @@
package work.slhaf.partner.api.factory.config;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import java.util.HashMap;
import java.util.List;
/**
* 默认配置工厂
* 将从当前运行目录的config文件夹下创建并读取配置
*/
public class DefaultModelConfigFactory extends ModelConfigFactory {
private static final String MODEL_CONFIG_DIR = "./config/model/";
private static final String PROMPT_CONFIG_DIR = "./config/prompt/";
@Override
protected HashMap<String, List<Message>> loadPrompt() {
return null;
}
@Override
protected HashMap<String, ModelConfig> loadConfig() {
return null;
}
}

View File

@@ -0,0 +1,70 @@
package work.slhaf.partner.api.factory.config;
import cn.hutool.json.JSONUtil;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.exception.ModelConfigDirNotExistException;
import work.slhaf.partner.api.factory.config.exception.ModelConfigNotExistException;
import work.slhaf.partner.api.factory.config.exception.ModelPromptDirNotExistException;
import work.slhaf.partner.api.factory.config.exception.ModelPromptNotExistException;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.factory.config.pojo.PrimaryModelConfig;
import work.slhaf.partner.api.factory.config.pojo.PrimaryModelPrompt;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
/**
* 默认配置工厂
* 将从当前运行目录的config文件夹下创建并读取配置
*/
public class DefaultModelConfigManager extends ModelConfigManager {
private static final String MODEL_CONFIG_DIR = "./config/model/";
private static final String PROMPT_CONFIG_DIR = "./config/prompt/";
@Override
protected HashMap<String, List<Message>> loadPrompt() {
File file = new File(PROMPT_CONFIG_DIR);
if (!file.exists() && !file.isDirectory()) {
throw new ModelPromptDirNotExistException("未找到提示词目录: " + PROMPT_CONFIG_DIR + " 请手动创建!");
}
File[] files = file.listFiles();
if (files == null || files.length == 0) {
throw new ModelPromptNotExistException("在目录 " + PROMPT_CONFIG_DIR + " 中未找到提示词配置!");
}
HashMap<String, List<Message>> promptMap = new HashMap<>();
for (File f : files) {
if (f.isDirectory()) {
continue;
}
PrimaryModelPrompt primaryModelPrompt = JSONUtil.readJSONObject(f, StandardCharsets.UTF_8).toBean(PrimaryModelPrompt.class);
promptMap.put(primaryModelPrompt.getKey(), primaryModelPrompt.getMessages());
}
return promptMap;
}
@Override
protected HashMap<String, ModelConfig> loadConfig() {
File file = new File(MODEL_CONFIG_DIR);
if (!file.exists() || !file.isDirectory()) {
throw new ModelConfigDirNotExistException("未找到配置目录: " + MODEL_CONFIG_DIR + " 请手动创建!");
}
File[] files = file.listFiles();
if (files == null || files.length == 0) {
throw new ModelConfigNotExistException("在目录" + MODEL_CONFIG_DIR + "中未找到配置文件!");
}
//遍历文件获取所有配置文件并返回
HashMap<String, ModelConfig> configMap = new HashMap<>();
for (File f : files) {
if (f.isDirectory()) {
continue;
}
PrimaryModelConfig primaryModelConfig = JSONUtil.readJSONObject(f, StandardCharsets.UTF_8).toBean(PrimaryModelConfig.class);
configMap.put(primaryModelConfig.getKey(), primaryModelConfig.getModelConfig());
}
return configMap;
}
}

View File

@@ -1,53 +0,0 @@
package work.slhaf.partner.api.factory.config;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.exception.UnExistModelConfigException;
import work.slhaf.partner.api.factory.config.exception.UnExistModelPromptException;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import java.util.HashMap;
import java.util.List;
public abstract class ModelConfigFactory {
public static ModelConfigFactory factory;
protected HashMap<String, ModelConfig> modelConfigMap;
protected HashMap<String, List<Message>> modelPromptMap;
public ModelConfigFactory() {
factory = this;
}
public void load() {
modelConfigMap = loadConfig();
modelPromptMap = loadPrompt();
}
protected abstract HashMap<String, List<Message>> loadPrompt();
protected abstract HashMap<String, ModelConfig> loadConfig();
public List<Message> loadModelPrompt(String modelKey){
if (!modelPromptMap.containsKey(modelKey)){
throw new UnExistModelPromptException("不存在的modelPrompt: "+modelKey);
}
return modelPromptMap.get(modelKey);
}
public ModelConfig loadModelConfig(String modelKey) {
if (!modelConfigMap.containsKey(modelKey)) {
throw new UnExistModelConfigException("不存在的modelKey: " + modelKey);
}
return modelConfigMap.get(modelKey);
}
public void updateModelConfig(String modelKey, ModelConfig config) {
if (!modelConfigMap.containsKey(modelKey)) {
throw new UnExistModelConfigException("不存在的modelKey: " + modelKey);
}
modelConfigMap.get(modelKey).setModel(config.getModel());
modelConfigMap.get(modelKey).setBaseUrl(config.getBaseUrl());
modelConfigMap.get(modelKey).setApikey(config.getApikey());
}
}

View File

@@ -0,0 +1,81 @@
package work.slhaf.partner.api.factory.config;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.exception.ModelConfigNotExistException;
import work.slhaf.partner.api.factory.config.exception.ModelPromptNotExistException;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Slf4j
public abstract class ModelConfigManager {
public static ModelConfigManager INSTANCE;
@Getter
protected HashMap<String, ModelConfig> modelConfigMap;
@Getter
protected HashMap<String, List<Message>> modelPromptMap;
protected ModelConfigManager() {
INSTANCE = this;
}
public void load() {
modelConfigMap = loadConfig();
modelPromptMap = loadPrompt();
}
protected abstract HashMap<String, List<Message>> loadPrompt();
protected abstract HashMap<String, ModelConfig> loadConfig();
/**
* 对模型Config与Prompt分别进行检验,除了都必须包含default外还需要确保数量、key一致毕竟是模型配置与提示词
*/
public void check(){
log.info("[ModelConfigManager]: 执行config与prompt检测...");
if (!modelConfigMap.containsKey("default")){
throw new ModelConfigNotExistException("缺少默认配置! 需确保存在一个模型配置的key为`default`");
}
if (!modelPromptMap.containsKey("basic")){
throw new ModelPromptNotExistException("缺少基础Prompt! 需要确保存在key为basic的Prompt文件它将与其他Prompt共同作用于模块节点。");
}
Set<String> configKeySet = new HashSet<>(modelConfigMap.keySet());
configKeySet.remove("default");
Set<String> promptKeySet = new HashSet<>(modelPromptMap.keySet());
promptKeySet.remove("basic");
if (!promptKeySet.containsAll(configKeySet)){
log.warn("存在未被提示词包含的模型配置,该配置将无法生效!");
}
log.info("[ModelConfigManager]: 检测完毕.");
}
public List<Message> loadModelPrompt(String modelKey){
if (!modelPromptMap.containsKey(modelKey)){
throw new ModelPromptNotExistException("不存在的modelPrompt: "+modelKey);
}
return modelPromptMap.get(modelKey);
}
public ModelConfig loadModelConfig(String modelKey) {
if (!modelConfigMap.containsKey(modelKey)) {
throw new ModelConfigNotExistException("不存在的modelKey: " + modelKey);
}
return modelConfigMap.get(modelKey);
}
public void updateModelConfig(String modelKey, ModelConfig config) {
if (!modelConfigMap.containsKey(modelKey)) {
throw new ModelConfigNotExistException("不存在的modelKey: " + modelKey);
}
modelConfigMap.get(modelKey).setModel(config.getModel());
modelConfigMap.get(modelKey).setBaseUrl(config.getBaseUrl());
modelConfigMap.get(modelKey).setApikey(config.getApikey());
}
}

View File

@@ -0,0 +1,11 @@
package work.slhaf.partner.api.factory.config.exception;
public class ModelConfigDirNotExistException extends ModelConfigFactoryFailedException{
public ModelConfigDirNotExistException(String message, Throwable cause) {
super(message, cause);
}
public ModelConfigDirNotExistException(String message) {
super(message);
}
}

View File

@@ -2,10 +2,10 @@ package work.slhaf.partner.api.factory.config.exception;
public class ModelConfigFactoryFailedException extends RuntimeException {
public ModelConfigFactoryFailedException(String message, Throwable cause) {
super("ModelConfigFactory 执行失败: " + message, cause);
super("ModelConfigManager 执行失败: " + message, cause);
}
public ModelConfigFactoryFailedException(String message) {
super("ModelConfigFactory 执行失败: " + message);
super("ModelConfigManager 执行失败: " + message);
}
}

View File

@@ -0,0 +1,11 @@
package work.slhaf.partner.api.factory.config.exception;
public class ModelConfigNotExistException extends ModelConfigFactoryFailedException {
public ModelConfigNotExistException(String message, Throwable e) {
super(message, e);
}
public ModelConfigNotExistException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,11 @@
package work.slhaf.partner.api.factory.config.exception;
public class ModelPromptDirNotExistException extends ModelConfigFactoryFailedException{
public ModelPromptDirNotExistException(String message, Throwable cause) {
super(message, cause);
}
public ModelPromptDirNotExistException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,11 @@
package work.slhaf.partner.api.factory.config.exception;
public class ModelPromptNotExistException extends ModelConfigFactoryFailedException{
public ModelPromptNotExistException(String message) {
super(message);
}
public ModelPromptNotExistException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.factory.config.exception;
public class UnExistModelConfigException extends ModelConfigFactoryFailedException {
public UnExistModelConfigException(String message, Throwable e) {
super(message, e);
}
public UnExistModelConfigException(String message) {
super(message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.factory.config.exception;
public class UnExistModelPromptException extends ModelConfigFactoryFailedException{
public UnExistModelPromptException(String message) {
super(message);
}
public UnExistModelPromptException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,9 @@
package work.slhaf.partner.api.factory.config.pojo;
import lombok.Data;
@Data
public class PrimaryModelConfig {
private String key;
private ModelConfig modelConfig;
}

View File

@@ -0,0 +1,12 @@
package work.slhaf.partner.api.factory.config.pojo;
import lombok.Data;
import work.slhaf.partner.api.common.chat.pojo.Message;
import java.util.List;
@Data
public class PrimaryModelPrompt {
private String key;
private List<Message> messages;
}

View File

@@ -2,8 +2,11 @@ package work.slhaf.partner.api.factory.entity;
import lombok.Data;
import org.reflections.Reflections;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
@@ -16,6 +19,8 @@ public class AgentRegisterContext {
private final HashMap<Class<?>, Object> capabilityHolderInstances = new HashMap<>();
private Set<Class<?>> cores;
private Set<Class<?>> capabilities;
private HashMap<String, List<Message>> modelPromptMap = new HashMap<>();
private HashMap<String, ModelConfig> modelConfigMap = new HashMap<>();
public AgentRegisterContext(String path) {
reflections = new Reflections(path);

View File

@@ -13,5 +13,6 @@ public class ModuleCheckFactory extends AgentBaseFactory {
protected void run() {
//检查注解AgentModule所在类是否继承了AgentInteractionModule
//检查hook注解所在方法是否位于AgentInteractionModule子类/AgentInteractionSubModule子类/ActivateModel子类
//检查当前加载的模块数量、名称与prompt是否一致
}
}

View File

@@ -1,7 +1,10 @@
package work.slhaf.partner.api.factory.module.annotation;
import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用于注解执行模块

View File

@@ -5,7 +5,7 @@ import work.slhaf.partner.api.common.chat.Model;
import work.slhaf.partner.api.common.chat.constant.ChatConstant;
import work.slhaf.partner.api.common.chat.pojo.ChatResponse;
import work.slhaf.partner.api.common.chat.pojo.Message;
import work.slhaf.partner.api.factory.config.ModelConfigFactory;
import work.slhaf.partner.api.factory.config.ModelConfigManager;
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.factory.module.annotation.Before;
@@ -17,7 +17,7 @@ public interface ActivateModel {
@Before
default void modelSettings() {
Model model = new Model();
ModelConfig modelConfig = ModelConfigFactory.factory.loadModelConfig(modelKey());
ModelConfig modelConfig = ModelConfigManager.INSTANCE.loadModelConfig(modelKey());
model.setBaseMessages(withBasicPrompt() ? loadSpecificPromptAndBasicPrompt(modelKey(), promptModule()) : loadSpecificPrompt(modelKey(), promptModule()));
model.setChatClient(new ChatClient(modelConfig.getBaseUrl(), modelConfig.getApikey(), modelConfig.getModel()));
}