- 人工智能
- AI Agent
- Agent 框架
- 工具调用
- Agent 工作流
- RAG
- MCP Clients
- 强化学习
【免费下载链接】agent-core-java
openJiuwen agent core Java是 openJiuwen Core的 Java版本,提供AI Agent开发、运行、调优与演进相关的全套SDK能力。
com.openjiuwen.memory.process.extract是 openJiuwen agent-core-java 记忆引擎中的「提取」环节,负责把一轮对话消息转换成可落库的长期记忆结果,覆盖参数封装、模型分析、摘要生成与片段记忆提取。本文以该模块为核心,逐层拆解MemoryAnalyzer、LongTermMemoryExtractor、Generator三类核心组件的职责与调用链,并结合源码、提示词模板与测试用例给出可验证的实现细节,帮助读者理解并复用这套「消息 → 记忆单元」的流水线。
一、模块定位:extract 在记忆流程中的角色
记忆引擎通常包含「提取 → 管理 → 检索」等环节,extract包对应最前端的提取阶段。按照 extract.README.md 的说明,该包负责把对话消息转换为长期记忆相关结果,具体覆盖四个方面:
- 参数封装:把提取流程所需的用户、消息与模型参数收敛为
ExtractMemoryParams; - 模型分析:通过
MemoryAnalyzer分析消息内容,输出关键信息标记、变量结果与摘要; - 摘要生成:按配置决定是否生成摘要记忆;
- 片段记忆提取:通过
LongTermMemoryExtractor抽取用户画像、语义记忆、情景记忆三类长期片段。
模块内共包含 6 个公开类型,核心类型总览如下(与原文档一致):
| 类型 | 说明 |
|---|---|
ExtractMemoryParams | 封装提取流程所需的用户、消息与模型参数。 |
Generator | 协调分析器与提取器,生成变量、摘要和片段记忆单元。 |
LongTermMemoryExtractor | 使用模型和提示词抽取长期片段记忆。 |
MemoryAnalyzer | 分析消息内容,输出关键信息标记、变量结果与摘要。 |
MemoryAnalyzerResult | 保存分析阶段返回的结构化结果。 |
VariableResult | 表示单个变量的键值抽取结果。 |
二、数据对象层:参数封装与结构化输出
ExtractMemoryParams、MemoryAnalyzerResult、VariableResult三个类是面向流程编排的轻量数据对象,负责在两阶段调用(分析 → 生成)之间传递数据。
2.1 ExtractMemoryParams:提取流程的入参集合
ExtractMemoryParams封装记忆提取阶段使用的用户、消息历史和基础模型参数,字段定义如下(见 ExtractMemoryParams.java):
| 字段 | 类型 | 说明 |
|---|---|---|
userId | String | 当前用户标识。 |
scopeId | String | 当前记忆作用域标识。 |
messages | List<BaseMessage> | 本轮需要分析的消息列表。 |
historyMessages | List<BaseMessage> | 可选的历史消息列表。 |
baseChatModel | Model | 基础聊天模型实例。 |
在源码中,Generator.genAllMemorySync会从kwargs中取出这五个参数组装该对象,再传给LongTermMemoryExtractor.extractLongTermMemory(...)使用;Generator同时支持无SearchManager与带SearchManager两种构造方式,后者用于处理「修改/删除记忆」指令时的语义检索。
2.2 MemoryAnalyzerResult:分析阶段的结构化输出
MemoryAnalyzerResult表示消息分析阶段的输出(见 MemoryAnalyzerResult.java):
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
hasKeyInformation | boolean | false | 标记当前消息中是否包含可提取的关键信息。 |
variables | List<VariableResult> | 空列表 | 提取出的变量结果列表。 |
summary | String | 空字符串 | 生成的摘要文本。 |
Generator会读取其中的变量列表、摘要与hasKeyInformation标记,决定后续生成哪些记忆单元:变量非空则转VariableUnit,摘要启用则转SummaryUnit,hasKeyInformation = true时才继续做片段记忆提取。
2.3 VariableResult:单个变量的键值抽取结果
VariableResult表示单个记忆变量的抽取结果(见 VariableResult.java),包含variableKey(变量名)与variableValue(变量值)两个字段,默认均为空字符串。MemoryAnalyzer负责创建该对象列表,Generator会把非空变量值转换为VariableUnit(空值直接跳过,见 Generator.java 的processExtractedData逻辑)。
三、MemoryAnalyzer:消息分析与三路输出
MemoryAnalyzer负责分析对话内容,输出「是否含关键信息」「变量提取结果」「摘要文本」三路结果。它是一个final工具类,提供多个重载的静态analyze方法(见 MemoryAnalyzer.java):
public static CompletionStage<MemoryAnalyzerResult> analyze( List<BaseMessage> messages, List<BaseMessage> historyMessages, Model baseChatModel, AgentMemoryConfig memoryConfig, Integer summaryMaxToken) public static CompletionStage<MemoryAnalyzerResult> analyze( List<BaseMessage> messages, List<BaseMessage> historyMessages, Model baseChatModel, AgentMemoryConfig memoryConfig, Integer summaryMaxToken, MemoryScopeConfig scopeConfig, String forbiddenVariables, int retries)3.1 分析流程
从源码看,一次完整分析包含以下步骤:
- 空消息校验:
messages为空时记录No messages to analyze警告并返回null; - 消息拼接:将
historyMessages与messages分别按role: content格式拼接为history与conversation文本; - 变量模板构建:遍历
memoryConfig.getMemVariables()(List<Param>),生成variables_define_template(variable_key→ 变量名、variable_value→ 变量描述)与variables_output_template(值为空的输出骨架); - 提示词变量注入:组装
has_variable(布尔值转True/False)、forbidden_variables(空白时归一化为None)、max_message_token、user_profile_definition、semantic_memory_definition、episodic_memory_definition等变量; - 提示词组装:
PromptApplier.getInstance().apply("memory_analysis_prompt", promptVariables)渲染 memory_analysis_prompt.md; - 模型调用与解析:输入固定为单条
UserMessage,用JsonOutputParser把模型输出解析成Map,再映射为MemoryAnalyzerResult(fromMap读取has_key_information、variables、summary三个字段,见 MemoryAnalyzer.java); - 重试兜底:默认最多重试 3 次(
DEFAULT_RETRIES = 3),连续失败后返回空白的MemoryAnalyzerResult。
3.2 两个值得注意的行为细节
- 摘要清空规则:若
memoryConfig为空,或未启用长期记忆(enableLongTermMem),或未启用摘要记忆(enableSummaryMemory),返回结果中的summary会被强制清空——避免生成不会被使用的摘要,节省模型开销; - 敏感变量保护:
forbidden_variables参数会注入提示词中的「禁止记忆变量定义」,与 memory_analysis_prompt.md 中的任务说明配合,约束模型不得提取明确列出的敏感变量。
3.3 期望的模型输出
分析阶段期望模型返回如下纯 JSON(保留```json代码块标记):
{ "has_key_information": true, "variables": [ {"variable_key": "nickname", "variable_value": "小王"} ], "summary": "用户昵称是小王" }对应行为已被 MemoryAnalyzerTest.java 覆盖验证,包括:forbidden_variables注入到提示词、空白值归一化为None、以及变量列表的正确解析。
四、LongTermMemoryExtractor:长期片段记忆提取
LongTermMemoryExtractor使用提示词与模型调用,把消息提取为长期片段记忆的分类结果,同样是final工具类(见 LongTermMemoryExtractor.java):
public static CompletionStage<Map<String, Object>> extractLongTermMemory( ExtractMemoryParams extractMemoryParas, String timestamp, MemoryScopeConfig scopeConfig) public static CompletionStage<Map<String, Object>> extractLongTermMemory( ExtractMemoryParams extractMemoryParas, String timestamp, MemoryScopeConfig scopeConfig, int retries)4.1 消息组装策略
与MemoryAnalyzer不同,提取器会区分两类消息文本:
- 参考消息(
reference_messages):历史消息 + 当前消息全部拼接,供模型做指代消解; - 目标消息(
input_messages):仅收集当前消息中role == "user"的消息(appendReference中collectUserMessages开关控制,见 LongTermMemoryExtractor.java)。
消息行的格式为name: content,其中name优先取message.getName(),为空时回退到role。
4.2 时间上下文构造
buildTimeContext会把传入的timestamp(支持OffsetDateTime、LocalDateTime、LocalDate三种 ISO 格式)解析为日期,并推算「当前所在周」的周一到周日区间,输出形如2026年5月11日(周一)~2026年5月17日(周日)(即05.11~05.17)的中文周区间文本;解析失败时原样返回timestamp。该上下文会以current_week变量注入提示词,供模型做「下周/上周/上个月/X天前」等相对时间的推理基准。
4.3 提示词与输出结构
提示词通过PromptApplier加载 fragment_memory_prompt.md,注入conversation_time、input_messages、reference_messages、三类记忆定义与current_week。该模板定义了六步执行流程:
- 指代消解:识别第三人称代词与指示代词,回溯参考消息还原实体;
- 主体锁定:主语为「我/本人/我们」锁定为用户本人,其他主体单独处理,无主语则丢弃;
- 逻辑推理:知识推理 + 时间推理(下周/上周/上个月按「当前所在周」推算为绝对日期);
- 内容提取:逐句扫描、原子化拆分,排除高敏感信息与寒暄,按用户画像(
user_profile)、情景记忆(episodic_memory)、语义记忆(semantic_memory)、变更记忆指令(instruct_memories)四类归档; - 内容整理:隐私过滤、主语统一为「用户」、相对时间替换为绝对日期;
- 输出:返回纯 JSON。
期望的模型输出结构为:
{ "has_explict_instruct": true, "instruct_memories": [ { "mem_content": "标准的记忆内容陈述", "mem_type": "user_profile", "mem_instruct": "UPDATE", "old_mem": "被修改或删除的旧记忆" } ], "user_profile": [], "semantic_memory": [], "episodic_memory": [] }模型输出经JsonOutputParser解析为Map后返回;默认最多重试 3 次,连续失败返回空映射(Map.of()),对应实现见 LongTermMemoryExtractor.java。
五、Generator:总协调器与记忆单元生成
Generator是整个 extract 模块的编排入口,负责协调消息分析、摘要生成与长期片段提取,输出按记忆类型分组的BaseMemoryUnit列表(见 Generator.java)。
5.1 入参与必填校验
genAllMemory(Map<String, Object> kwargs)返回CompletionStage<Map<String, List<BaseMemoryUnit>>>,在独立的 IO 线程池(memory-generator-io)中异步执行。kwargs支持以下键:
| 键 | 类型 | 说明 |
|---|---|---|
messages | List<BaseMessage> | 本轮消息(必填) |
config | AgentMemoryConfig | 记忆配置(必填) |
user_id | String | 用户标识(必填) |
scope_id | String | 作用域标识(必填) |
base_chat_model | Model | 基础聊天模型(必填) |
history_messages | List<BaseMessage> | 可选历史消息 |
forbidden_variables | String | 可选禁止记忆变量 |
message_mem_id | String | 可选消息记忆 ID |
timestamp | String | 可选对话时间 |
summary_max_token | Integer | 可选摘要 token 上限 |
scope_config | MemoryScopeConfig | 可选作用域配置(含三类记忆定义) |
semantic_store | Object | 可选语义存储 |
方法要求messages、config、user_id、scope_id、base_chat_model同时存在;任一缺失都会记录MEMORY_PROCESS错误日志并返回空映射(见 Generator.java)。
5.2 生成流水线
genAllMemorySync的核心流程与文档描述一致:先分析,再按配置生成摘要与片段。
- 分析阶段:先调用
MemoryAnalyzer.analyze(...)(传入summaryMaxToken、scopeConfig、forbiddenVariables),得到MemoryAnalyzerResult; - 变量单元:
processExtractedData把非空变量值转成VariableUnit并按类型归组; - 摘要单元:若
config.isEnableSummaryMemory()为 true,通过dataIdGenerator.generateNextId(userId)生成新memId,构造SummaryUnit(含摘要文本、messageMemId、timestamp); - 片段记忆前置条件:若
!analyzeResult.isHasKeyInformation()直接返回——消息不含关键信息时不触发片段提取; - 片段记忆:
categoriesToMemoryUnit调用LongTermMemoryExtractor.extractLongTermMemory(...),将返回的分类结果按CATEGORY_TO_CLASS映射为MemoryType(user_profile → USER_PROFILE、semantic_memory → SEMANTIC_MEMORY、episodic_memory → EPISODIC_MEMORY),每个片段生成独立的FragmentMemoryUnit(OperationType.ADD),再逐条按fragmentEnable开关过滤后加入结果。
其中fragmentEnable由三个独立开关决定(见 Generator.java):
Map<String, Boolean> fragmentEnable = Map.of( MemoryType.USER_PROFILE.getValue(), config.isEnableUserProfile(), MemoryType.SEMANTIC_MEMORY.getValue(), config.isEnableSemanticMemory(), MemoryType.EPISODIC_MEMORY.getValue(), config.isEnableEpisodicMemory() );三种记忆类型在 MemoryType.java 中定义,FragmentMemoryUnit承载记忆内容、来源消息 ID、时间戳与操作类型(见 FragmentMemoryUnit.java)。
5.3 变更记忆指令(UPDATE / DELETE)
当模型输出的has_explict_instruct为 true 时,handleMemoryWithInstruct会处理instruct_memories中的 UPDATE/DELETE 指令:
- 按
mem_instruct拆分出待更新、待删除两条记忆列表; processMemoryOperations以old_mem为查询构造SearchParams(topK=1,检索三种记忆类型),调用SearchManager做语义检索并按score降序取最优命中;semanticValidation通过semantic_validation提示词让模型校验检索结果是否与old_mem语义一致(输出含CORRECT且不含WRONG才通过),校验通过后生成对应OperationType的FragmentMemoryUnit。
整个片段生成过程用try/catch兜底:捕获NullPointerException(属性异常)、IllegalArgumentException(取值异常)与其他RuntimeException,分别记录 debug/warning 日志后返回已生成的结果,不中断主流程(见 Generator.java)。
5.4 输入兼容性
从测试与实现可见,Generator对模型的片段输出保持较强兼容性:片段数组元素既可以是纯字符串,也可以是{"content": "..."}形式的对象(取content字段,缺失时回退为String.valueOf),该行为在 GeneratorTest.java 中有明确断言。
六、AgentMemoryConfig:控制提取行为的配置开关
MemoryAnalyzer与Generator的取舍都围绕AgentMemoryConfig展开,其完整字段与默认值见 AgentMemoryConfig.java:
| JSON 字段 | Java 字段 | 默认值 | 作用 |
|---|---|---|---|
mem_variables | memVariables | 空列表 | 预定义的可提取记忆变量(List<Param>,含变量名与描述),驱动variables_define_template与variables_output_template。 |
enable_long_term_mem | enableLongTermMem | true | 总开关,关闭后Generator直接跳过摘要与片段记忆生成。 |
enable_user_profile | enableUserProfile | true | 是否生成用户画像片段记忆。 |
enable_semantic_memory | enableSemanticMemory | true | 是否生成语义记忆片段。 |
enable_episodic_memory | enableEpisodicMemory | true | 是否生成情景记忆片段。 |
enable_summary_memory | enableSummaryMemory | true | 是否生成摘要记忆。 |
此外还提供兼容方法isEnableFragmentMemory(),返回三个片段开关的「或」结果,供既有调用方判断是否需要片段提取能力。配置类同时支持无参构造与Builder链式构建,例如:
AgentMemoryConfig config = AgentMemoryConfig.builder() .memVariables(List.of(Param.string("nickname", "user nickname", false))) .enableSummaryMemory(true) .enableEpisodicMemory(false) .build();注意:当enableLongTermMem或enableSummaryMemory关闭时,MemoryAnalyzer返回的summary会被清空;关闭enableUserProfile等片段开关后,即使模型输出了对应分类内容,Generator也会在归组时将其过滤掉。
七、提示词模板与 PromptApplier
MemoryAnalyzer与LongTermMemoryExtractor都通过 PromptApplier.java 组装提示词。PromptApplier从 classpath 的openjiuwen/core/memory/prompts目录按文件名前缀加载 Markdown 模板(如fragment_memory_prompt.md),内部用ConcurrentHashMap缓存PromptTemplate,支持apply(filePrefix, variables)模板渲染与clearCache()清理。
当前仓库 resources 下共有 4 个记忆提示词模板:
fragment_memory_prompt.md:长期片段记忆提取(六步执行流程 + 变更指令识别);memory_analysis_prompt.md:消息分析与变量/摘要提取;memory_update_check.md:记忆更新校验;semantic_validation.md:UPDATE/DELETE 指令的语义一致性校验。
八、完整调用链与行为总结
将以上组件串联起来,一次记忆提取的完整调用链如下:
genAllMemory(kwargs) └─ MemoryAnalyzer.analyze(...) // 分析:关键信息标记 + 变量 + 摘要 └─ PromptApplier.apply("memory_analysis_prompt", ...) └─ Model.invoke(...) → JsonOutputParser ├─ processExtractedData(variables) // 变量 → VariableUnit(非空才转) ├─ (enableSummaryMemory) // 摘要 → SummaryUnit ├─ (hasKeyInformation) │ └─ LongTermMemoryExtractor.extractLongTermMemory(...) │ └─ PromptApplier.apply("fragment_memory_prompt", ...) │ └─ Model.invoke(...) → JsonOutputParser │ ├─ CATEGORY_TO_CLASS 分类映射 // → FragmentMemoryUnit (ADD) │ └─ instruct_memories 处理 // UPDATE/DELETE:SearchManager 检索 + semanticValidation └─ Map<MemoryType, List<BaseMemoryUnit>>围绕该模块的三个关键行为(与原文档互相印证):
- 先分析后生成:
Generator.genAllMemory(...)会先调用MemoryAnalyzer,再根据AgentMemoryConfig的开关决定是否生成摘要与片段记忆; - 统一提示词与重试机制:
LongTermMemoryExtractor与MemoryAnalyzer都通过PromptApplier组装提示词,并默认最多重试 3 次模型调用,连续失败时分别返回空映射或空白结果对象; - 轻量数据对象:
ExtractMemoryParams、MemoryAnalyzerResult、VariableResult均面向流程编排设计,仅承载字段数据,不包含业务逻辑。
对开发者而言,若要接入该提取流程,最直接的入口是Generator:构造DataIdManager(可选加SearchManager)后,在kwargs中补齐messages、config、user_id、scope_id、base_chat_model五个必填项即可异步获得按记忆类型分组的BaseMemoryUnit列表;若只想要「变量 + 摘要」能力,可直接调用MemoryAnalyzer.analyze(...);若只需要片段分类结果,则可直接调用LongTermMemoryExtractor.extractLongTermMemory(...)。各类型的字段语义、重试默认值与配置开关均可在本文引用的源码与测试中进一步核对。
- 人工智能
- AI Agent
- Agent 框架
- 工具调用
- Agent 工作流
- RAG
- MCP Clients
- 强化学习
【免费下载链接】agent-core-java
openJiuwen agent core Java是 openJiuwen Core的 Java版本,提供AI Agent开发、运行、调优与演进相关的全套SDK能力。
相关推荐
agent-core-java 长期记忆提取器 LongTermMemoryExtractor 源码解析:从对话消息到分类片段记忆
agent core java 长期记忆提取器 LongTermMemoryExtractor 源码解析:从对话消息到分类片段记忆 LongTermMemory
人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习DLSS Swapper:9 种 DLL、8 个游戏库,不更新游戏也能切换缩放版本
DLSS Swapper:9 种 DLL、8 个游戏库,不更新游戏也能切换缩放版本 如果你的游戏还停在上一代 DLSS,而新版早就发布,你又不想等厂商推送补丁、
桌面应用agent-core-java 记忆引擎 Generator 类详解:对话消息分析、摘要与长期片段提取的协调中枢
agent core java 记忆引擎 Generator 类详解:对话消息分析、摘要与长期片段提取的协调中枢 Generator 是 openJiuwen
人工智能AI AgentAgent 框架工具调用Agent 工作流RAGMCP Clients强化学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考