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

View File

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

View File

@@ -4,6 +4,6 @@ import lombok.Data;
@Data
public class CorrectionRecognizerResult {
private boolean needCorrection;
private boolean needCorrection = false;
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.scheduler.ActionScheduler;
import work.slhaf.partner.runtime.PartnerRunningFlowContext;
import work.slhaf.partner.runtime.exception.ContextExceptionReporter;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -68,18 +69,21 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
@Override
public void execute(@NotNull PartnerRunningFlowContext context) {
try {
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();
if (tendencies.isEmpty()) {
return;
}
appendTendencyBlock(tendencies, input);
evaluateTendency(context.getSource(), input, extractorResult);
} catch (Exception e) {
log.error("执行异常", e);
}
}
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.ContextBlock;
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.component.abstracts.AbstractAgentModule;
import work.slhaf.partner.framework.agent.factory.component.annotation.Init;
@@ -66,9 +67,7 @@ public class ActionEvaluator extends AbstractAgentModule.Sub<EvaluatorInput, Lis
messages,
EvaluatorResult.class
);
result
.onFailure(exception -> log.error("ActionEvaluator评估失败: {}", tendency, exception))
.onSuccess(evaluatorResult -> {
result.onFailure(ExceptionReporterHandler.INSTANCE::report).onSuccess(evaluatorResult -> {
evaluatorResult.setTendency(tendency);
synchronized (evaluatorResults) {
evaluatorResults.add(evaluatorResult);

View File

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

View File

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