干预意图提取模块初步完成,Prompt 待制定; 在 ChatClient 中添加了默认的超时设定,超时时间后续可能需要调整。

另: 发现很多细节错误,比如“各个后置模块允许执行的条件”、“主模块出现异常时需要如何处理”、“模块Prompt的构建方式、采用格式不统一”等,需要后续进行修复或调整
This commit is contained in:
2025-10-31 21:03:26 +08:00
parent ec4fbb7f19
commit 746fda1a5e
18 changed files with 217 additions and 21 deletions

View File

@@ -1,10 +1,12 @@
package work.slhaf.partner.api.chat;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.chat.constant.ChatConstant;
import work.slhaf.partner.api.chat.pojo.ChatBody;
import work.slhaf.partner.api.chat.pojo.ChatResponse;
@@ -13,6 +15,7 @@ import work.slhaf.partner.api.chat.pojo.PrimaryChatResponse;
import java.util.List;
@Slf4j
@Data
@NoArgsConstructor
public class ChatClient {
@@ -34,6 +37,8 @@ public class ChatClient {
public ChatResponse runChat(List<Message> messages) {
HttpRequest request = HttpRequest.post(url);
request.setConnectionTimeout(2000);
request.setReadTimeout(15000);
request.header("Content-Type", "application/json");
request.header("Authorization", "Bearer " + apikey);
@@ -53,17 +58,26 @@ public class ChatClient {
.build();
}
HttpResponse response = request.body(JSONUtil.toJsonStr(body)).execute();
ChatResponse finalResponse;
try {
HttpResponse response = request.body(JSONUtil.toJsonStr(body)).execute();
PrimaryChatResponse primaryChatResponse = JSONUtil.toBean(response.body(), PrimaryChatResponse.class);
finalResponse = ChatResponse.builder()
.type(ChatConstant.Response.SUCCESS)
.status(ChatConstant.ResponseStatus.SUCCESS)
.message(primaryChatResponse.getChoices().get(0).getMessage().getContent())
.usageBean(primaryChatResponse.getUsage())
.build();
response.close();
} catch (IORuntimeException e) {
log.error("请求超时", e);
finalResponse = ChatResponse.builder()
.message("连接超时")
.status(ChatConstant.ResponseStatus.FAILED)
.usageBean(null)
.build();
}
return finalResponse;
}

View File

@@ -8,8 +8,7 @@ public class ChatConstant {
public static final String ASSISTANT = "assistant";
}
public static class Response {
public static final String SUCCESS = "success";
public static final String ERROR = "error";
public enum ResponseStatus {
SUCCESS, FAILED
}
}

View File

@@ -4,13 +4,14 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import work.slhaf.partner.api.chat.constant.ChatConstant;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChatResponse {
private String type;
private ChatConstant.ResponseStatus status;
private String message;
private PrimaryChatResponse.UsageBean usageBean;
}

View File

@@ -35,6 +35,8 @@ public interface ActionCapability {
void removePhaserRecord(Phaser phaser);
List<ActionCore.PhaserRecord> listPhaserRecords();
ActionCore.PhaserRecord getPhaserRecord(String tendency, String source);
MetaAction loadMetaAction(@NonNull String actionKey);

View File

@@ -222,6 +222,11 @@ public class ActionCore extends PartnerCore<ActionCore> {
throw new MetaActionNotFoundException("未找到对应的行动程序信息" + actionKey);
}
@CapabilityMethod
public List<PhaserRecord> listPhaserRecords() {
return phaserRecords;
}
/**
* 命中缓存且评估通过时
*

View File

@@ -8,7 +8,7 @@ public abstract class PostRunningModule extends AgentRunningModule<PartnerRunnin
@Override
public final void execute(PartnerRunningFlowContext context) {
boolean trigger = context.getModuleContext().getExtraContext().getBoolean("post_process_trigger");
if (!trigger) {
if (!trigger && relyOnMessage()) {
return;
}
doExecute(context);
@@ -16,4 +16,5 @@ public abstract class PostRunningModule extends AgentRunningModule<PartnerRunnin
public abstract void doExecute(PartnerRunningFlowContext context);
protected abstract boolean relyOnMessage();
}

View File

@@ -40,5 +40,4 @@ public abstract class PreRunningModule extends AgentRunningModule<PartnerRunning
protected abstract void doExecute(PartnerRunningFlowContext context);
}

View File

@@ -58,4 +58,9 @@ public class ActionDispatcher extends PostRunningModule {
});
}
@Override
protected boolean relyOnMessage() {
return false;
}
}

View File

@@ -1,11 +1,17 @@
package work.slhaf.partner.module.modules.action.identifier;
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.InjectModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
import work.slhaf.partner.core.action.ActionCapability;
import work.slhaf.partner.core.cognation.CognationCapability;
import work.slhaf.partner.core.memory.MemoryCapability;
import work.slhaf.partner.module.common.module.PreRunningModule;
import work.slhaf.partner.module.modules.action.identifier.evaluator.InterventionEvaluator;
import work.slhaf.partner.module.modules.action.identifier.recognizer.InterventionRecognizer;
import work.slhaf.partner.module.modules.action.identifier.recognizer.entity.RecognizerInput;
import work.slhaf.partner.module.modules.action.identifier.recognizer.entity.RecognizerResult;
import work.slhaf.partner.runtime.interaction.data.context.PartnerRunningFlowContext;
import java.util.HashMap;
@@ -21,10 +27,34 @@ public class ActionInterventor extends PreRunningModule implements ActivateModel
@InjectModule
private InterventionEvaluator interventionEvaluator;
@InjectCapability
private ActionCapability actionCapability;
@InjectCapability
private CognationCapability cognationCapability;
@InjectCapability
private MemoryCapability memoryCapability;
@Override
protected void doExecute(PartnerRunningFlowContext context) {
//综合当前正在进行的行动链信息、用户交互历史、激活的记忆切片,尝试识别出是否存在行动干预意图
//首先通过recognizer进行快速意图识别识别成功则步入评估阶段评估成功则直接作用于目标行动链
//进行快速意图识别时必须结合近期对话与进行中行动链情况
RecognizerResult recognizerResult = interventionRecognizer.execute(buildRecognizerInput(context.getUserId(), context.getInput()));
if (!recognizerResult.isOk()) {
return;
}
//存在则进一步评估、评估通过则并直接添加行动程序至对应行动链
}
private RecognizerInput buildRecognizerInput(String userId, String input) {
RecognizerInput recognizerInput = new RecognizerInput();
recognizerInput.setInput(input);
recognizerInput.setUserDialogMapStr(memoryCapability.getUserDialogMapStr(userId));
// TODO 参考的对话列表大小或需调整
recognizerInput.setRecentMessages(cognationCapability.getChatMessages());
recognizerInput.setExecutingActions(actionCapability.listPhaserRecords());
return recognizerInput;
}
@Override
@@ -39,6 +69,7 @@ public class ActionInterventor extends PreRunningModule implements ActivateModel
@Override
protected HashMap<String, String> getPromptDataMap(PartnerRunningFlowContext context) {
return null;
}

View File

@@ -1,7 +1,14 @@
package work.slhaf.partner.module.modules.action.identifier.evaluator.entity;
import lombok.Data;
import work.slhaf.partner.api.chat.pojo.Message;
import work.slhaf.partner.core.memory.pojo.EvaluatedSlice;
import java.util.List;
@Data
public class EvaluatorInput {
private String interventionTendency;
private List<EvaluatedSlice> activatedSlices;
private List<Message> recentMessages;
}

View File

@@ -1,18 +1,82 @@
package work.slhaf.partner.module.modules.action.identifier.recognizer;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
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.AgentRunningSubModule;
import work.slhaf.partner.module.modules.action.identifier.recognizer.entity.InterventionResult;
import work.slhaf.partner.api.chat.pojo.ChatResponse;
import work.slhaf.partner.core.action.ActionCapability;
import work.slhaf.partner.core.action.ActionCore;
import work.slhaf.partner.core.action.entity.ActionData;
import work.slhaf.partner.module.modules.action.identifier.recognizer.entity.MetaRecognizerResult;
import work.slhaf.partner.module.modules.action.identifier.recognizer.entity.RecognizerInput;
import work.slhaf.partner.module.modules.action.identifier.recognizer.entity.RecognizerResult;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
@Slf4j
@AgentSubModule
public class InterventionRecognizer extends AgentRunningSubModule<String, InterventionResult> implements ActivateModel {
public class InterventionRecognizer extends AgentRunningSubModule<RecognizerInput, RecognizerResult> implements ActivateModel {
@InjectCapability
private ActionCapability actionCapability;
@Override
public InterventionResult execute(String data) {
public RecognizerResult execute(RecognizerInput input) {
//使用LLM进行快速意图识别
ExecutorService executor = actionCapability.getExecutor(ActionCore.ExecutorType.VIRTUAL);
RecognizerResult recognizerResult = new RecognizerResult();
Map<String, ActionCore.PhaserRecord> resultInterventionMap = recognizerResult.getInterventions();
List<ActionCore.PhaserRecord> executingActions = input.getExecutingActions();
CountDownLatch countDownLatch = new CountDownLatch(executingActions.size());
for (ActionCore.PhaserRecord record : executingActions) {
executor.execute(() -> {
try {
String prompt = buildPrompt(record, input);
ChatResponse response = this.singleChat(prompt);
MetaRecognizerResult result = JSONObject.parseObject(response.getMessage(), MetaRecognizerResult.class);
if (result.isOk()) {
synchronized (resultInterventionMap) {
resultInterventionMap.put(result.getIntervention(), record);
}
}
} catch (Exception e) {
log.error("LLM干预意图提取出错", e);
} finally {
countDownLatch.countDown();
}
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
log.warn("CountDownLatch阻塞已中断");
}
return recognizerResult;
}
return null;
private String buildPrompt(ActionCore.PhaserRecord record, RecognizerInput input) {
ActionData actionData = record.actionData();
JSONObject json = new JSONObject();
JSONObject actionInfo = json.putObject("行动信息");
actionInfo.put("行动倾向", actionData.getStatus());
actionInfo.put("行动原因", actionData.getReason());
actionInfo.put("行动描述", actionData.getDescription());
actionInfo.put("行动状态", actionData.getStatus());
actionInfo.put("行动来源", actionData.getSource());
JSONObject interactionInfo = json.putObject("交互信息");
interactionInfo.put("用户输入", input.getInput());
interactionInfo.put("当前对话", input.getRecentMessages());
interactionInfo.put("近期对话", input.getUserDialogMapStr());
return json.toString();
}
@Override

View File

@@ -3,7 +3,7 @@ package work.slhaf.partner.module.modules.action.identifier.recognizer.entity;
import lombok.Data;
@Data
public class InterventionResult {
private boolean result;
private String interventionTendency;
public class MetaRecognizerResult {
private boolean ok;
private String intervention;
}

View File

@@ -0,0 +1,21 @@
package work.slhaf.partner.module.modules.action.identifier.recognizer.entity;
import lombok.Data;
import work.slhaf.partner.api.chat.pojo.Message;
import work.slhaf.partner.core.action.ActionCore;
import java.util.List;
@Data
public class RecognizerInput {
private String input;
private List<Message> recentMessages;
/**
* 当前用户对应的近两日对话缓存
*/
private String userDialogMapStr;
/**
* 正在执行的行动-Phaser记录列表在Recognizer中结合本次输入并发评估(考虑到不同行动链之间对LLM的影响)
*/
private List<ActionCore.PhaserRecord> executingActions;
}

View File

@@ -0,0 +1,21 @@
package work.slhaf.partner.module.modules.action.identifier.recognizer.entity;
import lombok.Data;
import work.slhaf.partner.core.action.ActionCore;
import java.util.HashMap;
import java.util.Map;
@Data
public class RecognizerResult {
private boolean ok;
/**
* key: 干预倾向
* <br/>
* value: 干预倾向将作用的 phaser 记录
*/
private Map<String, ActionCore.PhaserRecord> interventions = new HashMap<>();
}

View File

@@ -10,6 +10,7 @@ import work.slhaf.partner.module.modules.action.planner.confirmer.entity.Confirm
public class ActionConfirmer extends AgentRunningSubModule<ConfirmerInput, ConfirmerResult> implements ActivateModel {
@Override
public ConfirmerResult execute(ConfirmerInput data) {
//TODO 完善确认逻辑
return null;
}

View File

@@ -119,6 +119,11 @@ public class MemoryUpdater extends PostRunningModule {
});
}
@Override
protected boolean relyOnMessage() {
return true;
}
private void updateMemory() {
log.debug("[MemoryUpdater] 记忆更新流程开始...");
tempMessage = new ArrayList<>(cognationCapability.getChatMessages());

View File

@@ -70,6 +70,11 @@ public class PerceiveUpdater extends PostRunningModule {
});
}
@Override
protected boolean relyOnMessage() {
return true;
}
private void runRelationExtractorAction(PartnerRunningFlowContext context, ReentrantLock userLock, User user) {
RelationExtractResult relationExtractResult = relationExtractor.execute(context);
userLock.lock();

View File

@@ -0,0 +1,15 @@
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import org.junit.jupiter.api.Test;
public class NetTest {
@Test
void httpTest() {
HttpRequest request = HttpRequest.get("slhaf.work");
request.setConnectionTimeout(2);
request.setReadTimeout(2);
HttpResponse execute = request.execute();
System.out.println(execute.toString());
execute.close();
}
}