refactor(action-core): migrate action modules to Result return flow and unify exception reporting

This commit is contained in:
2026-04-12 17:29:10 +08:00
parent 19f56d11f0
commit c14e6f84e7
9 changed files with 74 additions and 81 deletions

View File

@@ -10,6 +10,7 @@ import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCa
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule; import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule;
import work.slhaf.partner.framework.agent.model.ActivateModel; import work.slhaf.partner.framework.agent.model.ActivateModel;
import work.slhaf.partner.framework.agent.model.pojo.Message; import work.slhaf.partner.framework.agent.model.pojo.Message;
import work.slhaf.partner.framework.agent.support.Result;
import work.slhaf.partner.module.TaskBlock; import work.slhaf.partner.module.TaskBlock;
import work.slhaf.partner.module.action.executor.entity.CorrectionRecognizerInput; import work.slhaf.partner.module.action.executor.entity.CorrectionRecognizerInput;
import work.slhaf.partner.module.action.executor.entity.CorrectionRecognizerResult; import work.slhaf.partner.module.action.executor.entity.CorrectionRecognizerResult;
@@ -19,18 +20,18 @@ import java.util.List;
/** /**
* 负责在行动链执行过程中判断当前进度是否异常,是否需要引入 corrector 介入。 * 负责在行动链执行过程中判断当前进度是否异常,是否需要引入 corrector 介入。
*/ */
public class ActionCorrectionRecognizer extends AbstractAgentModule.Sub<CorrectionRecognizerInput, CorrectionRecognizerResult> implements ActivateModel { public class ActionCorrectionRecognizer extends AbstractAgentModule.Sub<CorrectionRecognizerInput, Result<CorrectionRecognizerResult>> implements ActivateModel {
@InjectCapability @InjectCapability
private CognitionCapability cognitionCapability; private CognitionCapability cognitionCapability;
@Override @Override
public CorrectionRecognizerResult execute(CorrectionRecognizerInput input) { public @NotNull Result<CorrectionRecognizerResult> execute(CorrectionRecognizerInput input) {
List<Message> messages = List.of( List<Message> messages = List.of(
resolveContextMessage(), resolveContextMessage(),
resolveTaskMessage(input) resolveTaskMessage(input)
); );
return formattedChat(messages, CorrectionRecognizerResult.class).getOrThrow(); return formattedChat(messages, CorrectionRecognizerResult.class);
} }
private Message resolveTaskMessage(CorrectionRecognizerInput input) { private Message resolveTaskMessage(CorrectionRecognizerInput input) {

View File

@@ -10,6 +10,7 @@ import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCa
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule; import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule;
import work.slhaf.partner.framework.agent.model.ActivateModel; import work.slhaf.partner.framework.agent.model.ActivateModel;
import work.slhaf.partner.framework.agent.model.pojo.Message; import work.slhaf.partner.framework.agent.model.pojo.Message;
import work.slhaf.partner.framework.agent.support.Result;
import work.slhaf.partner.module.TaskBlock; import work.slhaf.partner.module.TaskBlock;
import work.slhaf.partner.module.action.executor.entity.CorrectorInput; import work.slhaf.partner.module.action.executor.entity.CorrectorInput;
import work.slhaf.partner.module.action.executor.entity.CorrectorResult; import work.slhaf.partner.module.action.executor.entity.CorrectorResult;
@@ -19,18 +20,18 @@ import java.util.List;
/** /**
* 负责在单组行动执行后,根据行动意图与结果检查后续行动是否符合目的,必要时直接调整行动链,或发起自对话请求进行干预 * 负责在单组行动执行后,根据行动意图与结果检查后续行动是否符合目的,必要时直接调整行动链,或发起自对话请求进行干预
*/ */
public class ActionCorrector extends AbstractAgentModule.Sub<CorrectorInput, CorrectorResult> implements ActivateModel { public class ActionCorrector extends AbstractAgentModule.Sub<CorrectorInput, Result<CorrectorResult>> implements ActivateModel {
@InjectCapability @InjectCapability
private CognitionCapability cognitionCapability; private CognitionCapability cognitionCapability;
@Override @Override
public CorrectorResult execute(CorrectorInput input) { public @NotNull Result<CorrectorResult> execute(CorrectorInput input) {
List<Message> messages = List.of( List<Message> messages = List.of(
resolveContextMessage(), resolveContextMessage(),
resolveTaskMessage(input) resolveTaskMessage(input)
); );
return formattedChat(messages, CorrectorResult.class).getOrThrow(); return formattedChat(messages, CorrectorResult.class);
} }
private Message resolveTaskMessage(CorrectorInput input) { private Message resolveTaskMessage(CorrectorInput input) {

View File

@@ -21,6 +21,7 @@ import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ActionExecutor extends AbstractAgentModule.Standalone { public class ActionExecutor extends AbstractAgentModule.Standalone {
@@ -219,24 +220,22 @@ public class ActionExecutor extends AbstractAgentModule.Standalone {
boolean hasFailedMetaAction = hasFailedMetaAction(metaActions); boolean hasFailedMetaAction = hasFailedMetaAction(metaActions);
boolean shouldRunCorrector = hasFailedMetaAction; boolean shouldRunCorrector = hasFailedMetaAction;
try {
if (!shouldRunCorrector) { if (!shouldRunCorrector) {
val recognizerResult = resolveRecognizerResult(recognizerRecord); val recognizerResult = resolveRecognizerResult(recognizerRecord);
shouldRunCorrector = recognizerResult != null && recognizerResult.isNeedCorrection(); shouldRunCorrector = recognizerResult != null && recognizerResult.isNeedCorrection();
} }
if (shouldRunCorrector) { if (shouldRunCorrector) {
val correctorInput = assemblyHelper.buildCorrectorInput(executableAction); val correctorInput = assemblyHelper.buildCorrectorInput(executableAction);
val correctorResult = actionCorrector.execute(correctorInput); actionCorrector.execute(correctorInput)
.onFailure(ExceptionReporterHandler.INSTANCE::report)
.onSuccess(correctorResult -> {
actionCapability.handleInterventions(correctorResult.getMetaInterventionList(), executableAction); actionCapability.handleInterventions(correctorResult.getMetaInterventionList(), executableAction);
blockManager.emitActionCorrectionBlock( blockManager.emitActionCorrectionBlock(
executableAction, executableAction,
hasFailedMetaAction ? "has_failed_meta_action" : correctorResult.getCorrectionReason(), hasFailedMetaAction ? "has_failed_meta_action" : correctorResult.getCorrectionReason(),
correctorResult.getMetaInterventionList() correctorResult.getMetaInterventionList()
); );
});
}
} catch (Exception ignored) {
} }
// 第二次尝试进行阶段推进,本次负责补充上一次在不存在 stage时但 corrector 执行期间发生了 actionChain 的插入事件 // 第二次尝试进行阶段推进,本次负责补充上一次在不存在 stage时但 corrector 执行期间发生了 actionChain 的插入事件
// 如果第一次已经推进完毕,本次将会跳过 // 如果第一次已经推进完毕,本次将会跳过
@@ -305,7 +304,7 @@ public class ActionExecutor extends AbstractAgentModule.Standalone {
} }
private void executeMetaActionWithRetry(MetaAction metaAction, ExecutableAction actionData) { private void executeMetaActionWithRetry(MetaAction metaAction, ExecutableAction actionData) {
String failureReason = "参数提取失败"; AtomicReference<String> failureReason = new AtomicReference<>("参数提取失败");
val actionKey = metaAction.getKey(); val actionKey = metaAction.getKey();
for (int attempt = 1; attempt <= MAX_EXTRACTOR_ATTEMPTS; attempt++) { for (int attempt = 1; attempt <= MAX_EXTRACTOR_ATTEMPTS; attempt++) {
val result = metaAction.getResult(); val result = metaAction.getResult();
@@ -318,26 +317,30 @@ public class ActionExecutor extends AbstractAgentModule.Standalone {
.onFailure(ExceptionReporterHandler.INSTANCE::report); .onFailure(ExceptionReporterHandler.INSTANCE::report);
AgentRuntimeException exception = extractorInputResult.exceptionOrNull(); AgentRuntimeException exception = extractorInputResult.exceptionOrNull();
if (exception != null) { if (exception != null) {
failureReason = exception.getMessage(); failureReason.set(exception.getMessage());
break; break;
} }
ExtractorInput extractorInput = extractorInputResult.getOrThrow(); ExtractorInput extractorInput = extractorInputResult.getOrThrow();
ExtractorResult extractorResult = paramsExtractor.execute(extractorInput); Result<ExtractorResult> extractorResultWrapped = paramsExtractor.execute(extractorInput).onFailure(exp -> {
ExceptionReporterHandler.INSTANCE.report(exp);
if (extractorResult == null || !extractorResult.isOk()) { failureReason.set(exp.getLocalizedMessage());
failureReason = buildAttemptFailureReason("参数提取失败", null); });
if (extractorResultWrapped.exceptionOrNull() != null) {
continue; continue;
} }
if (extractorResult.getParams() != null) { ExtractorResult extractorResult = extractorResultWrapped.getOrThrow();
metaAction.getParams().putAll(extractorResult.getParams()); if (!extractorResult.isOk()) {
failureReason.set(buildAttemptFailureReason("参数提取失败", null));
continue;
} }
metaAction.getParams().putAll(extractorResult.getParams());
try { try {
runnerClient.submit(metaAction); runnerClient.submit(metaAction);
} catch (Exception e) { } catch (Exception e) {
failureReason = buildAttemptFailureReason("行动执行异常", e.getLocalizedMessage()); failureReason.set(buildAttemptFailureReason("行动执行异常", e.getLocalizedMessage()));
continue; continue;
} }
@@ -349,10 +352,10 @@ public class ActionExecutor extends AbstractAgentModule.Standalone {
return; return;
} }
failureReason = buildAttemptFailureReason("行动执行失败", result.getData()); failureReason.set(buildAttemptFailureReason("行动执行失败", result.getData()));
} }
metaAction.getResult().setStatus(MetaAction.Result.Status.FAILED); metaAction.getResult().setStatus(MetaAction.Result.Status.FAILED);
metaAction.getResult().setData(failureReason); metaAction.getResult().setData(failureReason.get());
} }
private RecognizerTaskRecord startRecognizerIfNeeded(ExecutableAction executableAction, Phaser phaser) { private RecognizerTaskRecord startRecognizerIfNeeded(ExecutableAction executableAction, Phaser phaser) {
@@ -369,7 +372,9 @@ public class ActionExecutor extends AbstractAgentModule.Standalone {
phaser.register(); phaser.register();
return () -> { return () -> {
try { try {
return actionCorrectionRecognizer.execute(input); return actionCorrectionRecognizer.execute(input)
.onFailure(ExceptionReporterHandler.INSTANCE::report)
.getOrDefault(new CorrectionRecognizerResult());
} finally { } finally {
phaser.arriveAndDeregister(); phaser.arriveAndDeregister();
} }

View File

@@ -16,34 +16,23 @@ import work.slhaf.partner.module.TaskBlock;
import work.slhaf.partner.module.action.executor.entity.ExtractorInput; import work.slhaf.partner.module.action.executor.entity.ExtractorInput;
import work.slhaf.partner.module.action.executor.entity.ExtractorResult; import work.slhaf.partner.module.action.executor.entity.ExtractorResult;
import java.util.HashMap;
import java.util.List; import java.util.List;
/** /**
* 负责依据输入内容进行行动单元的参数信息提取 * 负责依据输入内容进行行动单元的参数信息提取
*/ */
public class ParamsExtractor extends AbstractAgentModule.Sub<ExtractorInput, ExtractorResult> implements ActivateModel { public class ParamsExtractor extends AbstractAgentModule.Sub<ExtractorInput, Result<ExtractorResult>> implements ActivateModel {
@InjectCapability @InjectCapability
private CognitionCapability cognitionCapability; private CognitionCapability cognitionCapability;
@Override @Override
public ExtractorResult execute(ExtractorInput input) { public @NotNull Result<ExtractorResult> execute(ExtractorInput input) {
List<Message> messages = List.of( List<Message> messages = List.of(
resolveContextMessage(), resolveContextMessage(),
resolveTaskMessage(input) resolveTaskMessage(input)
); );
Result<ExtractorResult> result = formattedChat(messages, ExtractorResult.class); return formattedChat(messages, ExtractorResult.class);
return result.fold(
extractorResult -> extractorResult,
exception -> {
log.error("ParamsExtractor解析结果失败", exception);
ExtractorResult fallback = new ExtractorResult();
fallback.setOk(false);
fallback.setParams(new HashMap<>());
return fallback;
}
);
} }
private Message resolveTaskMessage(ExtractorInput input) { private Message resolveTaskMessage(ExtractorInput input) {

View File

@@ -4,6 +4,6 @@ import lombok.Data;
@Data @Data
public class CorrectionRecognizerResult { public class CorrectionRecognizerResult {
private boolean needCorrection; private boolean needCorrection = false;
private String reason; private String reason;
} }

View File

@@ -26,6 +26,7 @@ import work.slhaf.partner.module.action.planner.extractor.ActionExtractor;
import work.slhaf.partner.module.action.planner.extractor.entity.ExtractorResult; import work.slhaf.partner.module.action.planner.extractor.entity.ExtractorResult;
import work.slhaf.partner.module.action.scheduler.ActionScheduler; import work.slhaf.partner.module.action.scheduler.ActionScheduler;
import work.slhaf.partner.runtime.PartnerRunningFlowContext; import work.slhaf.partner.runtime.PartnerRunningFlowContext;
import work.slhaf.partner.runtime.exception.ContextExceptionReporter;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@@ -68,18 +69,21 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
@Override @Override
public void execute(@NotNull PartnerRunningFlowContext context) { public void execute(@NotNull PartnerRunningFlowContext context) {
try {
String input = context.getInput(); String input = context.getInput();
ExtractorResult extractorResult = actionExtractor.execute(input); Result<ExtractorResult> result = actionExtractor.execute(input)
.onFailure(exp -> {
ExceptionReporterHandler.INSTANCE.report(exp, ContextExceptionReporter.REPORTER_NAME);
});
if (result.exceptionOrNull() != null) {
return;
}
ExtractorResult extractorResult = result.getOrThrow();
List<String> tendencies = extractorResult.getTendencies(); List<String> tendencies = extractorResult.getTendencies();
if (tendencies.isEmpty()) { if (tendencies.isEmpty()) {
return; return;
} }
appendTendencyBlock(tendencies, input); appendTendencyBlock(tendencies, input);
evaluateTendency(context.getSource(), input, extractorResult); evaluateTendency(context.getSource(), input, extractorResult);
} catch (Exception e) {
log.error("执行异常", e);
}
} }
private void appendTendencyBlock(List<String> tendencies, String input) { private void appendTendencyBlock(List<String> tendencies, String input) {

View File

@@ -10,6 +10,7 @@ import work.slhaf.partner.core.cognition.BlockContent;
import work.slhaf.partner.core.cognition.CognitionCapability; import work.slhaf.partner.core.cognition.CognitionCapability;
import work.slhaf.partner.core.cognition.ContextBlock; import work.slhaf.partner.core.cognition.ContextBlock;
import work.slhaf.partner.core.cognition.ResolvedContext; import work.slhaf.partner.core.cognition.ResolvedContext;
import work.slhaf.partner.framework.agent.exception.ExceptionReporterHandler;
import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability; import work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule; import work.slhaf.partner.framework.agent.factory.component.abstracts.AbstractAgentModule;
import work.slhaf.partner.framework.agent.factory.component.annotation.Init; import work.slhaf.partner.framework.agent.factory.component.annotation.Init;
@@ -66,9 +67,7 @@ public class ActionEvaluator extends AbstractAgentModule.Sub<EvaluatorInput, Lis
messages, messages,
EvaluatorResult.class EvaluatorResult.class
); );
result result.onFailure(ExceptionReporterHandler.INSTANCE::report).onSuccess(evaluatorResult -> {
.onFailure(exception -> log.error("ActionEvaluator评估失败: {}", tendency, exception))
.onSuccess(evaluatorResult -> {
evaluatorResult.setTendency(tendency); evaluatorResult.setTendency(tendency);
synchronized (evaluatorResults) { synchronized (evaluatorResults) {
evaluatorResults.add(evaluatorResult); evaluatorResults.add(evaluatorResult);

View File

@@ -12,13 +12,13 @@ import work.slhaf.partner.module.action.planner.extractor.entity.ExtractorResult
import java.util.List; import java.util.List;
public class ActionExtractor extends AbstractAgentModule.Sub<String, ExtractorResult> implements ActivateModel { public class ActionExtractor extends AbstractAgentModule.Sub<String, Result<ExtractorResult>> implements ActivateModel {
@InjectCapability @InjectCapability
private CognitionCapability cognitionCapability; private CognitionCapability cognitionCapability;
@Override @Override
public ExtractorResult execute(String input) { public @NotNull Result<ExtractorResult> execute(String input) {
List<Message> messages = List.of( List<Message> messages = List.of(
cognitionCapability.contextWorkspace().resolve(List.of( cognitionCapability.contextWorkspace().resolve(List.of(
ContextBlock.VisibleDomain.COGNITION, ContextBlock.VisibleDomain.COGNITION,
@@ -26,14 +26,8 @@ public class ActionExtractor extends AbstractAgentModule.Sub<String, ExtractorRe
)).encodeToMessage(), )).encodeToMessage(),
new Message(Message.Character.USER, input) new Message(Message.Character.USER, input)
); );
Result<ExtractorResult> result = formattedChat(messages, ExtractorResult.class); return formattedChat(messages, ExtractorResult.class);
return result.fold(
extractorResult -> extractorResult,
exception -> {
log.error("提取信息出错", exception);
return new ExtractorResult();
}
);
} }
@NotNull @NotNull

View File

@@ -13,7 +13,7 @@ interface ActivateModel {
fun streamChat( fun streamChat(
messages: List<Message>, messages: List<Message>,
handler: StreamChatMessageConsumer handler: StreamChatMessageConsumer
): work.slhaf.partner.framework.agent.support.Result<Unit> { ): Result<Unit> {
return ModelRuntimeRegistry.resolveProvider(modelKey()).streamChat(mergeMessages(messages), handler) return ModelRuntimeRegistry.resolveProvider(modelKey()).streamChat(mergeMessages(messages), handler)
} }