Skip to content

Repository files navigation

🧠 Nexcore Context Engine

仿人类记忆模型的 Agent 上下文引擎——为 LLM Agent 提供可持久化、可检索、可推理的长期记忆。


TypeScript Fastify React Neo4j pnpm License: AGPL v3


Nexcore Context Engine 把「短期记忆 → 长期记忆」的认知过程落实为一条可观测、可评测的流水线:将对话与文档摄入为事件(Event),经 LLM 抽取为结构化事实(Fact),做时间轴融合后按策略准入短期记忆(STM),再通过「做梦」式巩固(Dreaming / Consolidation)沉淀为长期记忆(LTM),最终在需要时完成检索与 Context Pack 组装,为下游 Agent 提供带来源引用的上下文。

目录

✨ 核心特性

能力 说明
📥 多源摄入 文件(.txt / .md / .json / .docx)、Agent 写入、对话流,统一归一为 MemoryEvent
🔍 LLM 事实抽取 从非结构化文本抽取带时间与来源的结构化事实,支持批量与幂等写入
⏱️ 时间轴融合 对事实做时间推理与聚合,构建可查询的时间线,支撑「时间相关」类问答
🧩 STM 准入 由 LLM 判定事实是否进入短期记忆,附带准入原因与证据
🌙 做梦巩固 定时/手动触发的 dreaming 机制,以七维评分把 STM 巩固为 LTM(创建 / 修订 / 冲突消解)
🔎 混合检索 关键词 + 向量(bge-m3)+ 图召回 + 交叉编码器重排,输出带分数分解的候选
🧠 记忆图 Neo4j 存 STM/LTM 节点与关系,支持全文 + 向量索引,提供只读图查询 API
📦 Context Pack 组装 profile / task / recent 上下文,附引用(citation)与权限快照
🔐 权限与幂等 幂等写入、权限快照、来源引用,调试接口支持 includeInactive 查看被过滤项
🧪 评测闭环 内置 LongMemEval 与 LoCoMo 评测链路,端到端可复现

🧠 记忆模型

引擎借鉴人类记忆的「短时 → 长时」结构,把记忆生命周期拆成若干可独立观测的层:

Event ──parse──▶ Segment ──LLM抽取──▶ Fact ──时间轴融合──▶ STM ──做梦巩固──▶ LTM
   (原始事件)      (解析片段)        (结构化事实)    (时间线)   (短期记忆)      (长期记忆)
  • Event / Segment:一次原始输入及其解析产物。
  • Fact:LLM 抽取出的、带时间与来源声明的结构化事实,是检索的基本单元。
  • STM(短期记忆):刚通过准入判断的事实,权重高、易失效。
  • LTM(长期记忆):经做梦巩固后的稳定记忆,支持 revise / weaken / archive 等生命周期操作。

做梦巩固的七维评分定义、分数锚点与校准样例见 STM 到 LTM 七维评分 Prompt。

🏗️ 架构

flowchart TB
    subgraph ING["📥 摄入 Ingestion"]
        A1["文件 txt / md / json / docx"]
        A2["Agent Memory 写入"]
        A3["对话摄入 Conversation"]
    end

    subgraph PIPE["🔁 记忆流水线 Memory Pipeline"]
        B1["解析 Parse<br/>Event → Segment"]
        B2["事实抽取 Fact Extraction<br/>(LLM)"]
        B3["时间轴融合 Timeline Fusion"]
        B4["STM 准入 Admission<br/>(LLM 判定)"]
        B5["做梦巩固 Dreaming<br/>STM → LTM"]
    end

    subgraph STORE["🗄️ 存储 Store"]
        C1[("SQLite / JSON<br/>事实与状态")]
        C2[("Neo4j 图<br/>全文 + 向量索引")]
    end

    subgraph OUT["🔍 检索与组装 Retrieval & Pack"]
        D1["混合检索<br/>keyword + vector + graph + rerank"]
        D2["Context Pack 组装"]
    end

    A1 --> B1
    A2 --> B1
    A3 --> B1
    B1 --> B2 --> B3 --> B4 --> B5
    B2 --> C1
    B3 --> C1
    B4 --> C1
    B5 --> C2
    C1 --> D1
    C2 --> D1
    D1 --> D2
Loading

🛠️ 技术栈

层 技术
Monorepo pnpm workspaces
后端 Fastify + TypeScript + tsx
前端 React 18 + Vite 5
图存储 Neo4j(全文 + 向量索引)
本地存储 SQLite / JSON 文件
LLM OpenAI-compatible(默认 qwen3.7-flash,经 DashScope)
Embedding OpenAI-compatible(默认 bge-m3,经 SiliconFlow)

📁 项目结构

context-egine/
├── apps/
│   ├── backend/              # Fastify 后端:摄入、记忆流水线、检索、评测 CLI
│   │   └── src/modules/context-engine/   # 核心引擎实现
│   ├── web/                  # React + Vite 调试台
│   └── video/                # Remotion 记忆引擎演示视频
├── packages/
│   └── shared/               # 前后端共享类型(MemoryEvent / ContextPack / …)
├── config/
│   └── context-engine.json   # 引擎主配置
├── datasets/                 # LongMemEval / LoCoMo 评测数据集
├── docs/                     # 方案、评测报告与运行手册
├── openspec/                 # OpenSpec 规格驱动的变更规划
└── data/                     # 运行时存储(inbox、SQLite、评测产物)

🚀 快速开始

运行前提

  • Node.js 22+
  • pnpm 10+
  • (可选)Neo4j 5.x,用于图存储与向量/全文检索

安装与启动

# 安装依赖
pnpm install

# 启动后端 + 前端(并行)
pnpm dev

# 或分别启动
pnpm --filter @nexcore/backend dev   # 后端,默认 http://localhost:3101
pnpm --filter @nexcore/web dev       # 调试台,默认 http://localhost:5173

启动后打开 http://localhost:5173 即可进入调试台,写入测试记忆事件并查看解析、事实、STM、LTM 与融合时间轴。

一条链路跑通

# 1. 写入一条 Agent 记忆
curl -X POST http://localhost:3101/context/agent-memory \
  -H 'content-type: application/json' \
  -d '{
    "content": "用户偏好:回答要短,但要给验证证据。",
    "idempotencyKey": "basic-memory-demo-1",
    "sourceApp": "agent",
    "sourceId": "chat-session-demo"
  }'

# 2. 检索刚写入的记忆
curl 'http://localhost:3101/context/search?q=验证证据&layer=all&limit=5'

⚙️ 配置

默认配置文件为 config/context-engine.json,后端与前端代理都会读取。可用 CONTEXT_ENGINE_CONFIG 指向另一份配置:

CONTEXT_ENGINE_CONFIG=/absolute/path/context-engine.json pnpm dev

配置结构(示例):

{
  "server": { "host": "127.0.0.1", "port": 3101 },
  "dreaming": { "enabled": true },
  "storage": { "storePath": "data/context-engine-store.json" },
  "ingestion": { "inboxDirectory": "data/inbox" },
  "llm": {
    "provider": "openai-compatible",
    "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
    "model": "qwen3.7-flash",
    "apiKeyEnv": "OPENAI_API_KEY"
  },
  "embedding": {
    "protocol": "openai-compatible",
    "model": "BAAI/bge-m3",
    "apiKeyEnv": "EMBEDDING_API_KEY",
    "dimensions": 1024
  },
  "graphStore": {
    "mode": "neo4j",
    "neo4j": { "uri": "neo4j://127.0.0.1:7687", "database": "neo4j" }
  }
}

环境变量

部署或本地调试时,以下环境变量会覆盖配置文件:

环境变量 作用
PORT 后端端口(同时影响前端代理目标端口)
CONTEXT_ENGINE_STORE_PATH 持久化 JSON 文件路径
CONTEXT_ENGINE_INBOX_DIR 固定文件摄入目录
OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_API_KEY LLM 相关覆盖
LONGMEMEVAL_STORE_DIR LongMemEval 独立 SQLite 存储目录
LONGMEMEVAL_GRAPH_STORE LongMemEval 图存储模式:inherit / local / neo4j
LONGMEMEVAL_NEO4J_* LongMemEval 独立 Neo4j 连接、索引名等

longMemEval.graphStore.mode 默认为 inherit(沿用主 graphStore);设为 local 只用独立 SQLite;设为 neo4j 使用 longMemEval.graphStore.neo4j,未填写的字段继承主 graphStore.neo4j。

📚 核心链路

文件摄入

后端扫描固定目录 data/inbox 的第一层文件(.txt / .md / .json / .docx),生成 MemoryEvent 进入解析链路。.docx 从 word/document.xml 提取正文(暂不提取批注、修订、页眉页脚);.xlsx / .pptx / 图片会生成 unsupported 事件。

# 把文件放入 data/inbox,然后触发扫描
curl -X POST http://localhost:3101/context/ingest/files \
  -H 'content-type: application/json' -d '{}'

去重规则:file path + mtime + size 生成幂等 key,同一文件重复扫描不会重复写入,文件修改后视为新版本重新摄入。

结构化事实导入

对 序号 / 事实发生时间 / 记忆类型 / 事实记忆 / 来源类型 测试表,用确定性脚本导入(不调用 LLM):

pnpm import:weekly-facts --dry-run
pnpm import:weekly-facts --apply

脚本默认读取根目录的 极核产品经理一周事实记忆假数据.md,写入 synthetic-test 租户,并可用 --file / --dataset-id / --tenant / --principal 覆盖。

🔌 HTTP API

摄入与写入

方法 路径 说明
POST /context/events 写入原始 MemoryEvent
POST /context/agent-memory Agent 快速写入(受控事件 + 复用解析/准入链路)
POST /context/ingest/files 扫描 data/inbox 文件

检索与组装

方法 路径 说明
POST /context/search 检索 fact/STM/LTM,返回分数分解与来源引用
POST /context/assemble 组装 Context Pack
GET /context/read 读取上下文
POST /context/memory-graph/query 只读分页查询记忆图节点与关系

记忆图查询

curl -sS -X POST http://localhost:3101/context/memory-graph/query \
  -H 'content-type: application/json' \
  -d '{ "page": 1, "nodePage": { "limit": 100 }, "edgePage": { "limit": 500 } }' | jq .

响应使用 memory-graph.v1,节点与边共用顶层 page 但各自管理 limit,可用 nextCursor 稳定遍历。接口按「单用户 engine」设计,不做 owner 隔离,采用最终一致语义,不返回 embedding / 内部 graph node ID / Prompt / 调试 Trace。

做梦巩固(Dreaming)

方法 路径 说明
POST /context/dreaming/runs 创建 dreaming run
GET /context/dreaming/runs 列出 dreaming run
POST /context/dreaming/run 手动触发一次巩固

调试与反馈

GET    /context/debug/snapshot
GET    /context/tools
POST   /context/debug/manual-flow
POST   /context/debug/manual-step
POST   /context/feedback
POST   /context/permissions/invalidate
DELETE /context/debug/data

调试检索时加 includeInactive=true 可查看被过滤项;检索结果包含 scoreBreakdown、permissionStatus 与 dropped 原因。

📊 评测与基准

仓库保留三条语义不同的评测链路:

命令 语义
eval:longmemeval LongMemEval 端到端,一题对应一个隔离 haystack
eval:locomo LoCoMo 原生端到端,一个长对话只摄入一次,全部问题共享同一隔离 scope

LongMemEval

# 完整数据集评测
pnpm --filter @nexcore/backend eval:longmemeval datasets/LongMemEval/longmemeval_s_cleaned.json

# 按题目 ID / 区间
pnpm --filter @nexcore/backend eval:longmemeval sample \
  --dataset datasets/LongMemEval/longmemeval_s_cleaned.json --question-id e47becba

# 比例切分 + CI(stdout 仅 JSON)
pnpm --filter @nexcore/backend eval:longmemeval split \
  --dataset datasets/LongMemEval/longmemeval_s_cleaned.json \
  --ratio 0.1 --seed 20260806 --ci --result artifacts/longmemeval-result.json

完整操作手册见 docs/longmemeval-cli-benchmark.md。

LoCoMo 原生

# 准备一个 conversation 的 Fact/STM Store
pnpm --filter @nexcore/backend eval:locomo prepare \
  --sample-id conv-26 --store-path data/longmemeval/locomo-conv-26.sqlite

# 使用已准备 Store 只读评测
pnpm --filter @nexcore/backend eval:locomo evaluate \
  --sample-id conv-26 --store-path data/longmemeval/locomo-conv-26.sqlite \
  --result artifacts/locomo-conv-26.results.jsonl \
  --trace artifacts/locomo-conv-26.trace.jsonl \
  --summary artifacts/locomo-conv-26.summary.json

# 准备并评测前两个 conversation
pnpm --filter @nexcore/backend eval:locomo full --sample-range 1:2

官方 QA 指标是逐题 token F1 的自然加权平均,报告同时提供各 category 平均分与 perfectScoreRate。只评测 category 1-4,对抗性/不可回答题型(category 5)不参与答题与评分。可复现实验应固定数据集 SHA-256、模型/embedding 配置、profile 和独立 Store 路径。

候选召回 Benchmark

pnpm --filter @nexcore/backend eval:retrieval -- \
  --dataset data/longmemeval_s_cleaned.json \
  --output artifacts/retrieval-baseline.json \
  --diagnostics artifacts/retrieval-baseline.jsonl

报告包含 Recall / Precision / MRR / NDCG,以及分阶段诊断(fact_not_generated、memory_not_indexed、not_in_top_k 等)。

📖 文档

核心方案与运行手册集中在 docs/,重要的入口:

仓库根目录还保留了历史实现方案(Context-Engine-*.md、背景上下文技术方案.md 等),可作为设计回溯。

🤝 贡献

项目使用 OpenSpec 做规格驱动开发,变更规划沉淀在 openspec/changes/ 下。贡献流程:

openspec list
openspec validate <change-name>
openspec status --change <change-name>

提交与 PR 规范详见 AGENTS.md。提交前请运行:

pnpm build
pnpm typecheck
pnpm test

📄 License

本项目采用 GNU Affero General Public License v3.0 (AGPL-3.0) 许可协议。

AGPL-3.0 要求:任何通过网络提供本软件功能的服务,都必须向用户开放其修改后的完整源代码。完整条款见 LICENSE。

About

No description, website, or topics provided.

Resources

Stars

1.0k stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages