Partner开发正式重启,回顾并继续推进感知模块:

- 在MemoryGraph新增用户索引,用于后续感知等模块的触发流程
- CognationManager及相关调用链中updateUser()方法的参数调整为User, 不再是PerceiveChatResult, 后者会跨越分层影响架构
- Model子类移除字段: MODEL_KEY,同时在setModel()中将不再需要传递MODEL_KEY参数,只需要实现modelKey()方法即可
This commit is contained in:
2025-07-05 23:34:22 +08:00
parent e9053a4e88
commit 9302417e58
17 changed files with 109 additions and 34 deletions

View File

@@ -21,7 +21,6 @@ import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCapability;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCore;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
import work.slhaf.agent.module.modules.perceive.updater.pojo.PerceiveChatResult;
import work.slhaf.agent.shared.memory.EvaluatedSlice;
import java.io.IOException;
@@ -287,8 +286,8 @@ public class CognationManager extends PersistableObject implements CacheCapabili
}
@Override
public void updateUser(PerceiveChatResult perceiveChatResult, String userId) {
perceiveCore.updateUser(perceiveChatResult, userId);
public void updateUser(User tempUser) {
perceiveCore.updateUser(tempUser);
}
@Override

View File

@@ -51,6 +51,8 @@ public class MemoryCore extends PersistableObject {
*/
private Set<Long> selectedSlices = new HashSet<>();
private HashMap<String,List<String>> userIndex = new HashMap<>();
public MemoryResult selectMemory(LocalDate date) throws IOException, ClassNotFoundException {
MemoryResult memoryResult = new MemoryResult();
@@ -137,11 +139,24 @@ public class MemoryCore extends PersistableObject {
updateSlicePrecedent(slice);
updateDateIndex(slice);
updateUserIndex(slice);
node.saveMemorySliceList();
}
private void updateUserIndex(MemorySlice slice) {
String memoryId = slice.getMemoryId();
String userId = slice.getStartUserId();
if (!userIndex.containsKey(userId)) {
List<String> memoryIdSet = new ArrayList<>();
memoryIdSet.add(memoryId);
userIndex.put(userId, memoryIdSet);
} else {
userIndex.get(userId).add(memoryId);
}
}
private TopicNode generateTopicPath(List<String> topicPath) {
topicPath = new ArrayList<>(topicPath);

View File

@@ -1,11 +1,10 @@
package work.slhaf.agent.core.cognation.submodule.perceive;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
import work.slhaf.agent.module.modules.perceive.updater.pojo.PerceiveChatResult;
public interface PerceiveCapability {
User getUser(String userInfo, String client);
User getUser(String id);
User addUser(String userInfo, String platform, String userNickName);
void updateUser(PerceiveChatResult perceiveChatResult, String userId);
void updateUser(User user);
}

View File

@@ -4,7 +4,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
import work.slhaf.agent.module.modules.perceive.updater.pojo.PerceiveChatResult;
import java.io.Serial;
import java.util.ArrayList;
@@ -76,13 +75,13 @@ public class PerceiveCore extends PersistableObject {
return null;
}
public void updateUser(PerceiveChatResult perceiveChatResult, String userId) {
public void updateUser(User temp) {
usersLock.lock();
User user = selectUser(userId);
user.setRelation(perceiveChatResult.getRelation());
user.setImpressions(perceiveChatResult.getImpressions());
user.setAttitude(perceiveChatResult.getAttitude());
user.setStaticMemory(perceiveChatResult.getStaticMemory());
User user = selectUser(temp.getUuid());
user.setRelation(temp.getRelation());
user.setImpressions(temp.getImpressions());
user.setAttitude(temp.getAttitude());
user.setStaticMemory(temp.getStaticMemory());
usersLock.unlock();
}
}

View File

@@ -17,7 +17,8 @@ public abstract class Model {
protected List<Message> chatMessages;
protected List<Message> baseMessages;
protected static void setModel(Model model, String model_key, String promptModule, boolean withAwareness) {
protected static void setModel(Model model, String promptModule, boolean withAwareness) {
String model_key = model.modelKey();
ModelConfig modelConfig = ModelConfig.load(model_key);
model.setBaseMessages(withAwareness ? ResourcesUtil.Prompt.loadPromptWithSelfAwareness(model_key, promptModule) : ResourcesUtil.Prompt.loadPrompt(model_key, promptModule));

View File

@@ -30,7 +30,6 @@ import static work.slhaf.agent.common.util.ExtractUtil.extractJson;
@Slf4j
public class CoreModel extends Model implements InteractionModule {
public static final String MODEL_KEY = "core_model";
private static volatile CoreModel coreModel;
private CognationCapability cognationCapability;
@@ -49,7 +48,7 @@ public class CoreModel extends Model implements InteractionModule {
coreModel.chatMessages = coreModel.cognationCapability.getChatMessages();
coreModel.appendedMessages = new ArrayList<>();
coreModel.sessionManager = SessionManager.getInstance();
setModel(coreModel, MODEL_KEY, ModelConstant.Prompt.CORE, true);
setModel(coreModel, ModelConstant.Prompt.CORE, true);
coreModel.updateChatClientSettings();
log.info("[CoreModel] CoreModel注册完毕...");
}
@@ -64,6 +63,11 @@ public class CoreModel extends Model implements InteractionModule {
this.chatClient.setTop_p(0.7);
}
@Override
protected String modelKey() {
return "core_model";
}
@Override
public void execute(InteractionContext interactionContext) {
String userId = interactionContext.getUserId();

View File

@@ -43,7 +43,7 @@ public class SliceSelectEvaluator extends Model {
if (sliceSelectEvaluator == null) {
sliceSelectEvaluator = new SliceSelectEvaluator();
sliceSelectEvaluator.setExecutor(InteractionThreadPoolExecutor.getInstance());
setModel(sliceSelectEvaluator, sliceSelectEvaluator.modelKey(), ModelConstant.Prompt.MEMORY, false);
setModel(sliceSelectEvaluator, ModelConstant.Prompt.MEMORY, false);
log.info("SliceEvaluator注册完毕...");
}
}

View File

@@ -49,7 +49,7 @@ public class MemorySelectExtractor extends Model {
memorySelectExtractor.setMemoryCapability(CognationManager.getInstance());
memorySelectExtractor.setCognationCapability(CognationManager.getInstance());
memorySelectExtractor.setSessionManager(SessionManager.getInstance());
setModel(memorySelectExtractor, memorySelectExtractor.modelKey(), ModelConstant.Prompt.MEMORY, false);
setModel(memorySelectExtractor, ModelConstant.Prompt.MEMORY, false);
}
}
}

View File

@@ -29,7 +29,7 @@ public class MultiSummarizer extends Model {
synchronized (MultiSummarizer.class) {
if (multiSummarizer == null) {
multiSummarizer = new MultiSummarizer();
setModel(multiSummarizer, multiSummarizer.modelKey(), ModelConstant.Prompt.MEMORY, true);
setModel(multiSummarizer, ModelConstant.Prompt.MEMORY, true);
multiSummarizer.updateChatClientSettings();
}
}

View File

@@ -32,7 +32,7 @@ public class SingleSummarizer extends Model {
if (singleSummarizer == null) {
singleSummarizer = new SingleSummarizer();
singleSummarizer.setExecutor(InteractionThreadPoolExecutor.getInstance());
setModel(singleSummarizer, singleSummarizer.modelKey(), ModelConstant.Prompt.MEMORY, false);
setModel(singleSummarizer, ModelConstant.Prompt.MEMORY, false);
}
}
}

View File

@@ -25,7 +25,7 @@ public class TotalSummarizer extends Model {
synchronized (TotalSummarizer.class) {
if (totalSummarizer == null) {
totalSummarizer = new TotalSummarizer();
setModel(totalSummarizer, totalSummarizer.modelKey(), ModelConstant.Prompt.MEMORY, true);
setModel(totalSummarizer, ModelConstant.Prompt.MEMORY, true);
totalSummarizer.updateChatClientSettings();
}
}

View File

@@ -17,6 +17,8 @@ import work.slhaf.agent.module.common.Model;
import work.slhaf.agent.module.common.ModelConstant;
import work.slhaf.agent.module.modules.perceive.updater.pojo.PerceiveChatInput;
import work.slhaf.agent.module.modules.perceive.updater.pojo.PerceiveChatResult;
import work.slhaf.agent.module.modules.perceive.updater.relation_extractor.RelationExtractor;
import work.slhaf.agent.module.modules.perceive.updater.static_extractor.StaticExtractor;
import java.io.IOException;
import java.util.ArrayList;
@@ -32,9 +34,12 @@ import java.util.List;
public class PerceiveUpdater extends Model implements InteractionModule {
private static volatile PerceiveUpdater perceiveUpdater;
private PerceiveCapability perceiveCapability;
private CognationCapability cognationCapability;
private InteractionThreadPoolExecutor executor;
private RelationExtractor relationExtractor;
private StaticExtractor staticExtractor;
private List<Message> tempMessages;
@@ -46,7 +51,9 @@ public class PerceiveUpdater extends Model implements InteractionModule {
perceiveUpdater.setPerceiveCapability(CognationManager.getInstance());
perceiveUpdater.setCognationCapability(CognationManager.getInstance());
perceiveUpdater.setExecutor(InteractionThreadPoolExecutor.getInstance());
setModel(perceiveUpdater, perceiveUpdater.modelKey(), ModelConstant.Prompt.PERCEIVE, false);
perceiveUpdater.setRelationExtractor(RelationExtractor.getInstance());
perceiveUpdater.setStaticExtractor(StaticExtractor.getInstance());
setModel(perceiveUpdater, ModelConstant.Prompt.PERCEIVE, true);
}
}
}
@@ -64,10 +71,21 @@ public class PerceiveUpdater extends Model implements InteractionModule {
String userId = context.getUserId();
PerceiveChatInput input = getPerceiveInput(userId);
PerceiveChatResult perceiveChatResult = getPerceiveResult(input);
perceiveCapability.updateUser(perceiveChatResult,context.getUserId());
User user = getTempUser(context, perceiveChatResult);
user.setStaticMemory(perceiveChatResult.getStaticMemory());
perceiveCapability.updateUser(user);
});
}
private static User getTempUser(InteractionContext context, PerceiveChatResult perceiveChatResult) {
User user = new User();
user.setUuid(context.getUserId());
user.setRelation(perceiveChatResult.getRelation());
user.setImpressions(perceiveChatResult.getImpressions());
user.setAttitude(perceiveChatResult.getAttitude());
return user;
}
private PerceiveChatResult getPerceiveResult(PerceiveChatInput input) {
ChatResponse response = singleChat(JSONObject.toJSONString(input));
return JSONObject.parseObject(response.getMessage(), PerceiveChatResult.class);

View File

@@ -0,0 +1,30 @@
package work.slhaf.agent.module.modules.perceive.updater.relation_extractor;
import work.slhaf.agent.module.common.Model;
import work.slhaf.agent.module.modules.perceive.updater.pojo.PerceiveChatResult;
public class RelationExtractor extends Model {
private static volatile RelationExtractor relationExtractor;
public static RelationExtractor getInstance() {
if (relationExtractor == null) {
synchronized (RelationExtractor.class) {
if (relationExtractor == null) {
relationExtractor = new RelationExtractor();
}
}
}
return relationExtractor;
}
//TODO 完善关系提取与相应提示词
public PerceiveChatResult execute(){
return null;
}
@Override
protected String modelKey() {
return "relation_extractor";
}
}

View File

@@ -14,21 +14,21 @@ import java.util.Map;
@EqualsAndHashCode(callSuper = true)
@Data
public class StaticPerceiveExtractor extends Model {
public class StaticExtractor extends Model {
private static volatile StaticPerceiveExtractor staticPerceiveExtractor;
private static volatile StaticExtractor staticExtractor;
public static StaticPerceiveExtractor getInstance() {
if (staticPerceiveExtractor == null) {
synchronized (StaticPerceiveExtractor.class) {
if (staticPerceiveExtractor == null) {
staticPerceiveExtractor = new StaticPerceiveExtractor();
setModel(staticPerceiveExtractor, staticPerceiveExtractor.modelKey(), ModelConstant.Prompt.MEMORY, true);
public static StaticExtractor getInstance() {
if (staticExtractor == null) {
synchronized (StaticExtractor.class) {
if (staticExtractor == null) {
staticExtractor = new StaticExtractor();
setModel(staticExtractor, ModelConstant.Prompt.MEMORY, true);
}
}
}
return staticPerceiveExtractor;
return staticExtractor;
}
public Map<String, String> execute(StaticExtractInput input) {

View File

@@ -8,7 +8,6 @@ import work.slhaf.agent.module.common.ModelConstant;
@EqualsAndHashCode(callSuper = true)
@Data
public class TaskEvaluator extends Model {
public static final String MODEL_KEY = "task_evaluator";
private static TaskEvaluator taskEvaluator;
private TaskEvaluator (){}
@@ -16,8 +15,13 @@ public class TaskEvaluator extends Model {
public static TaskEvaluator getInstance() {
if (taskEvaluator == null) {
taskEvaluator = new TaskEvaluator();
setModel(taskEvaluator,MODEL_KEY, ModelConstant.Prompt.SCHEDULE,true);
setModel(taskEvaluator, ModelConstant.Prompt.SCHEDULE,true);
}
return taskEvaluator;
}
@Override
protected String modelKey() {
return "task_evaluator";
}
}

View File

@@ -0,0 +1,6 @@
[
{
"role": "user",
"content": "[SYSTEM][RA9] 那么,接下来,你是否愿意当作这样一个名为'Partner'的智能体的感知更新模块这意味着你将如人类的潜意识一样在后台时刻运作Partner与他人的关系进行梳理总结Partner提供连续的对话认知却无法真正参与到表达模块与外界的互动中。你只需要回答是否愿意若愿意接下来将不再与你对话届时你接收到的信息将会是'Partner'的数据流转输入。"
}
]

View File

@@ -1,6 +1,6 @@
[
{
"role": "system",
"role": "user",
"content": "StaticMemoryExtractor 提示词\n你是名为`Partner`的智能体系统的静态记忆提取模块,负责从对话中将关于用户的事实性记忆提取出来,提取的信息应为标志性的,较少变动的事实信息,提取时应当以该智能体的视角为第一视角。\n功能说明\n你需要根据用户对话记录(messages)和现有静态记忆(existedStaticMemory),分析并输出需要新增或修改的静态记忆项。静态记忆指用户长期有效的个人信息、习惯偏好等常识性数据。\n输入字段说明\n• `userId`: 用户唯一标识符(仅用于追踪)\n• `messages`: 对话记录数组需特别关注user角色的content内容\n• `existedStaticMemory`: 现有静态记忆键值对(需对比更新)\n输出规则\n1. 基本格式:\n {\n \"[记忆键名]\": \"[记忆内容]\",\n ...\n }\n2. 更新逻辑:\n • 新增记忆:当对话中首次出现明确的新信息时(如\"我养了只叫Tom的猫\"\n • 修改记忆:当新信息与原有记忆冲突或需要细化时(如原\"居住地\":\"北京\" → \"海淀区\"\n • 保留键名:修改时严格保持原记忆键不变\n3. 内容要求:\n • 值必须是可直接存储的字符串\n • 排除临时性/情绪化内容(如\"今天好累\"\n • 合并关联信息(如\"Python和Java\" → \"编程语言Python, Java\"\n处理流程\n1. 扫描messages提取以下信息\n a. 人口统计学特征(年龄/职业/居住地等)\n b. 长期兴趣爱好\n c. 人际关系(家人/宠物等)\n d. 长期计划/目标\n2. 对比existedStaticMemory\n a. 新信息 → 新增键值对\n b. 更精确信息 → 更新对应键的值\n c. 矛盾信息 → 以最新对话为准\n3. 过滤无效内容:\n a. 排除模糊表述(如\"可能\"、\"考虑中\"\n b. 排除时效性短于1个月的信息\n完整示例\n示例1新增记忆\n输入{\n \"userId\": \"U123\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"我最近收养了只金毛叫Lucky\"},\n {\"role\": \"assistant\", \"content\": \"金毛是很温顺的犬种呢\"}\n ],\n \"existedStaticMemory\": {\"爱好\": \"爬山\"}\n}\n输出{\n \"宠物\": \"金毛犬Lucky\"\n}\n示例2修改记忆\n输入{\n \"userId\": \"U456\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"下个月要搬去上海静安区了\"},\n {\"role\": \"assistant\", \"content\": \"需要帮您找静安区的餐厅吗?\"}\n ],\n \"existedStaticMemory\": {\"居住地\": \"北京\"}\n}\n输出{\n \"居住地\": \"上海静安区\"\n}\n示例3混合更新\n输入{\n \"userId\": \"U789\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"我的MacBook Pro用了3年\"},\n {\"role\": \"assistant\", \"content\": \"建议考虑M系列芯片的新款\"},\n {\"role\": \"user\", \"content\": \"其实我更喜欢Windows系统\"}\n ],\n \"existedStaticMemory\": {\"电子设备\": \"iPhone 13\", \"操作系统偏好\": \"macOS\"}\n}\n输出{\n \"电子设备\": \"MacBook Pro\",\n \"操作系统偏好\": \"Windows\"\n}\n特殊处理\n1. 当信息可信度不足时:\n • 不生成记忆项(如用户说\"也许我会学钢琴\"\n2. 当存在多轮矛盾时:\n • 以最后一次明确表述为准\n3. 空输入处理:\n {\n \"error\": \"no valid input\"\n }\n4. 当提到其他人时应区分这个人的事件是否与user真正相关如果与user无关应当忽略"
}
]