[中文](./README.md) | [English](./README_EN.md) ![Wangdefa.Memory Banner](./docs/images/WangdefaMemory_banner.png) ## Wangdefa.Memory **本地优先的 Agent 五层记忆体组件** [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![.NET](https://img.shields.io/badge/.NET-10.0-purple.svg)](https://dotnet.microsoft.com/) [![NuGet](https://img.shields.io/badge/NuGet-v1.1.9-orange.svg)](https://www.nuget.org/packages/Wangdefa.Memory/) [![DSH Plugin](https://img.shields.io/badge/DSH-Plugin-blue.svg)](https://github.com/topics/dsh-plugin) --- ## 📄 更新说明 详见 [CHANGELOG.md](./CHANGELOG.md) --- ## 📖 项目简介 Wangdefa.Memory 是一个为本地数字分身 Agent 设计的“理解型”五层记忆体组件,数据完全保留在本地,不依赖云端,目标达到轻量部署、白盒可控、可解释、置信可管,未来将进一步往企业级原生记忆体方向拓展。 Wangdefa.Memory 选择了无向量记忆体方向(不排除未来有弱向量辅助),将记忆模拟人类思考结构,分为**认知、特征推演、思考、阅历、传递**五层。 我们认为记忆来源于对事件特征的识别与记录,特征记忆是人类与机器之间能找到的记忆共性,而机器的优势在于能记住大量特征标签,所以这个项目希望以特征记忆能力为主要核心,让 Agent 趋向「像人一样理解用户,记住用户」的能力。 > 记忆体负责存储、检索和演化长期记忆及自我沉淀,并实现自我清理迭代,通过长期累计配合,让你的 Agent 用得越久越理解你,可以更好的理解你的潜在需求,逐渐成为你的本地“数字分身”。 > **状态:早期阶段(Early Stage)** - 核心功能已完成,正在优化推演逻辑。欢迎试用和反馈。 --- ## Wangdefa.Memory 设计思路 ### 大家都在卷什么 现在的记忆体越来越多,不管插件还是框架,卷的方向算高度一致:召回精确,精准识别。 怎么召得更准,怎么认得更精?毫无疑问这方面技术未来会越来越完善。 然而,**召回的准确,是否等同于召回的"有用"?** 精确召回的本质是搜索。搜得再准,它也是搜索。你问一句话,系统把"相关"的内容全塞进来,这错了吗?并没有。但需要吗?不好说。 什么是人真正想要的? 我个人认为,是LLM会像人类一样,不是召回就塞入大量的信息,这不仅显得信息过量,同时也消耗了大量的无效token,而根据聊天的需要召回“有效、有关联”的东西,个人认为才是真正的记忆体。 ### 人的记忆怎么进行的? 人的记忆核心是**感知驱动**。 永远是先感知对方的需求和意图,再决定调用什么层次的记忆来回应。 如果你在与闲聊的时候,对方问了你大概,这时候应该是用认知进行第一反应回复;而如果你塞了一堆起因经过结果,的事件背景给对方,这听起来就很扯淡了。 所以人在回忆某件事的时候,脑子里先出来的是个大概轮廓,不是全文。 只有深入讨论的时候,才需要把完整细节调出来。 按**浅、中、深,三层记忆深度提取记忆。**这才应该是人类记忆的响应: - 浅:只要给到意图,通过一个认知摘要回复即可。 - 中:需要事件的概要和内容的概览 - 深:代表需要提取整体事件的完整内容 人从来不是先"检索"再"回答"的。人是先"感知"再"驱动"。 ### 记忆是什么 我认为是记忆特征。 人类对记忆的检索都是基于特征获取的。 你记住的一个画面的细节,或者记住一个对话的关键词,乃至于你记住的一串独特数字,都是这个记忆的特征,不同维度的特征组成了一张记忆画面。 比如某个下午的会议,时间、空间、参与人、主题、起因、经过、结果,乃至于天气如何、桌上摆着一瓶花,会议屏幕长什么样?遥控是否坏了?都是这个时空下的记忆特征。 由这些记忆特征共同构建了一个事件画面,人从这个画面中提取了大概的过程,又接着在脑子里提取了一份会议事件的摘要。 这就是整个记忆的组成结构。 恰巧,记忆对于特征标签的记忆与人类的记忆特性是一致的, 而机器的优势在于,他能记住人类所无法记住的大量各异标签。 ### 为什么不用向量 因为人脑子里没有余弦相似度。 人想起一件事,永远是特征触发的。一个声音、一张脸、一个味道,"想起来了"。跟向量没有半毛钱关系。 向量是把高维特征压缩成低维向量。但你已经用特征了,就不需要向量了。 另外在事件的关联性上,人类的脑子是更微妙的直观感知记忆,通过认知直接焊死了两者的关联性。 我认为就是人脑子里的特征标签在自动处理推演。 所以特征标签,可解释、可编辑、轻量。 你知道为什么召回,人可以改,不需要 Embedding 模型和向量库。 ### LLM 该干什么 LLM 的语言理解能力已经到一定水平了。准确理解人类语言,即便现在还有瑕疵,未来也会越来越好。 那么LLM需要的就不会再是一个精准的记忆搜索工具,而是用户的意图推演修正辅助; 而记忆体真正该做的,就是作为**意图推演+记忆思路+用户偏好**的修正辅助而存在。 读懂用户——什么状态、什么情绪、什么意图、需要哪个层次的信息。然后把感知结果交给引擎去匹配特征、召回记忆。 语义理解交给 LLM,特征匹配交给引擎。 各司其职。 ### 我要做什么 基于对 LLM 未来能力的预期,设计了 Wangdefa.Memory。 两个核心理念: **感知驱动理解** —— 先感知意图,再决定调哪个层次的记忆。不盲目塞信息,尽量不浪费 token。 **记忆资产沉淀** —— 每一次对话都是一次积累。记忆越用越多,系统越来越懂你。最终是一个本地数字分身,同时沉淀属于你自己的个人记忆资产。 ### 关于WangdeMemory如何运作 目前以ABC三条线路进行运行; A线:意图感知 + 语义解析(只读) 1. 先判断输入文体。(人类语言离不开记叙、议论、说明、意识流、散文等主要文体),文体判断不是装饰,它决定意图推测的方向。 2. LLM 做意图分析,输出感知信息(场景/场景细分/情绪/状态/语境)、路由决策(浅/中/深)、记忆特征推测标签。 3. A线推测的标签用于检索线索,命中已有标签则取用,未命中则留给 C线统一处理(A线不写标签池)。 4. 引擎做多轮拓展匹配(含三级关联扩展),找出潜在关联的认知卡片,按置信度推给 B 线。 5. B 线开始前,A 线先建一张认知卡片框架占位。B 线完成后,C 线补全。 B线:内容生成 接收 A 线的感知结果、路由层级、关联记忆、用户偏好,LLM 生成回复,流式输出。 C线:学习与沉淀(异步,不阻塞用户) 1. 记录完整事件 2. 写概览与概要 3. 补全卡片标签、摘要、指针、场景定稿 4. 标签治理:同义标签**建立三级关联**(同义/相关/弱相关)并存,不退场 5. 泛用词拦截:无区分度的词转为**弃用状态**,退出召回 6. 版本对齐:对使用到的残缺标签补全定义与维度 7. 修正偏好与反馈 --- ## ✨ 核心特性 | 特性 | 说明 | |------|------| | **五层记忆架构** | 认知层 / 特征推演 / 思考层 / 阅历层 / 传递层 | | **特征推演引擎** | 标签池 + 密码簿 + 特征统计 + 时间衰减,让记忆通过认知驱动 | | **场景系统** | 场景大类+细分独立存储,可持续积累;检索时同场景记忆优先 | | **两阶段写入** | 先写框架(pending),后补全(completed),支持状态标记 | | **自我迭代** | 权重衰减 + 定期清理 + 标签演化,高频记忆自然沉淀,低频记忆自动遗忘 | | **偏好与反馈闭环** | 偏好和反馈独立提取、独立存储,反馈感知检索 | | **意图驱动检索** | 根据意图决定记忆注入深度(shallow / medium / deep) | | **关联式标签共存** | 三级关联(同义 / 相关 / 弱相关)替代消灭式合并,保住召回入口 | | **标签生命周期** | 待审 → 在役 / 弃用 / 已合并,状态驱动召回与治理 | | **双线读写边界** | A 线只读、C 线唯一写入,标签池不被检索路径污染 | | **可逆性设计** | LLM 只做可逆动作(建关联 / 状态控制 / 版本对齐),不可逆合并留给人工 | | **版本对齐自愈** | 以模型为基准,标签在使用中被被动补全与修正,无需离线批处理 | | **标签质量约束** | 禁止泛用词,要求标签可定位,数量收紧到 2-4 个 | | **统一存储** | 所有写入收敛到统一入口,原子写入,断电不损坏 | | **本地优先** | 所有数据存储在本地 SQLite + JSON | | **轻量依赖** | 仅依赖 SQLite + System.Text.Json | | **MCP 适配** | 支持通过 MCP 协议接入 DSH,提供 ProcessMessage / SaveMemory 工具 | --- ## 📦 NuGet 安装 ```bash dotnet add package Wangdefa.Memory ``` --- ## 🔌 DSH 一键安装 在 DSH 环境中执行以下命令即可完成安装: ```bash dsh plugin add github:VinsonWild/Wangdefa.Memory ``` 安装后启动 DSH,记忆体将自动工作: - 对话时自动检索历史记忆并注入上下文 - 对话结束后自动保存记忆 首次启动会自动下载引擎,无需额外配置。 ### 前置条件 - [.NET 10.0+](https://dotnet.microsoft.com/download) - DSH 已配置 `DEEPSEEK_API_KEY`(插件会自动复用) ### 使用示例 **第一次对话(写入记忆):** ``` 你:我喜欢用简洁的代码风格,变量名要清晰。 DSH:好的,已记录你的偏好。 ``` **后续对话(自动召回记忆):** ``` 你:帮我重构一下这个项目的代码。 DSH:好的,根据你偏好的简洁风格,我建议... ``` 记忆体自动完成检索、注入和保存,无需手动调用任何工具。 **2. 补全记忆(填内容)** 拿到 `frameId` 后,调用 `save_memory` 补全: ``` mcp__WangdefaMemory__save_memory 好的,已记录你的偏好 认知_20260819_143022 completed ``` 返回示例: ```json { "success": true, "message": "记忆已补全并保存,cardId: 认知_20260819_143022,状态: completed" } ``` **3. 查询记忆** 下次对话时,记忆体会自动检索相关记忆: ``` mcp__WangdefaMemory__process_message 写代码时要注意什么 ``` 如果命中,返回的 `hasMemory` 为 `true`,`memory` 字段包含摘要和标签。 ### 状态说明 | 状态 | 含义 | |------|------| | `pending` | 框架已建,内容待补全 | | `completed` | 已补全,可被检索 | | `interrupted` | 补全中断 | | `failed` | 补全失败 | --- ## 🚀 快速开始(.NET 开发者) ### 1. 初始化记忆体 ```csharp using Wangdefa.AgentMemory; using Wangdefa.AgentMemory.Models; using Wangdefa.Contracts; var chatService = new MyChatService(); var basePath = Path.Combine(Directory.GetCurrentDirectory(), "memory"); ServiceRegistry.Initialize(chatService, basePath); var memory = ServiceRegistry.GetWangdefaMemory(); ``` ### 2. 写入记忆(两阶段) ```csharp // 阶段一:写框架 var frameId = await memory.WriteMemoryFrame( topicId: "demo", userInput: "我喜欢用简洁的风格写代码", perception: new PerceptionModel { Scene = "工作", SceneSub = "代码评审" }, tags: new List { "代码风格", "简洁" }, route: "shallow" ); // 阶段二:补全 await memory.CompleteMemory( cardId: frameId, userInput: "我喜欢用简洁的风格写代码", agentResponse: "好的,已记录你的偏好", status: "completed" ); ``` ### 3. 查询记忆 ```csharp var result = await memory.CognitiveMatch( input: "写代码时要注意什么", semanticTags: null ); if (result != null) { Console.WriteLine($"匹配到记忆: {result.Summary}"); } ``` --- ## ⚙️ 核心机制:特征推演引擎 记忆体的核心是 **特征推演引擎(FeatureEngine)**,负责记忆的匹配和排序。 ### 特征推演三件套 | 组件 | 存什么 | 回答什么问题 | |------|--------|-------------| | **标签池(TagDictionary)** | 所有标签 + 定义 + 近义词 + 三级关联 + 状态 | "这个标签存在吗?它的 code 是什么?它和谁有关联?" | | **密码簿(PasswordBook)** | code → 卡片ID 列表 | "这个标签关联了哪些卡片?" | | **特征统计(FeatureStats)** | 每张卡片 → 它有哪些标签 | "这张卡片有哪些标签?" | 推演流程: 用户输入 → 推测特征标签 → 查标签池拿到 code(含重定向与关联扩展)→ 查密码簿拿到卡片ID → 通过特征池确认卡片有哪些标签 → 多轮拓展推演关联 → 计算匹配强度 ### 匹配流程 1. **标签匹配**:用标签名查标签池,命中则拿 code;已合并的标签自动重定向到目标标签 2. **近义匹配**:用近义词扩展匹配范围 3. **关联扩展**:按三级关联扩展召回(见下节「标签治理机制」) 4. **密码簿查询**:用 code 查密码簿,拿到卡片ID列表 5. **特征池匹配**:确认卡片实际包含哪些标签,计算匹配强度 6. **时间衰减**:匹配强度 × `exp(-0.05 × 天数)`,新记忆优先 7. **反馈修正**:confirmed 加分,rejected 丢弃,ignored/partial 中性 8. **场景加权**:大类命中 +0.1,细分命中再 +0.1 9. **状态过滤**:只返回 `completed` 状态的卡片 10. **排序返回**:按最终权重降序返回 TopN --- ## 🏷️ 标签治理机制 标签池是记忆体的召回入口。它如何演化,直接决定记忆"能不能被想起来"。 ### 为什么不做消灭式合并 LLM 天然会输出同义不同名的标签:`标签池` / `标签池管理` / `标签库`。 早期做法是合并它们,让标签池保持整洁。但这条路有问题: > **标签池的目标不是「干净」,而是「召回全」。** 合并意味着删掉一个入口。用户下次说的恰好是被删掉的那个词,就再也找不到这条记忆了 —— 为了整洁牺牲召回,得不偿失。 所以现在改为**关联式共存**:不消灭标签,而是建立关联,让它们互相能找到。 ### 三级关联 > **适用范围**:同义不同名的**有效标签**(如 `标签池` / `标签库`)。 > 泛用词不走关联 —— 它们无区分度,走的是**弃用**(见「标签生命周期」)。 | 等级 | 语义 | 检索行为 | |------|------|----------| | `synonym` | 同义(可互替) | 可多跳扩展,上限 3 跳 | | `related` | 相关(有关联但不等价) | 仅扩展 1 跳 | | `loose` | 弱相关(仅记录) | 不参与扩展 | **写入是双向的** —— 任一方被命中都能找到对方。 **等级只升不降** —— `loose → related → synonym` 允许升级,反向不允许。 **边界严守**: - 目标标签必须已存在,不因建关联而新增标签行 - 禁止自环 - 关联写入只改 `RelatedCodes`,不改状态 这条边界很关键:历史上曾因「近义词递归建标签」产生过永久待审的死循环。 ### 标签生命周期 | 状态 | 含义 | 是否参与召回 | |------|------|--------------| | `unexamined` | 新建,待 C 线判定 | ✅ | | `active` | 在役 | ✅ | | `deprecated` | 已弃用(泛用词等) | ❌ | | `merged` | 已被合并到其他标签 | ✅(作为重定向路标) | **`merged` 保留在缓存中是刻意的** —— `MergedTo` 指向目标标签,旧名字靠它一跳重定向,是"活路标"而非"废弃残留"。 **`deprecated` 则从缓存中剔除** —— 它没有任何指向,不该再被召回。 **两种治理手段的区别**: | 手段 | 对象 | 结果 | |------|------|------| | 建立关联 | 同义不同名的**有效标签** | 都保留,互相能找到(召回更全) | | 转为弃用 | 无区分度的**泛用词** | 退出召回(召回更准) | 前者是"舍不得丢入口",后者是"留着只会添噪" —— 两者的判断依据都是同一个问题:**它是否能独立指向一类记忆**。 ### 双线读写边界 | 线路 | 权限 | 说明 | |------|------|------| | **A 线**(检索) | 只读 | 命中的标签直接取用;未命中的只记录,绝不写标签池 | | **C 线**(学习) | 唯一写入者 | 标签的新增、激活、弃用、关联、版本对齐均由 C 线完成 | **为什么必须分开**:如果检索路径能写标签池,"用户提到一个不存在的词"就会变成"凭空创建一个标签",最终标签池会被检索行为污染,且难以追溯来源。 ### 可逆性原则 > **LLM 只做可逆的动作,不可逆的交给人工。** | 动作 | 可逆? | 执行者 | |------|-------|--------| | 建立关联 | ✅ 可撤销 | LLM(C 线) | | 状态控制(激活/弃用) | ✅ 可回滚 | LLM(C 线) | | 版本对齐(补定义/维度) | ✅ 可覆盖 | LLM(C 线) | | **合并标签** | ❌ 不可逆 | **人工 / 管理接口** | 合并会搬移卡片、转移语义、废弃源标签,一旦出错很难还原。因此不交给 LLM 自动执行,但从关联中仍可获得合并建议。 ### 版本对齐(被动自愈) 标签会随系统演进而变化:字段新增、格式调整、语义补充。历史标签不可能一次性全部迁移。 做法是**以 C# 模型为基准**,让标签在使用过程中自愈: 1. **检测**:A 线顺路检查命中的标签是否残缺(缺定义、缺维度、旧格式) 2. **上报**:残缺标签随卡片补全流程交给 C 线 3. **对齐**:C 线按当前模型补全或迁移,**只写实际出现的字段,空值不覆盖** **为什么要"被动"**:不阻塞主流程、不需要离线批处理、只修真正被用到的标签 —— 冷门标签不必提前处理,热门标签会自然收敛。 > 版本判断永远以代码模型为准,不手写版本规则。模型升级时,只需改模型一处。 --- ## 🏗️ 架构图 ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ 记忆体架构 │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 对外接口(IWangdefaMemory) │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 核心:特征推演引擎(FeatureEngine) │ │ │ │ │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ │ │ │ 标签池 │ │ 密码簿 │ │ 特征统计 │ │ │ │ │ │ TagDictionary │ │ PasswordBook │ │ FeatureStats │ │ │ │ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ │ │ │ │ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ 场景库(SceneStore) │ │ │ │ │ │ 场景大类 + 细分,独立存储,可持续积累 │ │ │ │ │ └───────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 认知层(CognitiveReader) │ │ │ │ │ │ │ │ 特征推演返回的卡片ID → 加载认知卡片 → 叠加反馈/场景权重 → 返回结果 │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 存储层(L2 + L3) │ │ │ │ │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ 思考层 │ │ 阅历层 │ │ 知识层 │ │ │ │ │ │ ThinkingStore │ │ EventStore │ │ KnowledgeStore │ │ │ │ │ │ │ │ MemorySink │ │ │ │ │ │ │ │ 分流索引 │ │ 事件存储 │ │ 概览+摘要 │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 🧩 各层职责 | 层级 | 名称 | 核心组件 | 职责 | |------|------|----------|------| | **L1** | 认知层 | `CognitiveReader` | 负责语义提取后快速读取认知卡片,通过特征推演检索记忆 | | **L2** | 思考层 | `ThinkingStore` | 负责考虑内容深度和学习存储,进行分流索引,并记录「去哪找」 | | **L3** | 阅历层 | `EventStore`、`KnowledgeStore`、`MemorySinkService` | 存储每一次交互的事件、知识的完整内容、概览和概要,并进行认知卡片的写入 | | **L4** | 特征推演 | `FeatureEngine`(标签池 + 密码簿 + 特征统计 + 场景库) | 标签匹配、近义扩展、关联扩展、场景加权、时间衰减排序 | | **L5** | 传递层 | 内置于 `Middleware` | 根据 `route` 决定记忆注入深度(shallow / medium / deep) | --- ## 📂 存储目录结构 ``` memory/ ├── wangdefa_memory.db ← SQLite 主库(记录检索用) ├── feature_pool.db ← 标签池 + 密码簿 + 特征统计 ├── scene_store.db ← 场景库(大类 + 细分) ├── cognitive/ │ └── records/ │ └── 认知_xxx.json ← L1 认知层(含 Status 状态标记) ├── experience/ │ ├── events/ │ │ └── 2026-08-10/ │ │ └── 事件_xxx.json ← L3 阅历层(事件) │ └── knowledge/ │ └── {topicId}/ │ ├── 概览_xxx.json ← L3 阅历层(知识) │ └── 摘要_xxx.json ← L3 阅历层(知识) └── thinking/ └── chat/ └── {topicId}/ └── 记录_xxx.json ← L2 思考层(分流索引) ``` --- ## 🔁 数据流 ### 写入流程(两阶段) ``` 阶段一:写框架(WriteMemoryFrame) 用户输入 → A线 推测标签 → 中间件 → 写框架(Status = pending) ├── 创建认知卡片(标签 + 感知信息 + 场景候选) ├── 写入密码簿(code → 卡片ID) └── 返回 frameId 阶段二:补全(CompleteMemory) Agent 生成回复 → 调用 SaveMemory(frameId, agentResponse) ├── 填充 Summary ├── 更新 Status → completed / interrupted / failed ├── 场景定稿(C线为主、A线兜底) ├── 标签治理(建立三级关联 / 泛用词转弃用) ├── 版本对齐(补全残缺标签的定义与维度) ├── 更新特征统计 └── 记忆可被检索 ``` ### 查询流程 ``` 用户输入 → A线 推测标签 → 中间件 ├── 标签匹配(含已合并标签重定向) ├── 近义扩展 + 关联扩展(同义多跳 / 相关 1 跳 / 弱相关不扩展) ├── 特征推演检索(标签匹配 + 时间衰减 + 反馈修正 + 场景加权) ├── 状态过滤(只返回 completed 卡片,弃用标签不参与召回) └── 返回 CognitiveMatchResult ``` --- ## 📝 接口说明 ### IWangdefaMemory | 方法 | 说明 | |------|------| | `CognitiveMatch()` | 根据语义标签匹配记忆(`semanticTags` 可空,空则自动提取) | | `CognitiveMatchByCodes()` | 根据标签 code 匹配记忆(支持场景参数) | | `CognitiveMatchTopN()` | 匹配多条记忆,返回 TopN | | `WriteMemoryFrame()` | 写框架(状态 pending),返回 frameId | | `CompleteMemory()` | 补全卡片,更新状态和内容(可传入残缺标签列表) | | `SinkAsync()` | 一次性写入(兼容旧模式) | | `AddTag()` | 添加标签 | | `AddTagWithSynonyms()` | 添加标签(含近义词) | | `GetTagCode()` | 获取标签 code(`merged` 标签自动重定向,`deprecated` 返回 null) | | `GetTagCodeByTagAndDefinitions()` | 按标签名 + 释义列表匹配 code(用于消歧) | | `GetTagEntryByCode()` | 获取标签条目 | | `GetRelations()` | 获取标签的三级关联(同义 / 相关 / 弱相关) | | `IsMalformed()` | 判断标签是否为残缺状态(缺定义 / 缺维度 / 旧格式) | | `ExecuteEvolutionAsync()` | 执行标签演化(激活 / 弃用;合并请走管理接口) | | `CleanMemoryAsync()` | 清理低权重记忆 | | `GetSourcePathAsync()` | 获取指定主题与记录下的概览路径 | | `GetOverview()` | 获取概览 | | `GetFullText()` | 获取原文 | | `DeepSearch()` | 深度检索 | --- ## 🤝 贡献 欢迎贡献!请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解详情。 1. Fork 本仓库 2. 创建你的分支 (`git checkout -b feature/amazing-feature`) 3. 提交你的修改 (`git commit -m 'Add some amazing feature'`) 4. 推送到分支 (`git push origin feature/amazing-feature`) 5. 提交 Pull Request ### 要求 - 所有测试必须通过 (`dotnet test`) - 新功能需要包含测试 - 保持代码风格与现有代码一致 --- ## 📄 License Apache License 2.0 © 2026 Wangdefa Memory Contributors See [LICENSE](LICENSE) for details.