feat(plugins): consolidate official plugins with independent releases (LANG-180) (#2797)

Co-authored-by: multica-agent <[email protected]>
This commit is contained in:
RockChinQ
2026-10-28 17:32:24 +08:00
committed by GitHub
co-authored by multica-agent
parent d099033d79
commit 3a77306c3c
1144 changed files with 142049 additions and 130 deletions
@@ -0,0 +1,608 @@
# LongTermMemory issue planning
本文档记录 `langbot-longterm-memory` 插件后续优化计划。当前阶段的原则是:
- 不要求修改 LangBot core 或 langbot-plugin-sdk。
- 保持 LongTermMemory 作为插件实现,而不是把 memory 变成 LangBot 内置业务功能。
- 保留当前 L1/L2 两层架构,不急于引入 L0 goals、L3 procedural memory 等新事实层。
- 优先补齐生产可用性:写入策略、召回质量、治理、审计、整合、透明性。
## Current position
当前实现已经满足核心长期记忆闭环:
- L1 core profile:稳定事实,存储在 plugin storage,并注入 system prompt。
- L2 episodic memory:事件记忆,写入 vector DB,通过 metadata 做 scope 隔离和检索。
- 自动注入:PromptPreProcessing 阶段注入 L1,并基于当前消息自动召回少量 L2。
- 主动工具:`remember`、`recall_memory`、`update_profile`、`forget`。
- 管理命令:`!memory`、`!memory profile`、`!memory search`、`!memory list`、`!memory forget`、`!memory export`。
- 纠正机制:带 `correction` / `fact-update` / `clarification` 标签的新 episode 会尝试 supersede 相似旧 episode,降低旧记忆权重。
当前不会自动删除记忆:
- L1 profile 只有显式 `remove` 或覆盖才会改变。
- L2 episode 只有 `forget` 或 `!memory forget <episode_id>` 才会删除。
- superseded episode 仍然保留在 vector DB 中,只是 importance 降低并标记 `superseded_by`。
- time decay 只影响召回排序,不会硬删除。
## Design stance
不建议把插件对外模型扩成多层:
- 不新增 L0 Active Goals 作为 LongTermMemory 的核心层。
- 不新增 L3 Procedural Memory 作为 LongTermMemory 的核心层。
- goals / tasks 更像独立任务管理或个人助手插件,不应塞进长期记忆插件第一阶段。
- procedural knowledge 可暂时用 L1 notes、session profile 或 L2 summary episode 表达。
推荐模型仍然是:
- L1:当前稳定事实和画像。
- L2:可追溯事件和历史。
- Derived views:摘要、索引、候选记忆、归档状态、审计日志、supersede 关系。这些是派生能力,不是新的事实来源。
## Issue 1: Clarify L1/L2 memory write policy
Priority: P0
### Background
当前工具已有基本说明,但模型仍可能过度调用 `remember`,或把稳定偏好写成 L2 episode,把短期事件写进 L1 profile。长期运行后,这会带来噪声和画像污染。
### Goal
明确告诉模型:
- 什么时候写 L1。
- 什么时候写 L2。
- 什么时候不要写。
- 纠正类信息如何同时处理 profile 和 episode。
### Scope
更新以下位置:
- `components/tools/remember.yaml`
- `components/tools/update_profile.yaml`
- `components/tools/recall_memory.yaml`
- `components/event_listener/memory_injector.py` 中的注入说明
- `README.md` 的 usage / best practices 部分
### Suggested policy
L1 profile 只保存稳定、低频、当前有效的事实:
- 姓名、身份、长期偏好。
- 长期沟通风格。
- 群聊或会话长期约定。
- 用户明确纠正后的当前事实。
L2 episode 保存有时间语义、历史价值或上下文价值的事件:
- 计划、行程、近期状态。
- 某次对话中的决定。
- 用户明确希望以后参考的事件。
- 纠正发生的历史记录。
不要保存:
- 一次性寒暄。
- 临时情绪,除非用户明确希望记住。
- 敏感隐私、密钥、凭证、一次性验证码。
- 可能伤害用户或他人的推断性标签。
- 未经确认的群聊八卦或第三方隐私。
### Acceptance criteria
- Tool prompts 对 L1/L2 边界表述一致。
- README 中有 `When to write L1 / L2 / nothing` 小节。
- 至少包含中文群聊和个人私聊示例。
- 纠正类信息的处理规则清晰:更新 L1,必要时写 L2 保留历史。
### Non-goals
- 不引入自动记忆提取。
- 不修改 LangBot core 或 SDK。
## Issue 2: Add memory KB health check
Priority: P0
### Background
L2 依赖 metadata filter 做隔离。README 已说明 Milvus / pgvector 等固定 schema 后端不适合当前实现,但用户仍可能误配。仅靠文档提醒不够。
### Goal
增加运行时健康检查,帮助用户确认当前 pipeline 的 memory KB 是否可用且隔离可靠。
### Proposed command
```text
!memory health
```
### Checks
- memory KB 是否已创建。
- memory KB 是否绑定到当前 pipeline。
- embedding model 是否配置。
- 当前 vector backend 是否能在写入后通过 `user_key` metadata filter 正确检索。
- `vector_list` / `vector_delete` 是否能按 filter 工作。
### Suggested probe
写入两条临时 probe:
- `user_key = health_probe_a`
- `user_key = health_probe_b`
然后分别按 user_key 查询,确认不会串 scope。最后删除 probe。
### Acceptance criteria
- `!memory health` 输出 `OK`、`WARN` 或 `ERROR`。
- filter probe 失败时,明确提示该后端不适合 LongTermMemory。
- health check 不会留下 probe 记忆。
- README 安装步骤中增加 health check 建议。
### Non-goals
- 不要求 LangBot core 暴露 vector backend capability API。
- 不强制阻止用户使用不兼容后端,但要给出明确风险提示。
## Issue 3: Improve episodic recall with hybrid search and exact-match fallback
Priority: P1
### Background
当前 L2 recall 主要依赖 vector similarity,再叠加 recency、importance、speaker、update signal。中文群聊、人名、ID、短标签、episode_id 等场景下,纯向量召回可能不稳定。
LangBot 的 vector API 已支持 `search_type`、`query_text`、`vector_weight`。Chroma 和 SeekDB 已有 hybrid / full-text 能力,插件可以优先使用,不需要改 core。
### Goal
提升 recall 稳定性,特别是:
- 中文短词。
- 人名和群成员名。
- sender_id / sender_name。
- tags。
- episode_id。
- 精确事件名称。
### Scope
- `MemoryStore.search_episodes`
- `LongTermMemoryEngine.retrieve`
- `recall_memory` tool 参数和文档
- `memory_engine.yaml` retrieval / creation schema
### Proposed config
```yaml
retrieval_strategy: vector | hybrid | auto
vector_weight: 0.7
exact_match_boost: true
```
Default should be `auto`:
- use hybrid when backend supports it or when it succeeds;
- fallback to vector when hybrid fails.
### Acceptance criteria
- Automatic L2 recall and `recall_memory` both support the configured strategy.
- Hybrid mode passes `query_text` to `vector_search`.
- Exact match on episode_id can find the episode without relying on embedding.
- Exact match on sender_name / tags can boost or include results.
- If hybrid search fails, recall falls back to vector and logs warning.
### Non-goals
- 不实现新的 CJK tokenizer。
- 不引入外部 search service。
## Issue 4: Add episode lifecycle status
Priority: P1
### Background
当前只有 delete 和 supersede。旧记忆不会自动删除,superseded episode 仍可能被召回,只是权重降低。长期运行后,需要更清晰的生命周期。
### Goal
为 L2 episode 增加生命周期状态,避免默认召回过期或被整合的记忆,同时保留可追溯性。
### Proposed statuses
```text
active
superseded
archived
deleted
```
Recommended semantics:
- `active`: 默认可召回。
- `superseded`: 默认不召回,或强降权;管理命令可查。
- `archived`: 普通 recall 不返回;管理命令可查。
- `deleted`: 物理删除或 tombstone,取决于审计策略。
### Scope
- episode metadata 增加 `status`
- auto-supersede 时设置旧 episode `status=superseded`
- recall 默认过滤 `status=active`
- 管理命令支持 `--include-superseded` 和 `--include-archived`
### Acceptance criteria
- 新写入 episode 默认 `status=active`。
- superseded episode 默认不会进入自动 recall。
- `!memory list --include-superseded` 可以查看旧记忆。
- `!memory search` 默认只查 active,可选包含 archived/superseded。
### Non-goals
- 不默认自动物理删除。
- 不要求历史数据迁移;缺失 status 的旧数据可视为 active。
## Issue 5: Add L2 export/import and scoped deletion commands
Priority: P1
### Background
当前 `!memory export` 只导出 L1 profiles。L2 可通过 KB UI 导入 JSON,但没有完整的命令式 export/import 和批量治理能力。
### Goal
让管理员可以迁移、备份、清理当前 scope 的 L2 episodes。
### Proposed commands
```text
!memory export l2
!memory import l2 <json>
!memory delete --speaker <sender_id>
!memory delete --tag <tag>
!memory delete --before <timestamp>
!memory delete --status archived
```
### Export fields
```json
{
"id": "episode_id",
"content": "...",
"tags": ["..."],
"importance": 2,
"timestamp": "2026-05-15T00:00:00Z",
"user_key": "...",
"sender_id": "...",
"sender_name": "...",
"source": "agent",
"status": "active",
"superseded_by": ""
}
```
### Acceptance criteria
- Export 只导出当前 `user_key` scope。
- Import 默认写入当前 scope,不允许导入覆盖其他 scope。
- 批量删除必须 scope-safe。
- 删除前返回 preview 或至少返回将删除数量。
- 批量删除写 audit log。
### Non-goals
- 不实现跨 scope 全量备份。
- 不开放任意 raw metadata filter 给模型。
## Issue 6: Add memory audit log
Priority: P1
### Background
长期记忆涉及误写、误删、隐私和治理。当前 delete / update 没有独立 audit 记录,排查困难。
### Goal
记录所有会改变 memory state 的操作。
### Operations to audit
- `remember`
- `update_profile`
- `forget`
- L2 import
- L2 export
- bulk delete
- consolidation apply
- archive / restore
### Storage
Audit log 存 plugin storage,不进入 L2 vector DB。
### Proposed command
```text
!memory audit [page]
!memory audit export
```
### Audit fields
```json
{
"audit_id": "...",
"operation": "remember",
"scope_key": "...",
"user_key": "...",
"sender_id": "...",
"sender_name": "...",
"target_type": "episode",
"target_id": "...",
"summary": "...",
"timestamp": "2026-05-15T00:00:00Z",
"query_id": 123
}
```
### Acceptance criteria
- 单条删除和批量删除都有 audit。
- profile 更新记录 field / action / scope。
- audit list 支持分页。
- audit export 不泄漏其他 scope。
### Non-goals
- 不做不可篡改日志。
- 不要求外部 SIEM 集成。
## Issue 7: Expose superseded and archived memories
Priority: P1
### Background
supersede 机制已经存在,但管理员看不到旧记忆为什么不再优先召回,也不容易验证 correction 是否生效。
### Goal
增强可解释性和可调试性。
### Proposed commands
```text
!memory show <episode_id>
!memory superseded [page]
!memory archived [page]
!memory restore <episode_id>
!memory archive <episode_id>
```
### Acceptance criteria
- `!memory show` 显示 status、superseded_by、timestamp、tags、importance、sender。
- `!memory superseded` 能列出被替代的 episode。
- `!memory restore` 可以把 archived episode 恢复为 active。
- 所有 status 修改写 audit log。
### Non-goals
- 不实现复杂合并 UI。
## Issue 8: Add consolidation preview and apply commands
Priority: P1
### Background
当前只有 time decay,没有主动整合。长期运行后,L2 会积累重复、过期、被纠正的 episode。OpenClaw 的 dreaming 和 Hermes 的 post-turn sync 都说明长期记忆需要整理,但自动后台直接改写记忆风险较高。
### Goal
增加安全的、管理员可控的 memory consolidation 流程。
### Proposed commands
```text
!memory consolidate preview
!memory consolidate run
```
### Recommended first version
第一版只做 preview-first,不默认后台自动执行。
Candidate selection:
- older than configured age, e.g. 7 days;
- same tag / high similarity duplicate;
- already superseded;
- low importance and rarely recalled;
- many episodes from the same speaker/topic.
Preview output:
- candidate episode IDs;
- suggested summary episode;
- suggested L1 profile updates;
- suggested archive list;
- risk notes.
Apply output:
- write summary episode;
- update L1 profile if configured;
- archive selected old episodes;
- write audit log.
### Proposed config
```yaml
consolidation_enabled: false
consolidation_min_age_days: 7
consolidation_max_candidates: 20
consolidation_apply_profile_updates: false
```
### Acceptance criteria
- Preview does not modify memory.
- Run modifies only current scope.
- Run writes audit log for every profile update / episode archive / summary write.
- Archived episodes are excluded from default recall.
### Non-goals
- 不做后台 cron。
- 不默认自动整合。
- 不新增 L3 procedural memory。
## Issue 9: Add optional post-turn memory candidate extraction
Priority: P1 / P2
### Background
当前 memory 写入主要依赖模型主动调用 `remember` / `update_profile`。这可控,但容易漏记。直接自动写入又可能污染 memory。
### Goal
增加一个默认关闭的候选记忆提取流程,让管理员观察模型会建议记什么,再决定是否自动化。
### Proposed behavior
Post-turn extraction 生成 candidates:
- candidate L1 profile update
- candidate L2 episode
- ignore reason
默认只记录候选,不写入正式 memory。
### Proposed commands
```text
!memory candidates [page]
!memory candidate accept <candidate_id>
!memory candidate reject <candidate_id>
```
### Proposed config
```yaml
candidate_extraction_enabled: false
candidate_auto_apply: false
candidate_max_per_turn: 3
```
### Acceptance criteria
- 默认关闭。
- 开启后不自动污染 L1/L2。
- accept 后走正常 `update_profile` / `remember` 路径,并写 audit log。
- reject 后候选可查。
### Non-goals
- 不要求修改 LangBot core 增加 TurnCompleted event。
- 第一版可以基于现有 `NormalMessageResponded` 事件或命令触发。
## Issue 10: Add richer memory management commands
Priority: P2
### Background
OpenClaw / Hermes 的文件式 memory 透明性较强。LongTermMemory 不应改成文件主存储,但需要提供足够透明的管理入口。
### Goal
用命令增强替代直接编辑 Markdown 文件的透明性。
### Proposed commands
```text
!memory show <episode_id>
!memory edit <episode_id>
!memory profile edit session
!memory profile edit speaker <sender_id>
!memory stats
!memory export all-current-scope
```
### Acceptance criteria
- 管理员能查看和编辑 L1/L2。
- 所有 edit/delete/archive 操作写 audit。
- 不允许跨 scope 操作,除非未来单独设计全局管理员权限。
### Non-goals
- 不做 Web UI 第一版。
## Issue 11: Design optional global speaker profile scope
Priority: P2 design only
### Background
当前 L1 speaker profile 绑定在 session_key 下。这适合群聊隔离,但不支持“同一个用户跨多个群共享画像”。
### Goal
做设计预研,不急着实现。
### Questions
- 是否需要 `speaker_global` scope?
- 如何识别同一个用户在不同平台/群的身份?
- 默认是否关闭?
- 用户如何授权跨群共享?
- 与 `bot` L2 isolation 如何组合?
- 冲突时 session speaker profile 和 global speaker profile 谁优先?
### Acceptance criteria
- 输出设计文档。
- 明确默认关闭。
- 明确隐私边界和迁移策略。
### Non-goals
- 不在第一阶段实现。
## Suggested implementation order
1. Issue 1: write policy.
2. Issue 2: health check.
3. Issue 4: lifecycle status.
4. Issue 6: audit log.
5. Issue 5: L2 export/import/delete.
6. Issue 7: superseded / archived visibility.
7. Issue 3: hybrid recall and exact-match fallback.
8. Issue 8: consolidation preview/apply.
9. Issue 9: post-turn candidates.
10. Issue 10 / 11: management UI and global profile design.
## What not to do yet
- Do not move memory implementation into LangBot core.
- Do not require LangBot SDK changes as a prerequisite.
- Do not add active goals into this plugin in the first phase.
- Do not add procedural memory as a first-class layer yet.
- Do not automatically delete old memories by default.
- Do not run background consolidation that modifies memory without preview or audit.