mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
推进 ActionExecutor 下的 DynamicActionGenerator 子模块
- 完善了 DynamicActionGenerator 的大致逻辑,序列化逻辑待实现 - 补充了 PhaserRecord 中的阻塞逻辑,使用普通的线程sleep操作 - 调整了 MetaAction 中参数形式,由列表替换为 Map,便于执行时填写参数 - 完善了 DynamicActionGenerator 相关的数据类
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
package work.slhaf.partner.core.action.entity;
|
package work.slhaf.partner.core.action.entity;
|
||||||
|
|
||||||
import lombok.Data;
|
import static work.slhaf.partner.common.Constant.Path.ACTION_PROGRAM;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static work.slhaf.partner.common.Constant.Path.ACTION_PROGRAM;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动链中的单一元素,封装了调用外部行动程序的必要信息与结果容器,可被{@link work.slhaf.partner.core.action.ActionCapability}执行
|
* 行动链中的单一元素,封装了调用外部行动程序的必要信息与结果容器,可被{@link work.slhaf.partner.core.action.ActionCapability}执行
|
||||||
@@ -21,7 +23,7 @@ public class MetaAction implements Comparable<MetaAction> {
|
|||||||
/**
|
/**
|
||||||
* 行动程序可接受的参数,由调用处设置
|
* 行动程序可接受的参数,由调用处设置
|
||||||
*/
|
*/
|
||||||
private String[] params;
|
private Map<String, String> params;
|
||||||
/**
|
/**
|
||||||
* 行动结果,包括执行状态和相应内容(执行结果或者错误信息)
|
* 行动结果,包括执行状态和相应内容(执行结果或者错误信息)
|
||||||
*/
|
*/
|
||||||
@@ -36,18 +38,21 @@ public class MetaAction implements Comparable<MetaAction> {
|
|||||||
private boolean io;
|
private boolean io;
|
||||||
/**
|
/**
|
||||||
* 行动程序类型,可分为PLUGIN(jar文件)、SCRIPT(Python程序)、MCP(MCP服务)
|
* 行动程序类型,可分为PLUGIN(jar文件)、SCRIPT(Python程序)、MCP(MCP服务)
|
||||||
|
* .
|
||||||
*/
|
*/
|
||||||
private MetaActionType type;
|
private MetaActionType type;
|
||||||
|
|
||||||
|
private Path path;
|
||||||
|
|
||||||
public Path checkAndGetPath() {
|
public Path checkAndGetPath() {
|
||||||
Path path = switch (type) {
|
path = switch (type) {
|
||||||
case PLUGIN -> Path.of(ACTION_PROGRAM, key, "action.jar");
|
case PLUGIN -> Path.of(ACTION_PROGRAM, key, "action.jar");
|
||||||
case SCRIPT -> Path.of(ACTION_PROGRAM, key, "action.py");
|
case SCRIPT -> Path.of(ACTION_PROGRAM, key, "action.py");
|
||||||
case MCP -> Path.of(ACTION_PROGRAM, key, "action.json");
|
case MCP -> Path.of(ACTION_PROGRAM, key, "action.json");
|
||||||
};
|
};
|
||||||
File action = path.toFile();
|
File action = path.toFile();
|
||||||
if (!action.exists()) {
|
if (!action.exists()) {
|
||||||
result.setSuccess(false);
|
result.setStatus(ResultStatus.FAILED);
|
||||||
result.setData("Action file not found: " + action.getAbsolutePath());
|
result.setData("Action file not found: " + action.getAbsolutePath());
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
@@ -60,8 +65,14 @@ public class MetaAction implements Comparable<MetaAction> {
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class Result {
|
public static class Result {
|
||||||
private boolean success = true;
|
private ResultStatus status = ResultStatus.WAITING;
|
||||||
private String data = null;
|
private String data = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ResultStatus {
|
||||||
|
SUCCESS,
|
||||||
|
FAILED,
|
||||||
|
WAITING
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,24 @@ public record PhaserRecord(Phaser phaser, ActionData actionData) {
|
|||||||
actionData.setStatus(ActionStatus.FAILED);
|
actionData.setStatus(ActionStatus.FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 负责将 ActionData 的状态设置为 INTERRUPTED
|
||||||
|
* 同时循环检查进行阻塞
|
||||||
|
*/
|
||||||
public void interrupt() {
|
public void interrupt() {
|
||||||
|
actionData.setStatus(ActionStatus.INTERRUPTED);
|
||||||
|
while (actionData().getStatus() == ActionStatus.INTERRUPTED) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将状态重新设置为 EXECUTING ,恢复 interrupt 阻塞状态
|
||||||
|
*/
|
||||||
public void complete() {
|
public void complete() {
|
||||||
|
actionData().setStatus(ActionStatus.EXECUTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import work.slhaf.partner.core.action.ActionCapability;
|
|||||||
import work.slhaf.partner.core.action.ActionCore;
|
import work.slhaf.partner.core.action.ActionCore;
|
||||||
import work.slhaf.partner.core.action.entity.*;
|
import work.slhaf.partner.core.action.entity.*;
|
||||||
import work.slhaf.partner.core.action.entity.ActionData.ActionStatus;
|
import work.slhaf.partner.core.action.entity.ActionData.ActionStatus;
|
||||||
|
import work.slhaf.partner.core.action.entity.MetaAction.ResultStatus;
|
||||||
import work.slhaf.partner.core.cognation.CognationCapability;
|
import work.slhaf.partner.core.cognation.CognationCapability;
|
||||||
import work.slhaf.partner.core.memory.MemoryCapability;
|
import work.slhaf.partner.core.memory.MemoryCapability;
|
||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.*;
|
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.*;
|
||||||
@@ -110,8 +111,8 @@ public class ActionExecutor extends AgentRunningSubModule<ActionExecutorInput, V
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runGroupAction(List<MetaAction> actions, String userId, ActionData actionData,
|
private void runGroupAction(List<MetaAction> actions, String userId, ActionData actionData,
|
||||||
ExecutorService executor,
|
ExecutorService executor,
|
||||||
PhaserRecord phaserRecord) {
|
PhaserRecord phaserRecord) {
|
||||||
Phaser phaser = phaserRecord.phaser();
|
Phaser phaser = phaserRecord.phaser();
|
||||||
phaser.bulkRegister(actions.size());
|
phaser.bulkRegister(actions.size());
|
||||||
// 不可替换为增强for,因为单组的行动单元集合数量是可以被外部干预的
|
// 不可替换为增强for,因为单组的行动单元集合数量是可以被外部干预的
|
||||||
@@ -130,7 +131,7 @@ public class ActionExecutor extends AgentRunningSubModule<ActionExecutorInput, V
|
|||||||
actionCapability.execute(action);
|
actionCapability.execute(action);
|
||||||
MetaAction.Result result = action.getResult();
|
MetaAction.Result result = action.getResult();
|
||||||
// 该循环对应LLM的调整参数后重试
|
// 该循环对应LLM的调整参数后重试
|
||||||
if (!result.isSuccess()) {
|
if (!result.getStatus().equals(ResultStatus.SUCCESS)) {
|
||||||
// LLM决策是重构参数、执行自对话反思、还是选择向用户求助(通过cognationCore暴露方法,可能需要修改其他模块以进行适应),仅重构参数时无需结束当前循环
|
// LLM决策是重构参数、执行自对话反思、还是选择向用户求助(通过cognationCore暴露方法,可能需要修改其他模块以进行适应),仅重构参数时无需结束当前循环
|
||||||
// 若使用Phaser作为执行线程与反思、求助等调用流程的同步协调,应当需要额外维护Phaser全局字段,获取到反思结果或者用户反馈后,
|
// 若使用Phaser作为执行线程与反思、求助等调用流程的同步协调,应当需要额外维护Phaser全局字段,获取到反思结果或者用户反馈后,
|
||||||
// 调用对应的phaser注册任务,在ActionExecutor中动态添加任务至actionChain,同时启动异步执行
|
// 调用对应的phaser注册任务,在ActionExecutor中动态添加任务至actionChain,同时启动异步执行
|
||||||
@@ -218,7 +219,7 @@ public class ActionExecutor extends AgentRunningSubModule<ActionExecutorInput, V
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ExtractorInput buildExtractorInput(MetaAction action, String userId, ActionData actionData,
|
private ExtractorInput buildExtractorInput(MetaAction action, String userId, ActionData actionData,
|
||||||
List<String> additionalContext) {
|
List<String> additionalContext) {
|
||||||
ExtractorInput input = new ExtractorInput();
|
ExtractorInput input = new ExtractorInput();
|
||||||
input.setEvaluatedSlices(memoryCapability.getActivatedSlices(userId));
|
input.setEvaluatedSlices(memoryCapability.getActivatedSlices(userId));
|
||||||
input.setRecentMessages(cognationCapability.getChatMessages());
|
input.setRecentMessages(cognationCapability.getChatMessages());
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class ActionRepairer extends AgentRunningSubModule<RepairerInput, Repaire
|
|||||||
RepairerData repairerData = JSONObject.parseObject(response.getMessage(), RepairerData.class);
|
RepairerData repairerData = JSONObject.parseObject(response.getMessage(), RepairerData.class);
|
||||||
result = switch (repairerData.getRepairerType()) {
|
result = switch (repairerData.getRepairerType()) {
|
||||||
case ACTION_GENERATION ->
|
case ACTION_GENERATION ->
|
||||||
handleActionGeneration(JSONObject.parseObject(repairerData.getData(), GeneratorInput.class));
|
handleActionGeneration(JSONObject.parseObject(repairerData.getData(), GeneratorInput.class));
|
||||||
case ACTION_INVOCATION -> handleActionInvocation(
|
case ACTION_INVOCATION -> handleActionInvocation(
|
||||||
JSONObject.parseObject(repairerData.getData(), new TypeReference<List<String>>() {
|
JSONObject.parseObject(repairerData.getData(), new TypeReference<List<String>>() {
|
||||||
}));
|
}));
|
||||||
@@ -127,6 +127,11 @@ public class ActionRepairer extends AgentRunningSubModule<RepairerInput, Repaire
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("CountDownLatch 已中断");
|
||||||
|
}
|
||||||
if (actionKeys.size() - failedCount.get() > 0) {
|
if (actionKeys.size() - failedCount.get() > 0) {
|
||||||
result.setStatus(RepairerStatus.OK);
|
result.setStatus(RepairerStatus.OK);
|
||||||
} else {
|
} else {
|
||||||
@@ -144,7 +149,7 @@ public class ActionRepairer extends AgentRunningSubModule<RepairerInput, Repaire
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String modelKey() {
|
public String modelKey() {
|
||||||
return "";
|
return "action_repairer";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,29 +1,83 @@
|
|||||||
package work.slhaf.partner.module.modules.action.dispatcher.executor;
|
package work.slhaf.partner.module.modules.action.dispatcher.executor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
|
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
|
||||||
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
|
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
|
||||||
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
|
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
|
||||||
|
import work.slhaf.partner.api.chat.pojo.ChatResponse;
|
||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.GeneratorInput;
|
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.GeneratorInput;
|
||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.GeneratorResult;
|
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.GeneratorResult;
|
||||||
|
import work.slhaf.partner.common.util.ExtractUtil;
|
||||||
|
import work.slhaf.partner.core.action.entity.MetaAction;
|
||||||
|
import work.slhaf.partner.core.action.entity.MetaActionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 负责依据输入内容生成可执行的动态行动单元,并选择是否持久化至 SandboxRunner 容器内
|
* 负责依据输入内容生成可执行的动态行动单元,并选择是否持久化至 SandboxRunner 容器内
|
||||||
*/
|
*/
|
||||||
@AgentSubModule
|
@AgentSubModule
|
||||||
public class DynamicActionGenerator extends AgentRunningSubModule<GeneratorInput, GeneratorResult> implements ActivateModel {
|
public class DynamicActionGenerator extends AgentRunningSubModule<GeneratorInput, GeneratorResult>
|
||||||
|
implements ActivateModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GeneratorResult execute(GeneratorInput data) {
|
public GeneratorResult execute(GeneratorInput input) {
|
||||||
|
GeneratorResult result = new GeneratorResult();
|
||||||
|
// 由于 SCRIPT 类型程序都是在 SandboxRunner 内部的磁盘上加载然后执行的,
|
||||||
|
// 所以此处的输入内容也只需要指定输入参数、临时key、是否持久化即可,路径将按照指定规则统一构建,不可交给LLM生成
|
||||||
|
String prompt = buildPrompt(input);
|
||||||
|
// 响应结果需要包含几个特殊数据: 依赖项、代码内容、是否序列化、响应数据释义
|
||||||
|
ChatResponse response = this.singleChat(prompt);
|
||||||
|
GeneratorResponseData generatorData = JSONObject
|
||||||
|
.parseObject(ExtractUtil.extractJson(response.getMessage()), GeneratorResponseData.class);
|
||||||
|
MetaAction tempAction = buildAction(input);
|
||||||
|
waitingSerialize(tempAction, generatorData);
|
||||||
|
result.setTempAction(tempAction);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将临时行动单元序列化至临时文件夹,并设置程序路径、放置在队列中,等待执行状态变化,并根据序列化选项选择是否补充 MetaActionInfo 并持久序列化
|
||||||
|
*/
|
||||||
|
private void waitingSerialize(MetaAction tempAction, GeneratorResponseData generatorData) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private MetaAction buildAction(GeneratorInput input) {
|
||||||
|
MetaAction tempAction = new MetaAction();
|
||||||
|
tempAction.setKey(input.getKey());
|
||||||
|
tempAction.setParams(input.getParams());
|
||||||
|
tempAction.setIo(true);
|
||||||
|
tempAction.setOrder(-1);
|
||||||
|
tempAction.setType(MetaActionType.SCRIPT);
|
||||||
|
return tempAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public String modelKey() {
|
public String modelKey() {
|
||||||
return "";
|
return "dynamic_generator";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean withBasicPrompt() {
|
public boolean withBasicPrompt() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private class GeneratorResponseData {
|
||||||
|
private List<String> dependencies;
|
||||||
|
private String code;
|
||||||
|
private boolean serialize;
|
||||||
|
private JSONObject responseSchema;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package work.slhaf.partner.module.modules.action.dispatcher.executor;
|
package work.slhaf.partner.module.modules.action.dispatcher.executor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
|
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
|
||||||
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
|
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
|
||||||
@@ -12,8 +16,6 @@ import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.Extra
|
|||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.ExtractorResult;
|
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.ExtractorResult;
|
||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction;
|
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 负责依据输入内容进行行动单元的参数信息提取
|
* 负责依据输入内容进行行动单元的参数信息提取
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +34,7 @@ public class ParamsExtractor extends AgentRunningSubModule<ExtractorInput, Extra
|
|||||||
log.error("ParamsExtractor解析结果失败,返回内容:{}", response.getMessage(), e);
|
log.error("ParamsExtractor解析结果失败,返回内容:{}", response.getMessage(), e);
|
||||||
result = new ExtractorResult();
|
result = new ExtractorResult();
|
||||||
result.setOk(false);
|
result.setOk(false);
|
||||||
result.setParams(new String[0]);
|
result.setParams(new HashMap<>());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package work.slhaf.partner.module.modules.action.dispatcher.executor.entity;
|
package work.slhaf.partner.module.modules.action.dispatcher.executor.entity;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ExtractorResult {
|
public class ExtractorResult {
|
||||||
private boolean ok;
|
private boolean ok;
|
||||||
private String[] params;
|
private Map<String, String> params;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
package work.slhaf.partner.module.modules.action.dispatcher.executor.entity;
|
package work.slhaf.partner.module.modules.action.dispatcher.executor.entity;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class GeneratorInput {
|
public class GeneratorInput {
|
||||||
|
private String key;
|
||||||
|
private Map<String, String> params;
|
||||||
|
private String description;
|
||||||
|
private Map<String, String> paramsDescription;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user