news 2026/9/28 19:55:44

Operit 记忆提取附加规则:为长期记忆库自定义入库范围、分类与表达偏好

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Operit 记忆提取附加规则:为长期记忆库自定义入库范围、分类与表达偏好
  • AI Agent
  • 人工智能
  • 大模型
  • AI 应用
  • 工具调用
  • 本地部署
  • MCP Clients
  • Agent 记忆

【免费下载链接】Operit

The most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent

项目地址:https://gitcode.com/gh_mirrors/op/Operit
点击查看免费下载

导读

Operit 的长期记忆库原本只使用内置知识图谱提示词进行自动与手动 AI 整理,用户无法限定入库范围、分类偏好或文本写法。本文介绍"记忆提取附加规则"(Memory Extraction Custom Rules)功能的完整实现:它允许用户在每个记忆空间独立保存一段文本规则,由自动保存调度器与手动更新共用,在知识图谱提取提示词中以受控标签注入,同时保持内置长期价值筛选与严格 JSON 输出协议不变。读完本文,你将掌握该功能的存储结构、UI 入口、保存链路、提示词注入方式,以及如何编写一份高质量的记忆提取规则。

背景:旧实现的局限与意图修正

旧实现的限制

在引入附加规则之前,记忆库的设置链路存在明确的短板(见 01_settings_and_prompt_integration.md):

  • 记忆库设置只保存检索权重(关键词 / 标签 / 向量 / 边权重)、自动保存间隔和嵌入模型配置三类内容;
  • 自动保存与手动更新都会进入MemoryLibrary.generateAnalysis生成知识图谱,但知识图谱提示词不接受用户规则。

其结果正如 index.md 所描述:长期记忆的自动与手动 AI 整理只使用内置知识图谱提示词,用户无法限定入库范围、分类偏好或文本写法。

意图修正

本次修改确立了三项目标:

  1. 在当前记忆空间的偏好中保存文本规则——规则按记忆空间(profileId)隔离存储;
  2. 在自动保存设置区的间隔说明下方提供多行编辑框——入口位于记忆库设置的"自动保存"分组内;
  3. 在知识图谱提取提示词中,将规则限定为入库范围、分类和表达偏好——规则只能细化这三个维度,继续要求严格 JSON 输出。

预期结果同时被明确为三条可验收标准:

  • 切换记忆空间时显示各自独立的规则;
  • 自动保存与手动更新使用相同规则;
  • 恢复默认时清空该记忆空间的规则。

存储层:按记忆空间隔离的规则持久化

规则的持久化落在 MemorySearchSettingsPreferences.kt 中。该类以profileId为粒度创建 SharedPreferences 文件:

class MemorySearchSettingsPreferences(context: Context, profileId: String) { private val searchPrefs = context.applicationContext.getSharedPreferences( "memory_search_settings_$profileId", Context.MODE_PRIVATE ) // ... companion object { private const val KEY_MEMORY_EXTRACTION_CUSTOM_RULES = "memory_extraction_custom_rules" const val DEFAULT_MEMORY_EXTRACTION_CUSTOM_RULES = "" } }

关键实现细节(MemorySearchSettingsPreferences.kt):

  • loadMemoryExtractionCustomRules():从 SharedPreferences 读取memory_extraction_custom_rules键,默认值为空字符串DEFAULT_MEMORY_EXTRACTION_CUSTOM_RULES = "";若取到 null 会抛出IllegalStateException以暴露异常状态;
  • saveMemoryExtractionCustomRules(rules: String):以apply()异步落盘写入该键;
  • 键名与存储文件memory_search_settings_$profileId均带 profileId 后缀,因此每个记忆空间的规则天然隔离,切换记忆空间时读取到的是各自独立的规则——这正是"切换记忆空间时显示各自的规则"这一预期结果的存储层保证。

值得注意的是,同文件中的自动保存间隔(KEY_AUTO_SAVE_INTERVAL_MINUTES,默认 5 分钟,允许范围 1~30 分钟)与规则共用一个搜索设置文件,这与"编辑入口放在自动保存设置分组中"的 UI 设计保持了一致。

UI 层:记忆库设置弹窗中的多行规则编辑入口

弹窗的输入承载

规则编辑入口位于记忆库设置的弹窗组件 MemorySearchSettingsDialog.kt 中。该弹窗新增了memoryExtractionCustomRules: String入参,并以本地状态承载编辑中的文本:

@Composable fun MemorySearchSettingsDialog( currentConfig: MemorySearchConfig, autoSaveIntervalMinutes: Int, memoryExtractionCustomRules: String, // ... onSave = { config, cloudConfig, autoSaveIntervalMinutes, memoryExtractionCustomRules -> ... } ) { var editedMemoryExtractionCustomRules by remember(memoryExtractionCustomRules) { mutableStateOf(memoryExtractionCustomRules) } // 自动保存分组内的多行编辑框(OutlinedTextField 多行形态) }

按照 01_settings_and_prompt_integration.md 的定位,该编辑框以多行文本框形态置于自动保存设置的间隔说明下方,即"自动保存分组"内。

弹窗的挂载与保存回调

弹窗由记忆库主界面 MemoryScreen.kt 挂载,保存回调同时把规则文本交给 ViewModel:

if (uiState.isSearchSettingsDialogVisible) { MemorySearchSettingsDialog( memoryExtractionCustomRules = uiState.memoryExtractionCustomRules, onSave = { config, cloudConfig, autoSaveIntervalMinutes, memoryExtractionCustomRules -> viewModel.saveSearchSettings(config, cloudConfig, autoSaveIntervalMinutes, memoryExtractionCustomRules) viewModel.searchMemories() }, // ... ) }

uiState.memoryExtractionCustomRules来自 ViewModel 的 UI 状态,切换记忆空间时由 ViewModel 重新加载,从而满足"切换记忆空间时显示各自的规则"。

保存链路:ViewModel 的读写与归一化

规则在 MemoryViewModel.kt 中完成读写闭环。

加载方向(loadSearchSettings,MemoryViewModel.kt):从searchSettingsPreferences.loadMemoryExtractionCustomRules()读取后写入_uiState,配合记忆空间切换即可在弹窗中展示当前空间规则。

保存方向(saveSearchSettings,MemoryViewModel.kt):一次保存同时落盘检索配置、自动保存间隔与附加规则:

fun saveSearchSettings( newConfig: MemorySearchConfig, newCloudConfig: CloudEmbeddingConfig, autoSaveIntervalMinutes: Int, memoryExtractionCustomRules: String ) { // 归一化检索配置与自动保存间隔(coerceIn 1..30 分钟) viewModelScope.launch(Dispatchers.IO) { searchSettingsPreferences.save(normalizedSearchConfig) searchSettingsPreferences.saveAutoSaveIntervalMinutes(normalizedInterval) searchSettingsPreferences.saveMemoryExtractionCustomRules(memoryExtractionCustomRules) repository.saveCloudEmbeddingConfig(normalizedCloudConfig) } }

"恢复默认"的语义在 01_settings_and_prompt_integration.md 中被定义为"清空该记忆空间的规则":由于DEFAULT_MEMORY_EXTRACTION_CUSTOM_RULES = "",恢复默认即把空字符串写入该空间的 SharedPreferences,规则随之失效。

提示词接入:规则如何在知识图谱提取中生效

读取与注入

规则真正影响记忆提取的路径在 MemoryLibrary.kt 的generateAnalysis(MemoryLibrary.kt)。该函数在构建候选记忆检索后,读取当前记忆空间的规则并传入提示词构建器:

val memorySearchSettings = MemorySearchSettingsPreferences(context, profileId) val searchConfig = memorySearchSettings.load() val memoryExtractionCustomRules = memorySearchSettings.loadMemoryExtractionCustomRules() // ... val systemPrompt = FunctionalPrompts.buildKnowledgeGraphExtractionPrompt( duplicatesPromptPart = duplicatesPromptPart, existingMemoriesPrompt = existingMemoriesPrompt, existingFoldersPrompt = existingFoldersPrompt, useEnglish = useEnglish, profileDocument = profileDocument, profileUpdateEnabled = profileUpdateEnabled, memoryExtractionCustomRules = memoryExtractionCustomRules )

这里可以清晰看到规则与既有检索机制的配合:本地混合检索策略(问题导向的紧凑查询 + 权重打分,取前 15 条候选记忆)先做粗筛,LLM 最终决策阶段才看到规则文本。规则不会改变本地检索打分,只作用于 AI 的知识图谱生成决策。

提示词中的受控注入格式

FunctionalPrompts.kt 的buildKnowledgeGraphExtractionPrompt(FunctionalPrompts.kt)将规则包裹在专用标签中注入提示词。中文版格式如下:

【用户指定的记忆提取附加规则】 <memory_extraction_custom_rules> $memoryExtractionCustomRules </memory_extraction_custom_rules> 使用这些规则细化记忆领域、入库重点、文件夹、标签或写法。写入前筛选、证据要求和严格 JSON 输出协议仍然必须遵守。

英文版([User-specified memory extraction rules])语义一致:"Use these rules to refine the memory domain, retention focus, folder selection, tags, or writing style. The selection gate, evidence requirements, and strict JSON output contract remain mandatory."

这段指令被插入在"【标题与内容写法】"与"【连接关系规则】"之间,位于整个提示词中段的规则区。两条红线始终生效:

  1. **规则只能细化(refine)**记忆领域、入库重点、文件夹选择、标签或写法——即文档所言的"入库范围、分类和表达偏好";
  2. 内置的写入前筛选(Selection gate)、证据要求与严格 JSON 输出协议保持强制——用户规则不能关闭内置筛选项,也不能放松 JSON schema 要求。

JSON 输出协议不受影响

提示词后半段的严格输出 schema 保持完整(FunctionalPrompts.kt):除{}外必须输出main、new、update、merge、links(开启资料自动更新时含profile_markdown);credibility、importance、weight必须是 0.0~1.0 的 JSON 数字。规则的注入不改变这一协议,AI 仍需返回合法 JSON 对象。服务端解析侧 MemoryLibrary.kt 的parseAnalysisResult对缺失字段、空值、越界浮点数均做严格校验,任何不符合协议的输出都会在解析阶段被拒绝。

自动保存与手动更新共用同一规则

自动保存链路

自动保存由 MemoryAutoSaveScheduler.kt 驱动:轮询器每 60 秒 tick 一次,按记忆空间检查候选消息数量(不足 5 条时继续累计),达到门槛后把同一会话内的候选消息按时间排序、分批(每会话每轮最多 20 条候选、单批最多 48 条消息)组装成对话历史,最终调用:

MemoryLibrary.saveMemoryNow( context = context, toolHandler = toolHandler, conversationHistory = conversationHistory, content = memoryContent, aiService = memoryService, profileIdOverride = profileId )

saveMemoryNow内部进入saveMemory→generateAnalysis,与手动更新走的是同一条提取函数。由于规则读取发生在generateAnalysis内部且以profileId为键,自动保存调度器无需任何额外改动即可复用当前记忆空间的规则——这正是"自动保存与手动更新使用相同规则"这一预期结果的实现原理。

手动更新链路

手动更新(如用户主动触发保存或记忆库工具的写入)同样调用MemoryLibrary.saveMemoryNow/saveMemoryWindowNow(后者支持自定义分析历史条数),因而也必然经过同一段规则读取与提示词注入逻辑。从源码结构看,任何进入generateAnalysis的路径——无论来源是自动调度器、手动保存还是窗口保存——都能获得一致的规则作用效果。

编写一份高质量的记忆提取规则

结合提示词注入段的措辞("细化记忆领域、入库重点、文件夹、标签或写法"),规则文本应围绕四个可控维度组织:

  1. 记忆领域(Domain):限定只关心哪些主题,例如"只记录与项目 A 相关的技术决策与依赖版本变化";
  2. 入库重点(Retention focus):说明高价值信号,例如"用户明确表达的偏好与约束优先入库;寒暄、天气、临时心情不入库";
  3. 分类偏好(Folder / tags):给出文件夹归属与标签习惯,例如"技术类记忆一律放入 folder_path 为tech/的目录,标签统一使用中文小写";
  4. 表达偏好(Writing style):约束内容写法,例如"content 用 2~3 句客观陈述,不写第一人称"。

需要注意的约束边界:

  • 规则不应试图关闭内置筛选(如"所有对话都入库"会被 Selection gate 拦截,常识性问答仍返回{});
  • 规则不应要求 AI 输出 JSON 以外的文本,输出协议强制为单一 JSON 对象;
  • 规则不应包含未来计划或推测内容——内置策略要求 content 只写"已发生事实 + 当前已确认状态";
  • 规则为空字符串时(默认状态),提示词注入段会插入空内容,功能退化为纯内置提示词行为,等价于旧实现。

验证与交付要点

依据 01_settings_and_prompt_integration.md 的验收清单,功能交付时需验证:

  • 切换记忆空间:在多个记忆空间分别填写不同规则并切换,弹窗中应分别显示各自保存的文本(存储层由memory_search_settings_$profileId文件隔离保证);
  • 自动保存与手动更新一致性:同一记忆空间下,观察自动保存调度器触发的入库结果与手动触发的入库结果在领域、分类、写法上符合同一份规则(两者共用generateAnalysis);
  • 恢复默认:执行恢复默认操作后,该记忆空间的规则被清空,再次打开弹窗显示空文本,后续提取恢复内置提示词行为;
  • 严格 JSON 协议:规则注入后,AI 输出仍必须符合main/new/update/merge/links的 schema,解析层校验不应出现回归。

总结

"记忆提取附加规则"在 Operit 中形成了一条完整、可验证的功能链路:存储层(MemorySearchSettingsPreferences.kt)按记忆空间隔离持久化规则文本 → UI 层(MemorySearchSettingsDialog.kt 与 MemoryScreen.kt)提供多行编辑入口 → ViewModel(MemoryViewModel.kt)完成读写闭环 → 提取核心(MemoryLibrary.kt 的generateAnalysis)在每次自动或手动提取时读取规则并注入提示词(FunctionalPrompts.kt 的buildKnowledgeGraphExtractionPrompt)。

该设计在放开用户定制能力的同时,通过"规则只能细化、不能覆盖"的措辞、内置 Selection gate 与严格 JSON 协议,守住了记忆图谱的事实质量底线。对于希望让 Operit 长期记忆更贴合自身工作流与偏好的用户,这是一项可直接上手配置的能力。

  • AI Agent
  • 人工智能
  • 大模型
  • AI 应用
  • 工具调用
  • 本地部署
  • MCP Clients
  • Agent 记忆

【免费下载链接】Operit

The most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent

项目地址:https://gitcode.com/gh_mirrors/op/Operit
点击查看免费下载

相关推荐

上一篇:Virtual-Display-Driver虚拟显示器驱动技术指南
下一篇:5步释放30GB!Czkawka跨平台系统清理工具新手入门教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 19:53:17

示波器还是高速采集卡?自动化测试场景下的选型指南

我有个老客户&#xff0c;年前找我聊测试平台升级的事情。他们研发部配了三台旗舰示波器&#xff0c;带宽都是500MHz往上走&#xff0c;测起波形细节来完全够用。可搭建自动化测试平台时&#xff0c;示波器这边的角色就尴尬了——人得定期去导数据、看波形、手动标记异常&#…

作者头像 李华
网站建设 2026/9/28 19:53:02

微信开源知识库系统:RAG与Agent结合的企业智能问答部署实践

1. 微信开源的这个知识库项目&#xff0c;到底解决了什么问题最近微信开源了一个知识库项目&#xff0c;技术圈讨论热度很高&#xff0c;很多做 RAG、做企业内部知识问答的同行都在转。先说结论&#xff1a;这不是一个简单的文档问答 Demo&#xff0c;而是一套把“文档解析、向…

作者头像 李华
网站建设 2026/9/28 19:52:56

Cadence Allegro 17.4元件库与原理图工程实战指南

Cadence Allegro 17.4这套工具&#xff0c;我用了快三年。中间踩过的坑&#xff0c;比我写过的笔记还多。经常有刚转硬件的朋友跑来问&#xff1a;原理图工程到底怎么建&#xff1f;元件库从哪来&#xff1f;为什么我自己画好的元件放到原理图里总报警告&#xff1f;这些问题看…

作者头像 李华