内容
<!-- mcp-name: io.github.Astrix-Labs/genesys-memory -->
[](https://pypi.org/project/genesys-memory/)
[](https://pypi.org/project/genesys-memory/)
[](https://github.com/Astrix-Labs/genesys/actions/workflows/ci.yml)
[](https://www.gnu.org/licenses/agpl-3.0)
# 基因表达
**人工智能记忆的智能层。**
> 基因表达不仅能记住发生了什么,还能记住为什么。一个用于人工智能代理记忆的评分引擎 + 因果图 + 生命周期管理器。本地支持MCP。
<img width="1512" height="827" alt="image" src="https://github.com/user-attachments/assets/d152aa07-a852-4b8e-9f98-942d0bebd497" />
## 这是什么
基因表达是一个用于人工智能记忆的评分引擎、因果图和生命周期管理器。记忆通过乘法公式(相关性 × 连接性 × 激活)进行评分,通过因果图连接,并主动遗忘不相关的记忆。
该软件包(`genesys-memory`)是核心库:一个内存因果图引擎,具有可选的JSON持久性,以及一个stdio MCP服务器。它没有数据库依赖,也没有REST API。在此库的基础上构建的托管产品 — 具有Postgres、附加存储后端和REST/HTTP MCP API — 在`genesys-api.astrixlabs.ai`上单独提供;它不是此软件包的一部分。
## 为什么
- **扁平记忆无法扩展。** 将所有内容转储到向量存储中可以实现召回,但没有理解。第500个记忆掩埋了5个重要的记忆。
- **没有遗忘就没有智能。** 真正的记忆系统会遗忘。没有主动修剪,人工智能会淹没在过时的上下文中。
- **没有因果推理。** 向量相似性无法回答“为什么选择X?” — 您需要一个图。
您的人工智能记得一切,但不理解任何事情。基因表达解决了这个问题。
## 快速入门
安装软件包。基本安装没有数据库依赖 — 状态存储在内存中,可选地持久化到JSON文件。
```bash
pip install genesys-memory
```
可选的额外功能:
```bash
pip install 'genesys-memory[openai]' # OpenAI embeddings
pip install 'genesys-memory[local]' # Local embeddings (sentence-transformers, no API key)
pip install 'genesys-memory[anthropic]' # LLM-based causal inference (consolidation, contradiction detection)
```
直接运行stdio MCP服务器:
```bash
python3 -m genesys_memory
```
### 从源代码
```bash
git clone https://github.com/Astrix-Labs/genesys.git
cd genesys
pip install -e '.[dev]'
pytest tests/
```
## 连接到您的人工智能
### Claude 代码
```bash
claude mcp add genesys -- python -m genesys_memory
```
### Claude 桌面版
将以下内容添加到您的 `claude_desktop_config.json`:
```json
{
"mcpServers": {
"genesys": {
"command": "python",
"args": ["-m", "genesys_memory"]
}
}
}
```
### 可靠性和重试
stdio服务器是一个单独的本地进程。在负载下或在托管传输重启或重新部署期间,工具调用可能会暂时失败或连接可能会短暂断开。内存写入和读取不值得因代理回合崩溃而牺牲,因此**客户端应优雅地降级,而不是将内存调用视为致命错误**:
- **服务器也优雅地降级**:工具异常(或缺少必需参数)作为结构化`{"error": "...", "retryable": bool}`有效载荷返回,而不是协议级MCP失败,因此内存卡顿永远不会使传输崩溃。`retryable`标志编码以下指南 — 仅适用于读取工具。
- **重试幂等读取** (`memory_recall`, `memory_search`, `memory_traverse`, `memory_explain`, `memory_stats`),采用短有界回退(例如2-3次尝试)。这些副作用微不足道,除了重新激活记账。
- **不要盲目重试`memory_store` / `memory_amend`**,在模糊超时时 — 静默成功后重试会创建重复节点。最好继续转折并在下一个`memory_recall`上协调,或传递稳定的`source_session`,以便轻松发现重复节点。
- **将内存视为尽力而为的上下文,而不是硬依赖。** 如果调用失败,请继续使用您已经拥有的上下文,并在下一个转折中重试,而不是中止。图是持久的;错过的写入是可恢复的,而崩溃的代理转折则不可恢复。
## MCP 工具
| 工具 | 描述 |
|------|-------------|
| `memory_store` | 存储新的记忆。使用`related`指定作者指定的**类型**边(`{id, type}`);`related_to`是遗留的,始终创建`caused_by`。可选`category`。可能返回`possible_conflicts`(启发式提示)。 |
| `memory_amend` | 记录更正:创建新的记忆,**取代**现有的记忆。旧记忆被保留(衰减召回),不被删除。 |
| `memory_recall` | 通过自然语言查询(向量 + 关键词 + 图传播激活)回忆记忆。支持`verbosity: "concise"`用于轻量级有效载荷。 |
| `memory_search` | 按状态、类别、日期(`since`)、最近活动日期(`active_since`)或实体过滤的向量搜索。传递**空查询**以按时间顺序枚举 — 无需嵌入 — 使用`since`/`active_since`回答“自上次查看后有什么新内容”而无需知道查询内容。 |
| `memory_traverse` | 从节点行走因果图。返回可达**节点和边**的诱导子图(`source/target/type/weight/created_by`)— 超集于BFS树,因此可以重建路径。遵守`edge_types`。 |
| `memory_explain` | 解释记忆的分数。包括`score_model`块(公式 + 实时分解 + 停滞注释)和`removal_impact`。 |
| `memory_stats` | 获取记忆系统统计信息 |
| `pin_memory` | 固定记忆,使其永远不会被遗忘 |
| `unpin_memory` | 取消固定先前固定的记忆 |
| `delete_memory` | 永久删除记忆 |
| `list_core_memories` | 列出核心记忆,可选按类别过滤 |
| `set_core_preferences` | 设置核心记忆类别的用户偏好 |
| `promote_to_org` | 将私有记忆提升为组织可见性 |
### 作者指定的边和更正
`memory_store`的`related`参数允许作者设置边语义,而不是猜测。每个条目都是`{"id": "<node-id>", "type": "<edge-type>"}`,有方向`new_node --type--> target`(因此`supersedes`表示新节点取代目标)。无效类型在节点创建**之前**被拒绝;显式写入永远不会部分成功。`related_to`仍然存在,但始终创建`caused_by`;请优先使用`related`。
要更正事实,请使用`memory_amend(node_id, content, reason=...)`:它存储新版本,链接`SUPERSEDES → old`,并**保留旧记忆**用于审计。自动召回降低了被取代的命中率,并标记它们为`superseded_by`。
当您`memory_store`某些内容与自动链接候选词(更改的数字、否定)相矛盾时,结果可能包括`possible_conflicts` — 启发式提示,**不是**已验证的矛盾,并且永远不会实现为边。使用它们来决定是否`memory_amend`。
### 简洁回忆
`memory_recall(query, verbosity="concise")`跳过因果链增强,仅返回每个命中`id / summary / status / score / activation / is_core`(加上`superseded_by`,如果设置)— 对于高频查找,令牌消耗更少。`verbosity="full"`(默认)保持不变。重新激活写入仍然发生(它们由`read_only`控制,而不是`verbosity`)。
参见 [`docs/scoring.md`](docs/scoring.md) 了解 `activation` / `decay_score` 的实际含义 — 简而言之,它是一种保留权重,当记忆被召回时**增加**,而不是删除的倒计时。
## 它是如何工作的
每个记忆通过三个力量的乘法公式进行评分:
```
decay_score = relevance × connectivity × reactivation
```
- **相关性** 随时间衰减。旧记忆除非强化,否则会逐渐消失。
- **连接性** 奖励具有许多因果联系的记忆。中心记忆得以存活。
- **重新激活** 提升不断被召回的记忆。频率很重要。
由于公式是乘法运算的,因此记忆必须在**所有三个**轴上得分才能存活。具有高连接性但从未被访问的记忆仍然会衰减。经常被召回但因果孤立的记忆仍然会消失。
`decay_score`(在每次命中时别名为`activation`)是**保留权重,而不是删除倒计时** — 回忆记忆会**增加**它,而低分数只意味着“休息”,而不是“注定”。删除需要低分数 **和** 孤立 **和** 未固定 **和** 非核心 **和** 非组织**,同时满足所有条件。参见 [`docs/scoring.md`](docs/scoring.md) 了解完整的模型和计算数字。
```
STORE → ACTIVE → DORMANT → FADING → PRUNED
↑ │
└── reactivation ────┘
(仅当score=0, 孤立, 未固定)
```
记忆也可以被提升到 **核心** 状态 — 结构上重要的记忆,会自动固定并永远不会被修剪。
## 基准测试结果
我们在开发过程中针对 [LoCoMo](https://arxiv.org/abs/2402.06397) 长对话记忆基准测试运行了内部评估。这些是自我报告的结果,使用我们自己的测试框架运行(类别 5 — 有争议的问题和有争议的事实 — 被排除),并且没有独立复制,因此将其视为方向性而不是已验证的声明。如果您想运行自己的数字,请在 [`benchmarks/`](benchmarks/) 中提供复制脚本。
## 存储后端
此软件包提供了一种存储后端:一个内存因果图(`storage/memory.py`),具有通过 `GENESYS_PERSIST_PATH` 进行的可选 JSON 持久性。不需要数据库。
附加后端 — Postgres/pgvector、FalkorDB、MongoDB 和 Obsidian vault 适配器 — 以及 REST API、OAuth 和多用户身份验证 — 是托管产品的一部分,位于 `genesys-api.astrixlabs.ai`,不包含在此仓库中。
想为开源库添加不同的存储后端?在 [`storage/base.py`](src/genesys_memory/storage/base.py) 中实现提供者协议,并带来您自己的。
## 配置
复制 `.env.example` 到 `.env` 并设置:
| 变量 | 必需 | 描述 |
|----------|----------|-------------|
| `OPENAI_API_KEY` | 除非 `GENESYS_EMBEDDER=local` | 嵌入 |
| `ANTHROPIC_API_KEY` | 否 | 启用基于LLM的因果推理(巩固、矛盾检测)。默认为关闭 — 没有它,因果边仅来自调用者在`memory_store`中明确声明的边加上余弦相似性链接。 |
| `GENESYS_EMBEDDER` | 否 | `openai`(默认)或 `local`(sentence-transformers,无API密钥) |
| `GENESYS_PERSIST_PATH` | 否 | JSON文件路径,用于在重启时保持状态(否则在内存中) |
| `GENESYS_USER_ID` | 否 | 单租户模式下的默认用户ID |
### 自动链接调优
自动链接将新存储的记忆连接到语义相似的现有记忆。如果过于宽容,您会得到一个“毛球” — 所有内容最终都在 ~2 跳之内互相链接,从而破坏遍历范围。三个旋钮控制它:
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `GENESYS_AUTOLINK_MIN_SIMILARITY` | 嵌入者推荐 | 创建自动链接的余弦下限。显式值优先于嵌入者默认值。 |
| `GENESYS_AUTOLINK_MAX_EDGES` | `3` | 单个 `memory_store` 可以创建的最大自动链接数。限制了节点的出度。 |
| `GENESYS_AUTOLINK_MAX_NODE_DEGREE` | `10` | 任何单个节点可以 **累积** 的最大自动链接边。仅出度限制了中心节点仍然可以获得一个边/存储/永远;此限制了中心节点本身。 |
下限是**嵌入者感知**的:自动链接是永久图结构,因此其下限位于**之上**瞬时召回下限。当 `GENESYS_AUTOLINK_MIN_SIMILARITY` 未设置时,实际下限是嵌入者的推荐 — **OpenAI 为 0.6** (`text-embedding-3-small`,其真实匹配集群 ~0.5+) 和 **local 为 0.45** (sentence-transformers,其真实匹配集群 ~0.2-0.4 但噪声对 ~0.44 观察到,因此仅本地自动链接近乎重复内容)。任何未知嵌入者都默认为 0.45。自动链接还会去重:如果一对已经通过**任何**边(例如 `user_explicit` `caused_by`)连接,则不会创建并行 `auto_link related_to`。
`possible_conflicts` 提示 `memory_store` 扫描具有**其自身较低下限** (`GENESYS_CONFLICT_MIN_SIMILARITY`,默认为召回下限)更广泛的窗口 (`GENESYS_CONFLICT_SCAN_K`,默认为 8) — 因此收紧自动链接下限永远不会缩小冲突检测。
### 召回/相关性下限
相同的嵌入者感知模式控制召回过滤:
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `GENESYS_RECALL_MIN_SIMILARITY` | 嵌入者推荐(OpenAI 0.5 / 其他 0.2) | 纯向量命中在`memory_recall`中被丢弃的余弦下限。关键词命中绕过它。 |
| `GENESYS_CORE_INJECT_MIN_SIMILARITY` | 嵌入者推荐(OpenAI 0.45 / 其他 0.2) | 将自动提升的核心记忆注入召回结果的下限。固定的记忆始终被注入。 |
### 评分旋钮
三力评分公式及其生命周期阈值都是可通过环境变量配置的(参见 [`engine/config.py`](src/genesys_memory/engine/config.py) 和 [`docs/scoring.md`](docs/scoring.md)):`GENESYS_ACTR_DECAY`、`GENESYS_RELEVANCE_VECTOR_WEIGHT`、`GENESYS_RELEVANCE_KEYWORD_WEIGHT`、`GENESYS_MIN_CONNECTIVITY`、`GENESYS_FORGETTING_THRESHOLD`、`GENESYS_DORMANCY_*`转换阈值和`GENESYS_CORE_*`提升权重。
参见 [`.env.example`](.env.example) 获取所有选项。
## 由谁构建
基因表达由 [Astrix Labs](https://astrixlabs.ai) 的 [Rishi Meka](https://github.com/rishimeka) 构建。它源于每次会话都需要向Claude解释项目上下文的挫折感。目标是LLM和内存之间的智能层 — 完全开源。
## 贡献
参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
## 许可证
[AGPL-3.0-or-later](LICENSE)
> **注意:** 基因表达 v0.3.6 之前的版本错误地在文档中注明为 Apache 2.0。LICENSE 文件始终包含 AGPLv3 文本。从 v0.3.6 及以后,所有文档都正确引用 AGPL-3.0-or-later,并附有贡献者许可协议。