oG-Memory:基于 openGauss 的语义记忆搜索库项目

可用于高效检索和管理文档信息,支持向量相似度与BM25全文混合检索,能按Markdown标题结构分块并保留层级信息,兼容OpenAI及Silra等嵌入服务,支持元数据过滤。【此简介由AI生成】

分支2Tags0
文件最后提交记录最后更新时间
feat(plugin): add marketplace.json with opengauss repo URL - Add .claude-plugin/marketplace.json for plugin marketplace discovery - Update marketplace URLs to https://gitcode.com/opengauss/oG-Memory Co-Authored-By: Claude glm-5.1[1m] <noreply@anthropic.com> 1 个月前
refactor: consolidate all config/env/docs into config/ and docs/ directories Move all configuration files, environment variables, templates, and documentation out of the project root into organized directories: - config/: runtime config, templates, env vars, AGFS/OpenClaw configs - docs/: ENV.md, OGMEMORY_ENV.md moved from root - docker/: Dockerfiles moved from root Update all loading paths (providers/unified_config.py, cli/commands/*, openclaw plugin, scripts) to read from config/ instead of root. Delete 4 duplicate templates (docker/ogmemory.example.yaml, docker/agfs-config.yaml, docker/openclaw-ogmem.json, agfs/config.example.yaml) replaced by unified config/ templates. Enhance ogmem onboard with mode-aware flows (local/docker/plugin), add --storage-backend flag, DB init, Docker deploy helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 25 天前
replace oG-Memory to oGMemory 14 天前
fix(cli): fix onboard param mismatch and unify port config reading - Fix start_plugin() passing root as positional arg to timeout parameter instead of cwd keyword arg, causing TypeError in health check - Unify start_headless() to read http_port via get_config() instead of only reading OGMEM_HTTP_PORT env var, consistent with start_plugin() Fixes: gitcode.com/opengauss/oG-Memory#58 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 15 天前
test: cover schema registry integration 11 天前
feat(memory): refine compact mechanism runtime state 11 天前
test: cover schema registry integration 11 天前
Merge upstream/dev into dev Conflicts resolved: - docker/Dockerfile.standalone: keep local (perf module) - providers/token_tracker.py: keep local (bucket stack) - server/memory_service.py: keep upstream (error handling) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> 7 天前
perf: fix M1/M3, multi-worker plan B, P1/P2 security fixes, report filtering M1 fix (rate_cards.py): - Split load_rate_card() into _load_cached(resolved_path: str) and public wrapper. lru_cache now keyed on resolved str path so same-path calls reuse cache. M3 fix (recorder.py): - Re-raise KeyError from compute_cost instead of silent $0 fallback. Unknown model without default in rate card must surface as error. Multi-worker plan B (recorder.py): - OGMEM_WORKER_ID env → perf.w{id}.jsonl suffix on JSONL path. - load_events() accepts directory → glob+merge all *.jsonl files. P1 fix (server/app.py): - POST /api/v1/perf/events now enforces _build_authenticated_context when perf is enabled (symmetric with GET). P2 fix (server/app.py): - GET response now documents that events is non-empty only with MemorySink. Default JsonlSink should use perf.report CLI to read persisted JSONL. Report filtering (report.py): - Use parent_span is None (not span=="") to identify stage root events, fixing synthetic events with named spans being misclassified as sub-spans. Dockerfile (standalone): - Remove COPY lifecycle/ (directory removed from workspace). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> 7 天前
feat(memory): refine compact mechanism runtime state 11 天前
修复一键部署脚本 1 个月前
feat: attribute internal tool usage 11 天前
!85 fix(providers): SQLRelationStore fallback to context_nodes.relations From: @dawnbreaker28 Reviewed-by: @akushonkamen, @jcp0578 See merge request: opengauss/oGMemory!853 天前
feat: add BM25 hybrid retrieval, dream lifecycle, and extraction improvements - Add BM25 keyword index with Vector-Anchored Fusion for hybrid seed retrieval - Add DreamService lifecycle subsystem with RecallTracker, SQLRecallStore, and LightDreaming phase - Merge dual-run extraction results by (category, routing_key) to reduce duplicates - Raise extraction confidence threshold from 0.5 to 0.6 - Remove L1 (overview) level from index records, enrich metadata with when/who/where - Add list_archives_since to SQLSessionArchiveStore for dream recall queries - Integrate recall tracking into RetrievalPipeline and MemoryService Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 21 天前
feat(memory): refine compact mechanism runtime state 11 天前
[bugfix] fix bug: test cannot run 3 天前
perf: P1 auth try/except fix, P2 explicit disabled check, cache_write improvements 1. P1 auth (server/app.py): - Added try/except around _build_authenticated_context() - Catches AuthenticationError/AuthorizationError - Returns _error_response(exc) for proper 401/403 responses 2. P2 disabled check (server/app.py): - Added explicit check: if not rec.enabled return 409 - No longer silent no-op on emit() 3. cache_write improvements: - Removed explicit cache_write: 0.00 from YAML (indistinguishable from "not defined") - Changed logic: only add cost if tokens > 0 AND rate is defined Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> 7 天前
!85 fix(providers): SQLRelationStore fallback to context_nodes.relations From: @dawnbreaker28 Reviewed-by: @akushonkamen, @jcp0578 See merge request: opengauss/oGMemory!853 天前
refactor: remove dream lifecycle subsystem Remove unused DreamService, LightDreaming, RecallTracker, and SQLRecallStore. Clean up all references in MemoryService, RetrievalPipeline, and OgMemConfig. The dream lifecycle was offline-only and did not affect retrieval results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 15 天前
refactor: consolidate all config/env/docs into config/ and docs/ directories Move all configuration files, environment variables, templates, and documentation out of the project root into organized directories: - config/: runtime config, templates, env vars, AGFS/OpenClaw configs - docs/: ENV.md, OGMEMORY_ENV.md moved from root - docker/: Dockerfiles moved from root Update all loading paths (providers/unified_config.py, cli/commands/*, openclaw plugin, scripts) to read from config/ instead of root. Delete 4 duplicate templates (docker/ogmemory.example.yaml, docker/agfs-config.yaml, docker/openclaw-ogmem.json, agfs/config.example.yaml) replaced by unified config/ templates. Enhance ogmem onboard with mode-aware flows (local/docker/plugin), add --storage-backend flag, DB init, Docker deploy helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 25 天前
Merge upstream/dev into dev Conflicts resolved: - docker/Dockerfile.standalone: keep local (perf module) - providers/token_tracker.py: keep local (bucket stack) - server/memory_service.py: keep upstream (error handling) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> 7 天前
feat: attribute internal tool usage 11 天前
feat(memory): refine compact mechanism runtime state 11 天前
!85 fix(providers): SQLRelationStore fallback to context_nodes.relations From: @dawnbreaker28 Reviewed-by: @akushonkamen, @jcp0578 See merge request: opengauss/oGMemory!853 天前
add opencode-og-memory-plugin Co-authored-by: shiyangzhou<shiyangzhou@noreply.gitcode.com> 3 天前
refactor: align codebase, cleanup, extraction enhancement, README rewrite Align all code layers with canonical architecture. Update OpenClaw plugin and Docker deployment. Enhance extraction with temporal/entity fields and few-shot examples. Rewrite README around Agent context lifecycle: 6 lifecycle hooks, 27 context operators, ContextFS virtual filesystem. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 1 个月前
chore: add uv package manager support and deployment script - Update pyproject.toml for uv/hatchling build system - Add .python-version (3.12) for uv - Add scripts/deploy.sh for quick deployment - Add uv.lock for dependency pinning Deployment: uv sync # Install dependencies uv run python examples/basic_usage.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 2 个月前
Initial commit3 个月前
Merge remote-tracking branch 'upstream/dev' into dev 5 天前
docs: comprehensive README accuracy audit + zh translation sync - Fix ContextFS table: describe actual protocol methods (write_node, read_node, etc.) not aspirational API - Fix read path: dedup by URI (not cos>0.9), BM25 fusion inside SeedRetriever, hotness in HierarchicalSearcher - Fix write path: show ContextWriter 5 logical steps, clarify 4-step is AGFS internal - Fix config defaults: chroma (not memory), agfs (not sql), config/ogmem.yaml - Fix onboard non-interactive: --mode headless (not local) - Add get_access_stats to ReAct tools, DirectorySummarizer to architecture - Add Roadmap section (Completed/Benchmark/In Progress/Planned) - Add Claude Code integration section - Expand API endpoints to 28+, fix ENV.md link to docs/ENV.md - Add 3 system-internal schemas note (tool, session_archive, session_summary) - Update repository layout (remove lifecycle/, add agfs/, deploy/, claude-plugin/, etc.) - Sync README_zh.md to match all audit fixes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 15 天前
fix: Red Team audit fixes and cleanup - Fix OpenGaussVectorIndex syntax errors from merge conflicts - Remove redundant openclaw_plugin symlink directory - Consolidate audit docs to single PRODUCTION_AUDIT_2025_03_25.md - Fix OpenGauss tests to use PostgreSQL syntax (ON CONFLICT) - Skip unimplemented auto-init tests - All 391 tests passing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 2 个月前
add opencode-og-memory-plugin Co-authored-by: shiyangzhou<shiyangzhou@noreply.gitcode.com> 3 天前
replace oG-Memory to oGMemory 14 天前
feat: add BM25 hybrid retrieval, dream lifecycle, and extraction improvements - Add BM25 keyword index with Vector-Anchored Fusion for hybrid seed retrieval - Add DreamService lifecycle subsystem with RecallTracker, SQLRecallStore, and LightDreaming phase - Merge dual-run extraction results by (category, routing_key) to reduce duplicates - Raise extraction confidence threshold from 0.5 to 0.6 - Remove L1 (overview) level from index records, enrich metadata with when/who/where - Add list_archives_since to SQLSessionArchiveStore for dream recall queries - Integrate recall tracking into RetrievalPipeline and MemoryService Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> 21 天前

ContextEngine: CLI Agent 的
上下文生命周期引擎

贯穿 Agent 循环的每一个阶段,管理什么进入上下文窗口、什么被保留、什么被淘汰、以及什么能够被重新召回。 七类上下文。三级缓存层次。一个虚拟文件系统。 降低 token 消耗。保持信号密度。跨越会话边界。

English | 中文


问题:Token 预算是瓶颈

每个 CLI Agent 运行在固定的 token 预算上。上下文窗口既是最昂贵的,也是最稀缺的资源。

症状 根因 缺失的生命周期阶段
Agent 会遗忘对话早期的内容 窗口占满后旧内容被淘汰,没有持久化 afterTurn — 缺少抽取 + 持久化机制
跨会话重复犯同样的错误 没有跨会话传递经验的机制 session_end — 无归档 + ② bootstrap — 无冷启动注入
一次本该花 $0.05 的查询花了 $0.50 扁平检索加载整篇文档,摘要就够了 assemble — 缺少 L0/L1/L2 分层检索
多 Agent 协作失效 Agent 之间看不到彼此的工作上下文 afterTurn — 无跨会话共享 + 多租户隔离
长会话中上下文不断膨胀 没有系统化压缩 — Agent 淹没在自己的历史中 compact — 缺少信号评分 + 摘要链

这不是模型的问题。这是基础设施问题

ContextEngine 提供的正是缺失的那层基础设施:一个全栈上下文生命周期管理系统,在 Agent 循环的六个明确定义阶段拦截,把上下文窗口当作受管资源来管理 — 而不是无界缓冲区。


设计哲学

核心洞察:上下文有生命周期

当前 RAG 系统把检索当作单一操作 — 向量化查询、搜索向量库、返回结果。这忽略了一个基本事实:Agent 系统中的上下文有完整的生命周期,就像数据库中的数据一样。

  诞生           结构化            存储              索引             召回            压缩             归档
  (从对话中      (按类型分类,      (原子写入,        (向量化 +        (向量搜索,      (摘要化,         (会话结束,
   抽取)          按策略路由)      有顺序保证)       写入 L0/L1/L2    分层展开,       去重,            归档,
                                                  IndexRecords)    按预算加载)     压缩)            状态快照)

每个阶段有不同的约束。抽取必须增量(不重复处理旧消息)。存储必须原子(不完整写入可检测)。索引必须异步(不阻塞 Agent 响应)。检索必须感知预算(只加载放得下的)。压缩必须保留信号(保护重要上下文)。

只处理其中一两个阶段的系统 — 比如只做检索 — 把其余阶段留给了偶然。ContextEngine 覆盖完整生命周期。

六个拦截点

Agent 循环不是黑盒。它有明确的执行阶段。每个阶段提供不同的上下文读/写/变换机会。

  ┌──────────────────────────────────────────────────────────────────────┐
  │                        Agent Loop(无限循环)                          │
  │                                                                       │
  │   ┌─────┐     ┌──────────┐     ┌──────────┐     ┌─────────┐         │
  │   │ ①   │     │    ②     │     │    ③     │     │   ④     │         │
  │   │ 消息 │────▶│ 推理准备 │────▶│ 工具调用 │────▶│ 轮次结束 │         │
  │   │ 到达 │     │          │     │          │     │         │         │
  │   └──┬──┘     └──────────┘     └──────────┘     └────┬────┘         │
  │      ▲                                              │               │
  │      │         ┌──────────┐         ┌─────────┐     │               │
  │      │         │    ⑤     │         │   ⑥     │     │               │
  │      └─────────│ 压缩管理 │◀────────│ 会话关闭 │◀────┘               │
  │                └──────────┘         └─────────┘                      │
  │                                                                       │
  └──────────────────────────────────────────────────────────────────────┘

关键设计选择:在循环边界拦截,而不是在模型推理内部拦截。 阶段 ①–⑥ 全部在 LLM 调用之外。这意味着对模型推理本身零延迟影响 — 所有上下文操作发生在推理前后,绝不在推理过程中。

上下文类型不平等

七类上下文,各有根本不同的生命周期行为。这不是随意分类 — 由信息本身的语义决定。

类型 为什么是这个生命周期? 写入策略
Profile 用户状态会变化 — "我住在北京"可能变成"我搬到了东京" Merge — 冲突时新覆盖旧
Preference 偏好按主题累积,每个主题只有一个当前视图 按 slug 归并 — 合并同主题
Entity 实体累积事实,但"项目 Alpha"仍然是"项目 Alpha" 按 slug 归并 — 合并同实体
Event 历史不可变 — "3月15日完成迁移"永远不会改变 仅追加 — 永不覆盖
Case 问题解决轨迹是历史记录 仅追加 — 永不覆盖
Pattern 模式从反复观察中涌现并随时间演化 按 slug 归并 — 逐步精炼
Skill 工具专长累积增长 — 经验越多知识越好 累积追加 — 知识持续积累

四种截然不同的写入策略,每种由信息的生命周期语义决定。单一的"用同一种方式存储一切"方案,要么丢失可变状态(如果仅追加),要么破坏不可变历史(如果覆盖写入)。

除 7 类用户面向类型外,还有 3 类系统内部 Schema(toolsession_archivesession_summary)— 它们由分块和压缩管线以编程方式创建,不由 LLM ReAct 循环抽取。


关键架构决策

为什么用 YAML 驱动 Schema?

问题:在 Python 中硬编码抽取 Schema,每新增一个上下文类型都要改代码、测试、部署。

方案:YAML Schema 声明式定义要抽取什么、如何分类。SchemaRegistry、PolicyRouter 和 URIResolver 都在运行时消费这些 Schema。新增类型 — 比如"Decision"或"Handoff" — 只需添加一个 YAML 文件,不需要改抽取管线。

不用这个方案会怎样:每个新类型都变成一次跨抽取、提交路由、URI 解析三个包的代码变更,必须协同发布。实际上团队会跳过添加新类型,所有东西都被塞进泛化的"notes"。

为什么用 Outbox 模式做异步索引?

问题:向量化 + 写入向量索引需要 100–500ms。如果同步执行,每次 afterTurn 都会阻塞那么久,增加 Agent 响应延迟。

方案:Outbox 模式将写入(快,~50ms)和索引(慢,异步)解耦。每次写入投递一个 OutboxEvent。后台 Worker 消费事件,提供至少一次投递保证和死信队列。写入路径立即返回;索引在几秒内追上。

不用这个方案会怎样:Agent 感知的响应时间膨胀 2–10 倍。更糟的是,如果向量库暂时不可用,写入失败、上下文丢失 — 系统对基础设施瞬时故障变得脆弱。

为什么用 L0/L1/L2 三级检索?

问题:内容越长,向量相似度反而可能越低 — 而非越高。一个 5000 token 的文档 embedding 必须表示其中每一个概念,导致任何单一主题的信号被稀释。

方案:每个上下文节点按三种粒度索引。L0 摘要(~100 token)产生聚焦 embedding — 精准的主题路标。L1 概述(~500 token)信号居中。L2 完整内容(~5000 token)信息最全但 embedding 弥散。检索引擎对三个层级做一次统一的向量搜索,然后把 L0/L1 命中作为目录入口点进行递归树展开:当 L0 摘要匹配时,搜索器展开其子节点,发现扁平搜索会遗漏的 L2 内容。分数传播(final = α·child + (1-α)·parent)让强匹配父节点下的边缘 L2 结果获得加成。热度混合(blended = (1-α_hotness)·semantic + α_hotness·h_score)在树展开过程中应用。

  ┌─────────────┐    ┌─────────────┐    ┌──────────────┐
  │  L0 摘要     │    │  L1 概述     │    │  L2 完整内容  │
  │  ~100 token  │    │  ~500 token  │    │  ~5000 token  │
  │  聚焦        │    │  平衡信号    │    │  信息全面     │
  │  embedding   │    │             │    │  但弥散       │
  │  → 路标定位  │    │  → 决策参考  │    │  → 完整细节   │
  └──────┬───────┘    └──────┬───────┘    └──────┬────────┘
         │                   │                    │
         ▼                   ▼                    ▼
    .abstract.md        .overview.md          content.md

召回优势:仅对 L2 做扁平向量搜索,会遗漏那些因细节稀释导致向量分数低于阈值的相关内容。L0/L1 路标引导搜索器定位到正确的目录,然后树展开发现其下的完整内容 — 包括原始向量分数不高但父主题强匹配的 chunk。

为什么用文件系统抽象?

问题:上下文操作 — 创建、读取、更新、关联、删除 — 需要可组合、原子、多租户安全。每一样都作为独立 API 构建意味着要为每个操作重新实现并发、权限和一致性。

方案:ContextFS 将每个上下文操作映射为 ctx:// URI 上的类文件操作。多租户隔离在文件系统层面强制执行(通过路径中的 account_id + owner_space),即使调用方有 bug 也无法绕过。ContextFS 协议提供以下操作:

协议方法 上下文操作
write_node(node, ctx) 原子写入,4 步顺序(content → relations → abstract/overview → meta.json)
read_node(uri, ctx) 加载完整节点(content + meta + relations)
delete_node(uri, ctx) 永久删除
archive_node(uri, ctx) 软删除(status → ARCHIVED)
move_node(from, to, ctx) 重定位节点
list_children(uri, ctx) 枚举子 URI
exists(uri, ctx) 仅 ACTIVE 时为 True(PENDING 不可见)

关系通过独立的 RelationStore 协议管理,不属于 ContextFS 本身。两个后端实现了 ContextFS:AGFS 适配器(Go 文件服务器,默认)和 SQL 适配器(PostgreSQL)。

不用这个方案会怎样:租户隔离变成"每个调用方都必须记得检查权限"。原子写入变成"每个调用方都必须正确实现 4 步写入协议"。每个新功能都重新解决相同的基础设施问题。

为什么用乐观锁做并发写入?

问题:Profile 节点会被用户的所有会话同时写入。两个会话可能同时抽取冲突的 profile 更新。

方案:乐观锁 — 读取当前 .meta.json 版本,仅在版本未变时写入。常见场景(无竞争)零基础设施开销。罕见场景(并发写入),第二个写入者用新状态重试。

不用这个方案会怎样:分布式锁需要协调服务(etcd/ZooKeeper)— 为罕见问题增加基础设施复杂度。不加锁则后写覆盖,静默丢失第一个写入者的更新。

为什么用 ReAct 循环做抽取?

问题:抽取质量取决于已知内容。如果系统已经知道"Alice 是后端工程师",再次抽取浪费 LLM token 并创建后续必须去重的重复条目。

方案:LLM 被赋予工具访问 — read(uri)list(uri)get_relations(uri)get_access_stats(uri),以及 extract_* 动作 — 然后在循环中运行。每一轮:先读取已有记忆节点(Reason),判断哪些是真正新的,再调用对应的 extract_* 工具(Act)。如果不确定,就读更多节点继续循环。这是真正的 ReAct:推理和工具调用交替进行,不是单次盲目抽取。

  迭代 1:  read(profile_uri) → "Alice, 后端工程师, 伦敦"
            → 无新信息,跳过

  迭代 2:  read(entities/go) → "Go 专家,偏好错误处理模式 X"
            → 新增: "Alice 现在也在用 Rust 做副项目"
            → extract_entity(slug="rust", ...)

不用这个方案会怎样:每轮重复抽取相同事实。100 轮后,"Alice 是后端工程师"被抽取 100 次,产生 100 次 Profile 合并操作 — 每次都在已有内容上浪费 LLM token。抽取成本随对话长度线性增长,而不是随信息密度增长。


架构

总体架构

         CLI Agent (Claude Code / OpenClaw / SDK)
              │  HTTP REST (端口 8090) 或 Python SDK
              ▼
    ┌─ HTTP 层 ──── Flask REST · 认证/RBAC · 会话管理 ─┐
    └──────────────────────┬─────────────────────────────┘
    ┌─ Service 层 ── MemoryWriteAPI · MemoryService ────┐
    └──────────────────────┬─────────────────────────────┘
        ┌──────────────────┴──────────────────┐
        │  写入链路            │  读取链路      │
        │  ReAct 抽取循环     │  QueryPlanner │
        │  PolicyRouter       │  SeedRetriever│
        │  ContextWriter      │  (+BM25 融合) │
        │  OutboxStore        │  HierSearcher │
        │                     │  ResultRanker │
        └──────────────────────┬───────────────┘
    ┌─ ContextFS ── AGFS 适配器 · SQL 适配器 ───────────┐
    └──────────────────────┬─────────────────────────────┘
    ┌─ 异步索引 ── OutboxWorker · DirSummarizer · RepairJob ─┐
    └──────────────────────┬─────────────────────────────────┘
              ┌─────────────▼─────────────┐
              │  AGFS · PostgreSQL · ChromaDB/pgvector│
              └───────────────────────────┘

开发模式:ChromaDB 向量 + AGFS 文件存储 — 零外部依赖(默认)。 SQL 模式:ChromaDB/pgvector + PostgreSQL — 安装 postgresqlpgvector 扩展。 生产模式:pgvector + PostgreSQL RLS — 行级租户隔离,水平可扩展。

写入路径:对话到持久化记忆

  Agent 轮次结束
        │
        ▼
  ┌─────────────────────────────────────────────────┐
  │  ReAct 抽取循环                                  │
  │                                                 │
  │  LLM 拥有工具: read(uri), list(uri),            │
  │  get_relations(uri), get_access_stats(uri),      │
  │  extract_*()                                    │
  └────────────────────┬────────────────────────────┘
                       │  CandidateMemory[]
                       ▼
  ┌──────────────────┐     ┌──────────────────┐
  │  PolicyRouter     │     │  ContextWriter    │
  │  (Schema 驱动)    │────▶│                  │
  │  Profile→Merge    │     │  Plan → Build     │
  │  Entity→Aggregate │     │  → Write (4步)    │
  │  Event→Append     │     │  → Outbox         │
  │  Skill→SkillTool  │     │  → DirSummary     │
  └──────────────────┘     └────────┬─────────┘
                                    │
                          ┌─────────▼─────────┐
                          │  Outbox Event     │
                          │  (异步, 持久化)   │
                          └─────────┬─────────┘
                                    │
                    ┌───────────────▼───────────────┐
                    │  Index Worker (后台)           │
                    │  embed(abstract) → L0 upsert  │
                    │  embed(overview)  → L1 upsert  │
                    │  embed(content)   → L2 upsert  │
                    │  DirectorySummarizer (L0/L1    │
                    │  为父节点生成摘要)              │
                    └───────────────────────────────┘

4 步原子写入(content.md → .relations → abstract+overview → .meta.json)是 AGFS 适配器的物理文件协议。ContextWriter 在更高层编排:Plan → Build → Write → Outbox → Directory Summary(5 个逻辑步骤)。

读取路径:查询到组装上下文

  用户消息到达
        │
        ▼
  ┌───────────────────┐     ┌──────────────────────────────────────────┐
  │  QueryPlanner      │     │  SeedRetriever                          │
  │                    │     │                                          │
  │  类型分类:         │────▶│  向量搜索 L0+L1+L2                       │
  │  正则 → MEMORY/    │     │  + BM25 关键词融合 (alpha 加权)           │
  │  SKILL/RESOURCE    │     │  → L0/L1 命中 = 目录路标                  │
  │  意图分类:         │     │  → L2 命中 = 直接内容匹配                 │
  │  RetrievalIntent   │     └────────────────────┬─────────────────────┘
  └───────────────────┘                          │
                                          ┌──────▼──────┐
                                          │  有 L0/L1   │
                                          │  命中?      │
                                          └──────┬──────┘
                                           是   │   否
                                          ┌──────▼──────▼──────┐
                                          │  分层搜索           │  直接使用
                                          │                    │  L2 结果
                                          │  search_children() │
                                          │  按目录节点展开     │
                                          │  分数传播           │
                                          │  + 热度混合         │
                                          └────────┬───────────┘
                                                   │
                                          ┌────────▼─────────┐
                                          │  ResultRanker     │
                                          │  按 URI 去重      │
                                          │  按分数排序       │
                                          │  截断至 top_k     │
                                          │  填充内容         │
                                          └──────────────────┘

一次向量搜索,不是三次逐层扫描。BM25 融合在 SeedRetriever 内部完成(不是独立的管线阶段),使用 Vector-Anchored Fusion:final = α·vec + (1-α)·sat_bm25。热度混合在 HierarchicalSearcher 展开过程中应用,不在 ResultRanker。去重按精确 URI 匹配,不是余弦相似度。

命名空间隔离: 查询按意图类型限定搜索范围。MEMORY 查询同时搜索 users/{user}/memories/agents/{agent}/memories/。SKILL 查询只搜索 agents/{agent}/skills/owner_space 过滤由 QueryPlanner 根据 context_typevisible_owner_spaces 设置,在向量索引层面强制执行 — 调用方无法覆盖。


Agent 上下文生命周期

六个阶段形成一条管线,每个阶段的输出馈入下一个。设计原则:永远不阻塞模型推理。所有上下文操作发生在循环边界 — LLM 思考前或行动后,绝不在推理过程中。

阶段 时机 做什么 关键不变量
① 消息到达 Agent 推理前 解析意图,从 L0 预取候选 永不阻塞;超时静默失败
② bootstrap + ingest + assemble 构建提示前 冷启动 profile 注入,预算感知 L0→L1→L2 加载,去重,技能注入 永不超过 token 预算
③ before_tool_call + tool_result_persist 工具执行前后 注入已知失败模式,压缩过大结果,抽取即时事实 工具参数有历史经验指导
④ afterTurn Agent 完成响应后 增量抽取差量,策略路由写入,关系构建,异步索引 只抽取新内容
⑤ before_compaction + compact 上下文填满时 信号打分,保护关键节点,压缩冗余 永不丢失 Profile 或活跃任务
⑥ session_end + dispose 会话关闭 归档已完成任务,为下个会话快照状态,完整性审计 下个会话无缝衔接

生命周期是循环的:阶段 ⑥ 的任务快照变成阶段 ② 的交接注入。阶段 ④ 诞生的上下文在阶段 ① 被召回。跨越会话持久化的内容使系统学习,而不仅仅是记忆


数据流:端到端追踪

  会话 1 — 写入路径: "我叫 Alice,是一名后端工程师,住在伦敦"
  ────────────────────────────────────────────────────────────────
    用户消息 → 阶段 ④ afterTurn
        → 增量抽取 (name, role, location)
        → CandidateMemory(category="profile")
        → PolicyRouter → ProfilePolicy (merge)
        → ContextWriter (Plan → Build → Write → Outbox → DirSummary)
        → OutboxEvent → 异步 IndexRecordBuilder (L0 + L1 + L2 embed + upsert)

  会话 2 — 读取路径: "Alice 是做什么工作的?"
  ────────────────────────────────────────────────────────────────
    用户消息 → 阶段 ① message_received
        → QueryPlanner → type=MEMORY, intent=BACKGROUND_SUPPLEMENT
        → SeedRetriever → 向量搜索 + BM25 → L0 命中 (profile 匹配)
        → HierarchicalSearcher → 从 L0 展开 → 发现 L2 内容
        → ResultRanker → 按 URI 去重,排序,截断
        → 注入 "Alice 是一名后端工程师"
        → Agent 正确响应

写入耗时 ~50ms(同步)+ ~100ms(异步索引)。读取耗时 ~50ms。成本在写入时支付一次,在读取时多次分摊。


与典型方案的区别

ContextEngine 不是"多了几步的向量 RAG"。根本区别在于生命周期覆盖、写入策略和检索粒度。

维度 ContextEngine 标准向量 RAG Mem0
生命周期覆盖 6 阶段:抽取 → 存储 → 索引 → 召回 → 压缩 → 归档 1 阶段:检索 2 阶段:写入 + 检索
写入策略 4 种策略(merge / aggregate / append / cumulative),按信息语义选择 单一:upsert 单一:upsert with memory_id
检索粒度 L0/L1 目录路标 → 分层树展开 → L2 内容发现,BM25 融合,分数传播 + 热度 扁平 top-k 相似搜索 扁平 top-k + 图展开
上下文类型 7 类,每类独立生命周期行为(+ 3 类系统内部 Schema) 1 类:"document chunk" 1 类:"memory" + scope 标签
多租户隔离 文件系统层面强制(路径中 account_id + owner_space),调用方无法绕过 应用层过滤(依赖调用方) 应用层过滤
并发写入 乐观锁 + 版本检查 后写覆盖(或外部锁) 后写覆盖
原子性 4 步顺序写入,不完整状态可检测 尽力而为 尽力而为
压缩 信号评分 + 受保护节点 + 摘要链(Phase 2,进行中)

核心区别:ContextEngine 把上下文当作受管生命周期来处理,不是存取问题。写入策略不是配置 — 它们是源自信息语义的架构决策。检索不是单一操作 — 它是带预算感知的多阶段决策过程。系统设计为跨会话持续运行,而不仅是响应查询。


Roadmap

已完成

里程碑 核心交付
核心基础 领域模型、ContextFS 抽象(AGFS + SQL 适配器)、ctx:// URI 方案、4 步原子写入
抽取管线 YAML SchemaRegistry(10 个 Schema:7 用户面向 + 3 系统)、ReAct 抽取循环、Schema 驱动 PolicyRouter、4 种合并策略
分层检索 L0/L1/L2 IndexRecords、SeedRetriever(含 BM25 融合)、HierarchicalSearcher(树展开 + 分数传播 + 热度)、QueryPlanner、IntentClassifier
L0 结构化摘要 双模板抽取(每节点 L0 abstract + L1 overview)、overview-first 检索、session summary 生成
会话生命周期 SessionManager、TopicBuffer、session commit(archive + extract)、session context assembly、RollingCompressor
多租户认证 RBAC(ROOT/ADMIN/MEMBER)、API key 认证、IP 白名单 + 代理信任、agent sharing(off/whitelist/all)、审计日志
Agent 集成 Claude Code hooks 插件、OpenClaw TypeScript 桥接、ogmem 统一 CLI(onboard/start/stop/check/config/status/logs/eval)
多 Agent 交接 子 Agent spawn/ended 生命周期、Agent 间上下文交接、结果合并回父 Agent
边界检测 基于 LLM 的对话分块、消息边界检测、可配置分段大小

基准测试进展(LoCoMo10)

Run 准确率 关键改进
Run76 88.2% (1358/1540) L0 结构化摘要 + BM25 混合搜索 + 抽取 prompt 优化
Run69 88.2% L0 摘要注入 + prompt 优化(比 run68 +6.6%)
Run68 81.6% session_time 修复(基线)

基于 LoCoMo 长上下文对话记忆基准评测(10 个会话,4 个类别,1540 道题)。

进行中

里程碑 描述
上下文压缩(⑤ compact) 信号评分、受保护节点(Profile、活跃任务)、摘要链、预算感知截断
图检索 实体-关系图遍历用于多跳查询,关系加权展开

计划中

里程碑 描述
工具上下文注入(③) 工具调用前后 hook — 注入已知失败模式,压缩过大工具结果
会话恢复(⑥) 跨会话状态交接 — 会话结束时快照,新会话冷启动注入
图聚类 社区检测用于实体分组 — 自动将关联实体聚类为话题
自适应规划 查询感知的检索策略选择 — 复杂查询路由到更深的管线
可观测性 OpenTelemetry 追踪、token 使用面板、检索质量指标
AI Functions 工具增强的检索动作 — 上下文感知的工具选择和参数建议

快速开始

前置条件

  • Python 3.11+
  • PostgreSQL 14+pgvector 扩展(PostgreSQL 模式需要)
  • Docker(可选,用于容器化部署)

安装

git clone https://gitcode.com/opengauss/oG-Memory.git
cd oG-Memory
python3 -m venv .venv && source .venv/bin/activate
方式 A:AGFS 模式(默认)
pip install -e .

# 交互式配置向导(引导 LLM + Embedding + 向量库 + 存储配置)
ogmem onboard

# 一键启动(AGFS + ContextEngine)
ogmem start local
非交互模式(CI / 自动化)
ogmem onboard --non-interactive --mode headless \
  --provider openai --api-key sk-xxx \
  --embedding-model text-embedding-ada-002 --vector-db chroma \
  --storage-backend sql
方式 B:PostgreSQL 模式(直连 SQL 存储)

1. 安装并配置 PostgreSQL

# Ubuntu / Debian
sudo apt-get install postgresql postgresql-contrib
sudo apt-get install postgresql-16-pgvector   # 版本号按实际 PG 调整

# macOS
brew install postgresql@16
brew install pgvector

# 启动 PostgreSQL
sudo service postgresql start   # Ubuntu
brew services start postgresql  # macOS

# 创建数据库并启用 pgvector
sudo -u postgres createdb ogmemory
sudo -u postgres psql -d ogmemory -c "CREATE EXTENSION IF NOT EXISTS vector;"

2. 安装 ContextEngine(含 SQL 扩展)

pip install -e ".[dev,sql]"

3. 配置连接

cp config/ogmem.reference.yaml config/ogmem.yaml
# 编辑 storage.connection_string 指向你的 PostgreSQL 实例

使用

HTTP 服务(推荐)

AGFS 模式:

ogmem start local    # 启动 AGFS + ContextEngine,端口 1833 + 8090

PostgreSQL 模式:

cp config/ogmem.reference.yaml config/ogmem.yaml
# 编辑 ogmem.yaml: 设置 storage.backend 为 sql,storage.connection_string 为 PostgreSQL DSN
python server/app.py

写入对话轮次

curl -X POST http://localhost:8090/api/v1/after_turn
-H "Content-Type: application/json"
-d '{"userId":"user-1","sessionId":"session-1", "messages":[{"role":"user","content":"I am Alice, a backend engineer"}, {"role":"assistant","content":"Nice to meet you!"}]}'

搜索记忆

curl -X POST http://localhost:8090/api/v1/compose
-H "Content-Type: application/json"
-d '{"userId":"user-1","sessionId":"session-2","query":"what is alice job"}'


</details>

<details>
<summary><strong>Python SDK</strong></summary>

```python
from service.api import MemoryWriteAPI
from core.models import RequestContext
from fs.sql_adapter import SQLContextFS
from providers.config import ProviderConfig

config = ProviderConfig.from_env()
fs = SQLContextFS(connection_string="host=127.0.0.1 port=5432 dbname=ogmemory user=postgres password=postgres")
write_api = MemoryWriteAPI(fs=fs, llm=config.create_llm())

ctx = RequestContext(account_id="acct", user_id="u1", agent_id="a1", session_id="s1", trace_id="t1")
result = write_api.commit_session([
    {"role": "user", "content": "I'm Alice, backend engineer, London"},
    {"role": "assistant", "content": "Nice to meet you, Alice!"},
], ctx)
Docker / HTTP API 参考
docker compose up   # 服务端口 8090,PostgreSQL 端口 5432
端点 方法 说明
/api/v1/compose POST 搜索记忆,返回当前轮次上下文
/api/v1/after_turn POST 从对话中抽取并持久化记忆
/api/v1/ingest POST 单条消息写入
/api/v1/ingest_batch POST 批量消息写入
/api/v1/bootstrap POST 冷启动会话(profile + preferences 注入)
/api/v1/compact POST 触发上下文压缩
/api/v1/prepare_compaction POST 准备压缩令牌(预压缩规划)
/api/v1/dispose POST 会话处置 — 归档 + 清理
/api/v1/prepare_subagent_spawn POST 子 Agent 上下文交接(多 Agent)
/api/v1/on_subagent_ended POST 子 Agent 结果合并回父 Agent
/api/v1/token_stats GET/POST LLM & embedding token 用量(POST 带 reset 清除)
/api/v1/sessions/{id}/messages POST 向会话缓冲区添加消息
/api/v1/sessions/{id} GET 获取会话元数据 + 待处理 token
/api/v1/sessions/{id}/commit POST 提交会话:archive + extract
/api/v1/sessions/{id}/context GET 获取组装后的会话上下文
/api/v1/call/<method> POST 通用方法分发(前向兼容)
/api/v1/health GET 健康检查(storage + LLM + vector DB)
/api/v1/admin/accounts GET 列出账户
/api/v1/admin/accounts/{id} GET 获取账户
/api/v1/admin/accounts/{id}/users GET/POST 列出 / 创建用户
/api/v1/admin/accounts/{id}/users/{uid} DELETE 删除用户
/api/v1/admin/accounts/{id}/users/{uid}/role PATCH 设置用户角色(ROOT/ADMIN/MEMBER)
/api/v1/admin/accounts/{id}/roles GET 列出角色
/api/v1/admin/accounts/{id}/agents GET/POST 列出 / 注册 Agent
/api/v1/admin/accounts/{id}/agents/{aid} GET/PATCH 获取 / 更新 Agent
/api/v1/admin/accounts/{id}/audit-logs GET 列出审计日志
/api/v1/admin/accounts/{id}/audit-logs/{log_id} GET 获取单条审计日志
/api/v1/admin/config/agent-sharing GET Agent 共享配置

配置

主要环境变量(完整参考见 ENV.md)。 配置优先级:YAML 值 > 环境变量 > 硬编码默认值。

变量 默认值 说明
OGMEM_API_KEY LLM API 密钥(OpenAI 兼容)
OGMEM_BASE_URL 自定义 LLM API 基础 URL
OGMEM_LLM_MODEL gpt-4o-mini 抽取 + 分类使用的 LLM 模型
OGMEM_EMBEDDING_MODEL text-embedding-ada-002 向量索引使用的嵌入模型
OGMEM_EMBEDDING_API_KEY 嵌入 API 独立密钥(缺省回退 OGMEM_API_KEY
EMBEDDING_PROVIDER 独立嵌入提供商(openai / volcengine / st / mock
VECTOR_DB_TYPE chroma 向量后端:chroma / opengauss(pgvector)/ memory
STORAGE_BACKEND agfs 存储后端:agfs(AGFS 文件服务器)/ sql(PostgreSQL)
SQL_CONNECTION_STRING PostgreSQL DSN(STORAGE_BACKEND=sql 时必填)
AGFS_BASE_URL http://127.0.0.1:1833 AGFS 服务器 URL(STORAGE_BACKEND=agfs 时使用)
OGMEM_HTTP_PORT 8090 HTTP 服务监听端口
OGMEM_CONFIG config/ogmem.yaml YAML 配置文件路径
OG_ACCOUNT_ID acct-demo 默认账户 ID
OG_USER_ID u-alice 默认用户 ID
OG_AGENT_ID main 默认 Agent ID
OG_ROLE_CONTROL_ENABLED false 启用 RBAC 认证
OG_ROOT_API_KEY Root API key 用于管理员访问
OG_AGENT_SHARED_MODE off Agent 记忆共享:off / whitelist / all
OGMEM_AFTER_TURN_THRESHOLD 200 触发抽取的最小消息长度
OGMEM_CACHE_ENABLED true 启用检索缓存
CHUNKING_ENABLED false 启用边界检测 + 分块
INDEX_INTERVAL 30 索引 Worker 轮询间隔(秒)

仓库结构

ContextEngine/
├── core/                   # 领域模型、Protocol 接口、枚举、错误类型
├── fs/                     # ContextFS 抽象(上下文操作的文件系统隐喻)
│   ├── agfs_adapter/       #   AGFS-backed ContextFS(Go 文件服务器,默认后端)
│   └── sql_adapter/        #   PostgreSQL-backed ContextFS(原子 upsert、RLS 租户隔离)
├── extraction/             # CandidateExtractor(ReAct 循环 + YAML SchemaRegistry)
│   ├── prompts/            #   LLM 提示模板(Jinja2)
│   └── schemas/            #   Schema 注册 + 各类别 YAML 定义
│       └── definitions/    #     10 个 YAML 文件:profile, entity, event, skill, tool 等
├── commit/                 # 写入链路:PolicyRouter → MergePolicy → ContextWriter → OutboxStore
├── index/                  # 异步索引:OutboxWorker → IndexRecordBuilder → DirectorySummarizer
├── retrieval/              # 读取链路:QueryPlanner → IntentClassifier → SeedRetriever (+BM25)
│                          #   → HierarchicalSearcher → ResultRanker
├── providers/              # 外部适配:LLM、Embedder、VectorIndex、RelationStore
│   ├── llm/                #   OpenAI 兼容 LLM(支持 OpenAI/Volcengine/DashScope/Zhipu)
│   ├── embedder/           #   4 种后端(OpenAI、Volcengine、SentenceTransformers、Mock)
│   ├── vector_index/       #   InMemory / ChromaDB / pgvector (OpenGauss)
│   └── relation_store/     #   SQL + AGFS 关系存储
├── service/                # API 层:MemoryWriteAPI、MemoryService、IndexService
├── server/                 # HTTP REST 服务(Flask)、认证/RBAC、IP 白名单、会话管理
├── session/                # SessionManager、TopicBuffer、RollingCompressor、ArchiveStore
├── tests/
│   ├── contract/           # 跨团队契约测试(不变量检查)
│   ├── unit/               # 各包单元测试
│   ├── integration/        # 端到端集成测试
│   ├── e2e/                # LoCoMo 基准评测框架
│   ├── benchmark/          # 性能和质量基准
│   ├── ab/                 # A/B 对比测试
│   └── fixtures/           # 共享测试数据
├── docs/                   # 架构、部署、快速上手指南
├── examples/               # 使用示例(SDK、Agent 集成)
├── cli/                    # 统一管理 CLI(ogmem 命令)
│   └── commands/           #   onboard, start, stop, check, config, status, logs, eval
├── claude-plugin/          # Claude Code hooks 集成(hooks, scripts, skills)
├── openclaw_context_engine_plugin/  # OpenClaw 插件(TypeScript 桥接)
├── agfs/                   # AGFS Go 服务器源码(cmd/, pkg/, sdk/)
├── config/                 # 配置文件(ogmem.yaml, .env, AGFS 配置)
├── deploy/                 # Docker 部署脚本和配置
├── docker/                 # Docker Compose 文件
└── scripts/                # 辅助脚本(索引服务等)

Agent 集成

Claude Code

ContextEngine 提供原生 Claude Code hooks 实现零配置记忆:

ogmem onboard                           # 交互式:选择 "Agent Plugin" → "Claude Code"
ogmem start plugin                      # 启动 CE 服务 + 安装 hooks

OpenClaw

cd openclaw_context_engine_plugin && openclaw plugins install -l .
工具 阶段 操作
og_memory_write ④ 轮次结束 提取 + 持久化新上下文
og_memory_search ① 消息到达 预取相关上下文
og_memory_read ② 推理准备 按 URI 加载完整上下文

自动行为(无需 Agent 代码修改):新消息触发预取,轮次结束触发抽取,上下文填满触发压缩,会话关闭触发归档。


实现状态

Phase 0 + 1(生产质量): 详见 Roadmap 里程碑分解。

核心模型、ContextFS 抽象(AGFS + PostgreSQL 适配器)、抽取管线(YAML SchemaRegistry + ReAct 循环)、写入链路(4 种合并策略 + OutboxStore)、分层检索(L0/L1/L2)含 BM25 混合搜索、异步索引含死信队列、提供商(OpenAI/Volcengine/DashScope/Zhipu LLM、4 种嵌入器、InMemory/ChromaDB/pgvector)、HTTP REST API 含 RBAC 认证、会话管理、L0 结构化摘要生成、多 Agent 交接、边界检测/分块。100+ 测试文件(contract + unit + integration + e2e + benchmark)。

已覆盖生命周期阶段: ① message_received, ② bootstrap + ingest + assemble, ④ afterTurn

Phase 2(进行中): 上下文压缩管线、图检索。Phase 3(计划中): 工具上下文注入、会话恢复、图聚类、自适应规划、可观测性、AI Functions。

待覆盖生命周期阶段: ③ before_tool_call + tool_result_persist, ⑤ compression, ⑥ session_end + dispose

文档: CLAUDE.md(完整技术规范)| ENV.md(环境配置)| 快速开始 | 部署指南 | Claude 插件 | OpenClaw 插件 | 基准测试(LoCoMo 评测)

测试: pytest tests/contract/ -v(核心不变量)| pytest tests/ -v(全部测试)| pytest tests/ --cov=core --cov=fs --cov=service --cov-report=html


参考文献

基准测试与评估

LLM Agent 记忆架构

分层检索与多粒度

上下文压缩

推理与行动

多 Agent 与治理

基础设施

许可证

Apache License 2.0