mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
refactor(executor): remove legacy ActionRepairer、DynamicActionGenerator and related data class
This commit is contained in:
@@ -1,211 +0,0 @@
|
|||||||
package work.slhaf.partner.module.modules.action.executor;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.alibaba.fastjson2.TypeReference;
|
|
||||||
import lombok.Data;
|
|
||||||
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
|
|
||||||
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.Init;
|
|
||||||
import work.slhaf.partner.api.agent.factory.component.annotation.InjectModule;
|
|
||||||
import work.slhaf.partner.api.chat.pojo.Message;
|
|
||||||
import work.slhaf.partner.core.action.ActionCapability;
|
|
||||||
import work.slhaf.partner.core.action.ActionCore.ExecutorType;
|
|
||||||
import work.slhaf.partner.core.action.entity.MetaAction;
|
|
||||||
import work.slhaf.partner.core.action.entity.MetaAction.Result;
|
|
||||||
import work.slhaf.partner.core.action.runner.RunnerClient;
|
|
||||||
import work.slhaf.partner.core.cognition.CognitionCapability;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.GeneratorInput;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.GeneratorResult;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.RepairerInput;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.RepairerResult;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.RepairerResult.RepairerStatus;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 负责识别行动链的修复
|
|
||||||
* <ol>
|
|
||||||
* <li>
|
|
||||||
* 可通过协调 {@link DynamicActionGenerator} 生成新的行动单元并调用,获取所需的参数信息(必要时持久化);
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* 也可以直接调用已存在的行动程序获取信息;
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* 如果上述都无法满足,将发起自对话借助干预模块进行操作或者借助自对话通道向用户发起沟通请求,该请求的目的一般为行动程序生成/调用指导或者用户侧的信息补充,后续还需要再走一遍参数修复流程
|
|
||||||
* </li>
|
|
||||||
* </ol>
|
|
||||||
*/
|
|
||||||
public class ActionRepairer extends AbstractAgentModule.Sub<RepairerInput, RepairerResult> implements ActivateModel {
|
|
||||||
private final AssemblyHelper assemblyHelper = new AssemblyHelper();
|
|
||||||
@InjectCapability
|
|
||||||
private ActionCapability actionCapability;
|
|
||||||
@InjectCapability
|
|
||||||
private CognitionCapability cognitionCapability;
|
|
||||||
@InjectModule
|
|
||||||
private DynamicActionGenerator dynamicActionGenerator;
|
|
||||||
private RunnerClient runnerClient;
|
|
||||||
|
|
||||||
@Init
|
|
||||||
void init() {
|
|
||||||
runnerClient = actionCapability.runnerClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RepairerResult execute(RepairerInput data) {
|
|
||||||
RepairerResult result;
|
|
||||||
try {
|
|
||||||
String prompt = assemblyHelper.buildPrompt(data, null);
|
|
||||||
RepairerData repairerData = formattedChat(
|
|
||||||
List.of(new Message(Message.Character.USER, prompt)),
|
|
||||||
RepairerData.class
|
|
||||||
);
|
|
||||||
result = switch (repairerData.getRepairerType()) {
|
|
||||||
case ACTION_GENERATION ->
|
|
||||||
handleActionGeneration(JSONObject.parseObject(repairerData.getData(), GeneratorInput.class));
|
|
||||||
case ACTION_INVOCATION -> handleActionInvocation(
|
|
||||||
JSONObject.parseObject(repairerData.getData(), new TypeReference<List<String>>() {
|
|
||||||
}));
|
|
||||||
case USER_INTERACTION -> handleUserInteraction(repairerData.getData());
|
|
||||||
};
|
|
||||||
if (!repairerData.getRepairerType().equals(RepairerType.USER_INTERACTION)
|
|
||||||
&& result.getStatus().equals(RepairerResult.RepairerStatus.FAILED)) {
|
|
||||||
log.warn("常规行动修复失败,将尝试自对话通道");
|
|
||||||
prompt = assemblyHelper.buildPrompt(data, "常规行动修复失败,请尝试通过自对话通道获取必要的信息以完成行动参数的修复");
|
|
||||||
repairerData = formattedChat(
|
|
||||||
List.of(new Message(Message.Character.USER, prompt)),
|
|
||||||
RepairerData.class
|
|
||||||
);
|
|
||||||
handleUserInteraction(repairerData.getData());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
result = new RepairerResult();
|
|
||||||
result.setStatus(RepairerStatus.FAILED);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 负责根据输入内容进行行动单元的参数信息修复
|
|
||||||
*
|
|
||||||
* @param generatorInput 生成的行动单元参考内容,最好包含行动单元的执行逻辑
|
|
||||||
* @return 修复后的行动单元结果
|
|
||||||
*/
|
|
||||||
private RepairerResult handleActionGeneration(GeneratorInput generatorInput) {
|
|
||||||
RepairerResult result = new RepairerResult();
|
|
||||||
GeneratorResult generatorResult = dynamicActionGenerator.execute(generatorInput);
|
|
||||||
MetaAction tempAction = generatorResult.getTempAction();
|
|
||||||
if (tempAction == null) {
|
|
||||||
result.setStatus(RepairerStatus.FAILED);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
runnerClient.submit(tempAction);
|
|
||||||
// 根据 tempAction 的执行状态设置修复结果
|
|
||||||
Result actionResult = tempAction.getResult();
|
|
||||||
if (actionResult.getStatus() != MetaAction.Result.Status.SUCCESS) {
|
|
||||||
result.setStatus(RepairerStatus.FAILED);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.setStatus(RepairerStatus.OK);
|
|
||||||
result.getFixedData().add(actionResult.getData());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 负责根据输入内容进行行动单元的参数信息修复
|
|
||||||
*
|
|
||||||
* @param actionKeys 需要调用的行动单元Key列表
|
|
||||||
* @return 修复后的行动单元结果
|
|
||||||
*/
|
|
||||||
private RepairerResult handleActionInvocation(List<String> actionKeys) {
|
|
||||||
RepairerResult result = new RepairerResult();
|
|
||||||
CountDownLatch latch = new CountDownLatch(actionKeys.size());
|
|
||||||
ExecutorService virtual = actionCapability.getExecutor(ExecutorType.VIRTUAL);
|
|
||||||
ExecutorService platform = actionCapability.getExecutor(ExecutorType.PLATFORM);
|
|
||||||
ExecutorService executor;
|
|
||||||
AtomicInteger failedCount = new AtomicInteger(0);
|
|
||||||
for (String key : actionKeys) {
|
|
||||||
MetaAction action = actionCapability.loadMetaAction(key);
|
|
||||||
executor = action.getIo() ? virtual : platform;
|
|
||||||
executor.execute(() -> {
|
|
||||||
try {
|
|
||||||
runnerClient.submit(action);
|
|
||||||
result.getFixedData().add(action.getResult().getData());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("行动单元执行失败: {}", key, e);
|
|
||||||
failedCount.incrementAndGet();
|
|
||||||
} finally {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("CountDownLatch 已中断");
|
|
||||||
}
|
|
||||||
if (actionKeys.size() - failedCount.get() > 0) {
|
|
||||||
result.setStatus(RepairerStatus.OK);
|
|
||||||
} else {
|
|
||||||
result.setStatus(RepairerStatus.FAILED);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RepairerResult handleUserInteraction(String acquireContent) {
|
|
||||||
RepairerResult result = new RepairerResult();
|
|
||||||
result.setStatus(RepairerStatus.ACQUIRE);
|
|
||||||
// 发送自对话请求
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String modelKey() {
|
|
||||||
return "action_repairer";
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum RepairerType {
|
|
||||||
ACTION_GENERATION,
|
|
||||||
ACTION_INVOCATION,
|
|
||||||
USER_INTERACTION
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
private static class RepairerData {
|
|
||||||
private RepairerType repairerType;
|
|
||||||
private String data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("InnerClassMayBeStatic")
|
|
||||||
private class AssemblyHelper {
|
|
||||||
private AssemblyHelper() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildPrompt(RepairerInput data, String specialInstruction) {
|
|
||||||
JSONObject prompt = new JSONObject();
|
|
||||||
JSONObject actionData = prompt.putObject("[本次行动信息]");
|
|
||||||
actionData.put("[行动描述]", data.getActionDescription());
|
|
||||||
JSONObject actionParamsData = actionData.putObject("[行动参数说明]");
|
|
||||||
actionParamsData.putAll(data.getParams());
|
|
||||||
JSONArray historyData = prompt.putArray("[历史行动执行结果]");
|
|
||||||
data.getHistoryActionResults().forEach(historyAction -> {
|
|
||||||
JSONObject historyItem = new JSONObject();
|
|
||||||
historyItem.put("[行动Key]", historyAction.actionKey());
|
|
||||||
historyItem.put("[行动描述]", historyAction.description());
|
|
||||||
historyItem.put("[行动结果]", historyAction.result());
|
|
||||||
historyData.add(historyItem);
|
|
||||||
});
|
|
||||||
JSONArray messageData = prompt.putArray("[最近消息列表]");
|
|
||||||
messageData.addAll(data.getRecentMessages());
|
|
||||||
if (specialInstruction != null) {
|
|
||||||
prompt.put("[特殊指令]", specialInstruction);
|
|
||||||
}
|
|
||||||
return prompt.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package work.slhaf.partner.module.modules.action.executor;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import lombok.val;
|
|
||||||
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
|
|
||||||
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.Init;
|
|
||||||
import work.slhaf.partner.api.chat.pojo.Message;
|
|
||||||
import work.slhaf.partner.core.action.ActionCapability;
|
|
||||||
import work.slhaf.partner.core.action.entity.GeneratedData;
|
|
||||||
import work.slhaf.partner.core.action.entity.MetaAction;
|
|
||||||
import work.slhaf.partner.core.action.runner.RunnerClient;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.GeneratorInput;
|
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.GeneratorResult;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 负责依据输入内容生成可执行的动态行动单元,并选择是否持久化至 SandboxRunner 容器内
|
|
||||||
*/
|
|
||||||
public class DynamicActionGenerator extends AbstractAgentModule.Sub<GeneratorInput, GeneratorResult>
|
|
||||||
implements ActivateModel {
|
|
||||||
@InjectCapability
|
|
||||||
private ActionCapability actionCapability;
|
|
||||||
private RunnerClient runnerClient;
|
|
||||||
|
|
||||||
@Init
|
|
||||||
void init() {
|
|
||||||
runnerClient = actionCapability.runnerClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GeneratorResult execute(GeneratorInput input) {
|
|
||||||
GeneratorResult result = new GeneratorResult();
|
|
||||||
try {
|
|
||||||
// 由于 SCRIPT 类型程序都是在 SandboxRunner 内部的磁盘上加载然后执行的,
|
|
||||||
// 所以此处的输入内容也只需要指定输入参数、临时key、是否持久化即可,路径将按照指定规则统一构建,不可交给LLM生成
|
|
||||||
String prompt = buildPrompt(input);
|
|
||||||
// 响应结果需要包含几个特殊数据: 依赖项、代码内容、是否序列化、响应数据释义
|
|
||||||
GeneratedData generatorData = formattedChat(
|
|
||||||
List.of(new Message(Message.Character.USER, prompt)),
|
|
||||||
GeneratedData.class
|
|
||||||
);
|
|
||||||
val location = runnerClient.buildTmpPath(input.getActionName(), generatorData.getCodeType());
|
|
||||||
MetaAction tempAction = new MetaAction(
|
|
||||||
input.getActionName(),
|
|
||||||
true,
|
|
||||||
generatorData.getLauncher(),
|
|
||||||
MetaAction.Type.ORIGIN,
|
|
||||||
location
|
|
||||||
);
|
|
||||||
// 将临时行动单元序列化至临时文件夹,并设置程序路径、放置在队列中,等待执行状态变化,并根据序列化选项选择是否补充 MetaActionInfo 并持久序列化
|
|
||||||
// 通过 ActionCapability 暴露的接口,序列化至临时文件夹,同时返回Path对象并设置。队列建议交给 SandboxRunner
|
|
||||||
// 持有,包括监听与序列化线程
|
|
||||||
runnerClient.tmpSerialize(tempAction, generatorData.getCode(), generatorData.getCodeType());
|
|
||||||
if (generatorData.isSerialize()) {
|
|
||||||
waitingSerialize();
|
|
||||||
}
|
|
||||||
result.setTempAction(tempAction);
|
|
||||||
} catch (Exception e) {
|
|
||||||
result.setTempAction(null);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO persist serialize. For now, it can be scheduled as a cycling-triggered StateAction or as a special MetaAction
|
|
||||||
private void waitingSerialize() {
|
|
||||||
throw new UnsupportedOperationException("Unimplemented method 'waitingSerialize'");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildPrompt(GeneratorInput data) {
|
|
||||||
JSONObject prompt = new JSONObject();
|
|
||||||
prompt.put("[行动描述]", data.getDescription());
|
|
||||||
// prompt.putObject("[行动参数]").putAll(data.getParams());
|
|
||||||
prompt.putObject("[行动参数描述]").putAll(data.getParamsDescription());
|
|
||||||
return prompt.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String modelKey() {
|
|
||||||
return "dynamic_generator";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package work.slhaf.partner.module.modules.action.executor.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GeneratorInput {
|
|
||||||
private String actionName;
|
|
||||||
private Map<String, Object> params;
|
|
||||||
private String description;
|
|
||||||
private Map<String, String> paramsDescription;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package work.slhaf.partner.module.modules.action.executor.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import work.slhaf.partner.core.action.entity.MetaAction;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GeneratorResult {
|
|
||||||
private MetaAction tempAction;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package work.slhaf.partner.module.modules.action.executor.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import work.slhaf.partner.api.chat.pojo.Message;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class RepairerInput {
|
|
||||||
|
|
||||||
private String userId;
|
|
||||||
private List<Message> recentMessages;
|
|
||||||
private Map<String, String> params;
|
|
||||||
private String actionDescription;
|
|
||||||
private List<HistoryAction> historyActionResults;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package work.slhaf.partner.module.modules.action.executor.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 行动修复结果,包含行动状态和修复后的参数
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class RepairerResult {
|
|
||||||
|
|
||||||
private RepairerStatus status;
|
|
||||||
private List<String> fixedData;
|
|
||||||
|
|
||||||
public enum RepairerStatus {
|
|
||||||
/**
|
|
||||||
* 成功修复: 携带修复后参数; 此种情况对应 Repairer 通过某种方式获取到了完整的参数(调用额外的行动)
|
|
||||||
*/
|
|
||||||
OK,
|
|
||||||
/**
|
|
||||||
* 发送了自对话请求干预行动,这类一般是补充信息或者提供行动指导,后续必须再步入修复进程,但需要设置层级
|
|
||||||
*/
|
|
||||||
ACQUIRE,
|
|
||||||
/**
|
|
||||||
* 修复失败(简单修复、自对话通道均出现错误,正常情况不应该出现)
|
|
||||||
*/
|
|
||||||
FAILED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user