Partner 主体与框架适配完成! 完整逻辑已达到适配框架之前的完成度。发现并修复了不少问题,以及更新了README

框架:
- 由于`Gateway`的启动属于`Agent`启动流程的子线程,而主线程可能由于逻辑执行结束时机早于`Gateway`创建完成时机而报错,故引入`CountDownLatch`进行阻塞
- 在`AgentRunningModule`与`AgentRunningSubModule`中添加日志hook,记录模块执行的起始与截止时机
- 修复了`AgentUtil`中收集继承链时遗忘起始类的错误
- 在`CapabilityCheckFactory`中针对`CoordinateManager`无参构造方法的实现检验
- 在`CapabilityRegisterFactory`中添加了收集模块之外的CapabilityHolder的逻辑,与`@InjectCapability`的校验与注入逻辑保持一致
- 修复了‘生成模块启用配置时,多余局部变量导致无法执行流正确读取启用情况’的错误
- 在GlobalExceptionHandler中添加了对于未知异常的处理逻辑,确保不会导致程序异常终止
- 发现`ModuleProxyFactory`中使用`record`类型会导致`ByteBuddy`无法正确创建代理类,已修复,替换成普通类

本体:
- `ActiveData`由于`CognationCore`的引用,也需要实现序列化,已修复
- 修复了`MemorySelectExtractor`中由于匹配到的主题列表为空导致的空指针异常
- 将后置模块的trigger判定抽取到新的父类中,统一判断
- 修复了`WebSocketServer`如果存在过ws连接,关闭后短时间再次启动内仍提示端口占用的情况,设置允许端口重用
- 在`WebSocketGateway`新增了断开ws客户端连接的逻辑
This commit is contained in:
2025-09-30 15:46:05 +08:00
parent a7d54349e4
commit 941943f696
32 changed files with 271 additions and 105 deletions

View File

@@ -56,6 +56,7 @@ public class CognationCore extends PersistableObject {
} else {
FileUtils.createParentDirectories(filePath.toFile().getParentFile());
connectCores(this);
this.activeData = new ActiveData();
this.serialize();
}
setupHook(this);

View File

@@ -1,14 +1,21 @@
package work.slhaf.partner.core.cognation.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.partner.api.common.entity.PersistableObject;
import work.slhaf.partner.core.submodule.memory.pojo.EvaluatedSlice;
import java.io.Serial;
import java.util.HashMap;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class ActiveData {
private HashMap<String, List<EvaluatedSlice>> activatedSlices;
public class ActiveData extends PersistableObject {
private HashMap<String, List<EvaluatedSlice>> activatedSlices = new HashMap<>();
@Serial
private static final long serialVersionUID = 1L;
public void updateActivatedSlices(String userId, List<EvaluatedSlice> memorySlices) {
activatedSlices.put(userId, memorySlices);

View File

@@ -1,7 +0,0 @@
package work.slhaf.partner.module.common.module;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
public abstract class CoreRunningModule extends AgentRunningModule<PartnerRunningFlowContext> {
}

View File

@@ -3,5 +3,19 @@ package work.slhaf.partner.module.common.module;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import java.io.IOException;
public abstract class PostRunningModule extends AgentRunningModule<PartnerRunningFlowContext> {
@Override
public final void execute(PartnerRunningFlowContext context) throws IOException, ClassNotFoundException {
boolean trigger = context.getModuleContext().getExtraContext().getBoolean("post_process_trigger");
if (!trigger){
return;
}
doExecute(context);
}
protected void doExecute(PartnerRunningFlowContext context){}
}

View File

@@ -1,7 +1,6 @@
package work.slhaf.partner.module.common.module;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.module.common.entity.AppendPromptData;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
@@ -32,11 +31,9 @@ public abstract class PreRunningModule extends AgentRunningModule<PartnerRunning
@Override
public final void execute(PartnerRunningFlowContext context) throws IOException, ClassNotFoundException {
log.debug("[{}] 模块执行开始...", this.getClass().getAnnotation(AgentModule.class).name());
doExecute(context); // 子类实现差异化逻辑
setAppendedPrompt(context); // 通用逻辑
setActiveModule(context); // 通用逻辑
log.debug("[{}] 模块执行结束...", this.getClass().getAnnotation(AgentModule.class).name());
}
protected abstract void doExecute(PartnerRunningFlowContext context) throws IOException, ClassNotFoundException;

View File

@@ -8,6 +8,7 @@ import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapabili
import work.slhaf.partner.api.agent.factory.module.annotation.CoreModule;
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.AgentRunningModule;
import work.slhaf.partner.api.chat.constant.ChatConstant;
import work.slhaf.partner.api.chat.pojo.ChatResponse;
import work.slhaf.partner.api.chat.pojo.Message;
@@ -15,7 +16,6 @@ import work.slhaf.partner.api.chat.pojo.MetaMessage;
import work.slhaf.partner.core.cognation.CognationCapability;
import work.slhaf.partner.module.common.entity.AppendPromptData;
import work.slhaf.partner.module.common.model.ModelConstant;
import work.slhaf.partner.module.common.module.CoreRunningModule;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import work.slhaf.partner.runtime.session.SessionManager;
@@ -30,7 +30,7 @@ import static work.slhaf.partner.common.util.ExtractUtil.extractJson;
@Data
@Slf4j
@CoreModule
public class CoreModel extends CoreRunningModule implements ActivateModel {
public class CoreModel extends AgentRunningModule<PartnerRunningFlowContext> implements ActivateModel {
@InjectCapability
private CognationCapability cognationCapability;

View File

@@ -5,7 +5,6 @@ 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.AfterExecute;
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;
@@ -59,6 +58,7 @@ public class MemorySelector extends PreRunningModule {
List<EvaluatedSlice> evaluatedSlices = selectAndEvaluateMemory(runningFlowContext, extractorResult);
cognationCapability.updateActivatedSlices(userId, evaluatedSlices);
}
setModuleContextRecall(runningFlowContext);
}
private List<EvaluatedSlice> selectAndEvaluateMemory(PartnerRunningFlowContext runningFlowContext, ExtractorResult extractorResult) throws IOException, ClassNotFoundException {
@@ -79,7 +79,6 @@ public class MemorySelector extends PreRunningModule {
return memorySlices;
}
@AfterExecute(order = 1)
private void setModuleContextRecall(PartnerRunningFlowContext runningFlowContext) {
String userId = runningFlowContext.getUserId();
boolean recall = cognationCapability.hasActivatedSlices(userId);

View File

@@ -94,6 +94,9 @@ public class MemorySelectExtractor extends AgentRunningSubModule<PartnerRunningF
}
m.setText(fixTopicPath(m.getText()));
});
if (extractorResult.getMatches().isEmpty()) {
return extractorResult;
}
extractorResult.getMatches().removeIf(m -> m.getText().split("->")[0].isEmpty());
return extractorResult;
}

View File

@@ -96,7 +96,7 @@ public class MemoryUpdater extends PostRunningModule {
}
@Override
public void execute(PartnerRunningFlowContext context) {
public void doExecute(PartnerRunningFlowContext context) {
if (context.isFinished()) {
log.warn("[MemoryUpdater] 流程强制结束, 不触发记忆被动更新机制");
return;

View File

@@ -7,17 +7,16 @@ import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapabili
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.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.common.thread.InteractionThreadPoolExecutor;
import work.slhaf.partner.core.cognation.CognationCapability;
import work.slhaf.partner.core.submodule.perceive.PerceiveCapability;
import work.slhaf.partner.core.submodule.perceive.pojo.User;
import work.slhaf.partner.module.common.module.PostRunningModule;
import work.slhaf.partner.module.modules.perceive.updater.relation_extractor.RelationExtractor;
import work.slhaf.partner.module.modules.perceive.updater.relation_extractor.pojo.RelationExtractResult;
import work.slhaf.partner.module.modules.perceive.updater.static_extractor.StaticMemoryExtractor;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -31,7 +30,7 @@ import java.util.concurrent.locks.ReentrantLock;
@Slf4j
@Data
@AgentModule(name = "perceive_updater", order = 8)
public class PerceiveUpdater extends AgentRunningModule<PartnerRunningFlowContext> {
public class PerceiveUpdater extends PostRunningModule {
private static volatile PerceiveUpdater perceiveUpdater;
@@ -53,12 +52,9 @@ public class PerceiveUpdater extends AgentRunningModule<PartnerRunningFlowContex
this.executor = InteractionThreadPoolExecutor.getInstance();
}
public void execute(PartnerRunningFlowContext context) throws IOException, ClassNotFoundException {
@Override
public void doExecute(PartnerRunningFlowContext context) {
executor.execute(() -> {
boolean trigger = context.getModuleContext().getExtraContext().getBoolean("perceive_updater");
if (!trigger){
return;
}
ReentrantLock userLock = new ReentrantLock();
User user = new User();
user.setUuid(context.getUserId());

View File

@@ -5,8 +5,8 @@ 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.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.core.cognation.CognationCapability;
import work.slhaf.partner.module.common.module.PostRunningModule;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import java.io.IOException;
@@ -15,7 +15,7 @@ import java.io.IOException;
@Slf4j
@Data
@AgentModule(name = "postprocess_executor", order = 6)
public class PostprocessExecutor extends PostRunningModule {
public class PostprocessExecutor extends AgentRunningModule<PartnerRunningFlowContext> {
private static final int POST_PROCESS_TRIGGER_ROLL_LIMIT = 36;

View File

@@ -1,9 +1,10 @@
package work.slhaf.partner.module.modules.process;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityHolder;
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.core.cognation.CognationCapability;
import work.slhaf.partner.core.submodule.perceive.PerceiveCapability;
@@ -17,9 +18,10 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
@CapabilityHolder
@AgentModule(name = "preprocess_executor", order = 1)
public class PreprocessExecutor extends PreRunningModule {
private static volatile PreprocessExecutor preprocessExecutor;

View File

@@ -38,6 +38,7 @@ public class WebSocketGateway extends WebSocketServer implements AgentGateway<Pa
private WebSocketGateway(int port) {
super(new InetSocketAddress(port));
this.setReuseAddr(true);
this.executor = InteractionThreadPoolExecutor.getInstance();
}
@@ -101,15 +102,29 @@ public class WebSocketGateway extends WebSocketServer implements AgentGateway<Pa
}
private void setShutDownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
//关闭WebSocketServer
this.stop();
log.info("WebSocketServer 已关闭");
} catch (Exception e) {
log.error("WebSocketServer关闭失败: ", e);
}
}));
try {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
// 先断开所有客户端连接
for (WebSocket webSocket : getConnections()) {
try {
webSocket.close(1001, "Server shutting down");
} catch (Exception e) {
log.warn("关闭客户端连接时出错: ", e);
}
}
//关闭WebSocketServer给10秒超时时间确保连接正确关闭
this.stop(10000);
log.info("WebSocketServer 已关闭");
} catch (IllegalStateException e) {
log.warn("无法添加关闭钩子JVM可能已在关闭过程中: ", e);
} catch (Exception e) {
log.error("WebSocketServer关闭失败: ", e);
}
}));
} catch (IllegalStateException e) {
log.warn("无法添加关闭钩子JVM可能已在关闭过程中: ", e);
}
}
@Override