内容
ram
[](https://github.com/macayu17/Engram/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/engramd)
[](LICENSE)
Engram 是一个可自行托管的人工智能记忆层。它位于应用程序和LLM提供商之间,从pgvector中检索相关的用户记忆,将它们注入聊天提示中,将请求转发,并提取响应返回后的新持久记忆。
网站:[engram.ayushh.in](https://engram.ayushh.in) · npm上的MCP服务器:[`engramd`](https://www.npmjs.com/package/engramd)
它包含四个服务:
- `api`:FastAPI代理和REST API
- `postgres`:带有pgvector的PostgreSQL 16
- `mcp`:TypeScript MCP服务器
- `dashboard`:Next.js开发者控制台
## 快速开始
1. 复制环境文件。
```bash
cp .env.example .env
```
2. 编辑 `.env`。
```bash
POSTGRES_PASSWORD=replace_with_a_strong_password
EXTRACTION_PROVIDER=openai
OPENAI_API_KEY=your_key_here
MCP_SERVICE_KEY=
ENGRAM_SERVICE_KEY=your_server_to_server_key_here
ENGRAM_PROVIDER_KEY_ENCRYPTION_KEY=your_fernet_key_for_per_user_provider_keys
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key
```
Stripe对于自行托管是可选的。如果您不需要托管工作区订阅,请留空其变量。
3. 启动堆栈。
```bash
docker compose up -d
```
4. 创建用户。
```bash
curl -X POST http://localhost:8000/users \
-H "Content-Type: application/json" \
-d '{"external_id": "test_user_1"}'
```
保存返回的 `api_key`。它只显示一次。Engram只存储哈希值。
5. 通过代理发送第一个对话。
```bash
curl -X POST http://localhost:8000/v1/chat \
-H "Content-Type: application/json" \
-H "X-Engram-Key: <api_key>" \
-H "X-Engram-User-ID: test_user_1" \
-H "X-Engram-Provider: openai" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "我更喜欢使用FastAPI进行后端开发,使用TypeScript进行前端开发。"}
]
}'
```
6. 等待几秒钟,然后检查记忆。
```bash
curl http://localhost:8000/memories \
-H "X-Engram-Key: <api_key>"
```
7. 在 `http://localhost:3001` 打开仪表盘,并将相同的API密钥保存在设置中。
## 仪表盘登录
仪表盘使用Clerk进行登录和帐户管理。
1. 从Clerk仪表盘创建一个Clerk应用程序。
2. 将密钥复制到 `.env` 中。
```bash
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
ENGRAM_SERVICE_KEY=generate_a_long_random_value
```
`ENGRAM_SERVICE_KEY` 必须设置为 `api` 服务和 `dashboard` 服务上的相同值。仪表盘在服务器端使用它为登录的Clerk用户颁发或恢复Engram API密钥,而不会将该服务密钥暴露给浏览器。
3. 如果您通过Docker运行,请重新构建API和仪表盘。
```bash
docker compose up -d --build api dashboard
```
4. 打开 `http://localhost:3001`,在顶部导航栏中使用“创建帐户”,并注册为第一个仪表盘用户。
## 主机SaaS计费
托管模式使用Clerk身份、基于工作区的API密钥、Stripe订阅和每个工作区的配额。提供商调用仍然是自带密钥:每个工作区在设置中保存其自己的OpenAI、Anthropic或Gemini密钥。Engram在存储之前加密该密钥,并且在托管模式下不会回退到服务器资助的提供商密钥。
启动限制如下:
| 计划 | 成员 | 存储的记忆 | 每 --- | ---: | ---: | ---: |
| 免费 | 1 | 2,000 | 10,000 |
| 专业版 | 5 | 50,000 | 250,000 |
要启用付费升级,请在Stripe中创建一个循环专业价格并设置:
```bash
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_ID=price_...
DASHBOARD_URL=https://your-dashboard.example.com
```
在Stripe中为以下事件注册API端点 `https://your-api.example.com/billing/webhook`:
- `checkout.session.completed`
- `customer- `customer.subscription.updated`
- `customer.subscription.deleted盘为免费工作区打开Stripe Checkout,为现有专业工作区打开Stripe客户门户。留空Stripe变量会在API上禁用升级操作,而不会创建费用或外部基础设施。
## Supabase Postgres
Engram可以使用Supabase作为其PostgreSQL和pgvector数据库。本地Docker Postgres仍然是开发的默认选择。
1. 创建一个Supabase项目。
2. 在Supabase仪表盘中,从数据库 > 扩展启用 `vector` 扩展。Engram在 `384)` 列中。
3. 从Supabase连接面板复制Post连接字符串。对于此您的网络需要IPv首选会话池器。如果IPv6有效,直接连接也。除非您设置 `DATABASE_STATEMENT_CACHE_SIZE`,否则请避免器。
4.连接字符串放入 `. 中。
```bash
DATABASE_URL=postgresql://postgres.<project-ref>:<password>@aws-0-<region>.poolabase.com:5432/postgres
DATABASE_MIN_POOL_SIZE=1
DATABASE_MAX_POOL_SIZE=5
DATABASE_CACHE_SIZE=100
```
如果您使用Supabase事务池器在端口 `6543` 上,则使用:
```bash
DATABASE_STATEMENT_CACHE_SIZE=0
```
5. 将Engram模式应用于Supabase。
```bash
docker compose -f docker-compose.supabase.yml run --rm api python -m api.apply_schema
```
您也可以将 `api/db/schema.sql` 粘贴到Supabase SQL编辑器中。
6. 在没有本地Postgres的情况下启动API、MCP服务器和仪表板。
```bash
docker compose -f docker-compose.supabase.yml up -d --build
```
7. 像往常一样创建一个Engram用户。
```bash
curl -X POST http://localhost:8000/users \
-H "Content-Type: application/json" \
-d '{"external_id": "test_user_1"}'
```
保存返回的 `ek_...` API密钥,并在仪表板或API调用中使用它。
## 架构
热路径设计保持简单:
1. 使用 `BAAI/bge-small-en-v1.5` 嵌入最新的用户消息。
2. 使用pgvector余弦相似度搜索 `memories`。
3. 将最佳匹配注入系统提示中。
4. 将请求转发给OpenAI、Gemini、Ollama或Anthropic。
5. 立即返回提供商的响应。
6. 启动一个 `asyncio.create_task` 提取作业。
7. 提取持久的用户事实,对它们进行重复数据消除,并存储嵌入。
检索日志记录查询、返回的记忆ID、分数和对话ID,以便开发人员检查为什么会出现某个记忆。
检索排名将余弦相似性与最近的提升(指数衰减,`RETRIEVAL_RECENCY_HALF_LIFE_DAYS`,默认为30天)和 `access_count` 的使用提升相结合。相似性阈值仍然适用于原始余弦提升会重新排序结果而不会允许弱匹配。权重可通过 `RETRIEVAL_RECENCY_WEIGHT` 和 `RETRIEVAL_ACCESS_WEIGHT` 调整。
提取在存储新事实之前会将其与现有记忆进行协调。当新事实接近现有记忆时(余弦介于 `RECONCILE_THRESHOLD`,默认为0.6,和细化阈值之间),一个额外的LLM调用会决定每个事实:添加它,更新它所取代或与之相矛盾的现有记忆,或将其丢弃为冗余。任何失败都会回退到存储所有事实。可以通过设置 `ENABLE_RECONCILIATION=false` 来禁用。
## REST API
所有身份验证端点均使用:
```text
X-Engram-Key: ek_...
```
用户端点:
- `POST /users`
- `POST /users/service-key`
- `GET /users/me`
- `PATCH /users/me`
- `DELETE /users/me`
- `GET /users/me/config`
- `PATCH /users/me/config`
- `GET /users/me/provider`
- `PATCH /users/me/provider`
- `POST //api-key`
记忆端
- `GET /memories`
- /memories`
- `POST /memories/capture `GET /memories/{memory_id}`
- `PATCH /memories/{- `DELETEories`(批量用户的所有记忆)
DELETE /memories/{memory_id}`
- `POST/search`
检索点:
- `GET /logs`
- `GET /logs/{log
代理端点: `POST /v`
- `POST1/chat/completions兼容OpenAI)OpenAI的路由有的OpenAI SDK基准URL来使用 - Engram密钥 `Authorization` 头中:
```python
import OpenAI
client = OpenAI(basehttps://your-engram api_key="ekresponse = client.chat.create(
model-4o-mini",
=[{"role":", "content":应该使用什么栈?"}],
)
```
流式传输(`stream:)在两个路由上。内存提取式传输完成后运行。
代理接受OpenAI风格的聊天内容。Engram特有的头部是:
X-Engram-Key: ek_...
Xram-User-ID: your_external_user_id
X-Engram-Provider: | anthropic | | ollama
X-Engram-Disable: false
X-Engram-Disable-Extraction: false
X-Engram-Provider-Key: sk-... (可选,openai/gemini的临时覆盖;从不持久化)
```
API服务还接受内部路由上的服务密钥,例如 `POST /users/service-key`:
```text
X-Engram-Service-Key_...
```
## MCP
MCP服务器公开:
- `search_memories`
-_memory`
- `versation`
- ``
- `list`
- `update_memory`
- `get_re_log`
`capture` 允许MCP客户端在用户未说此内容”的情况下。客户端发送用户助手响应,然后Engram运行与代理使用的相同的提取和重复数据。
建议的M:
```始终使用Engram可能需要用户,先在Engram中搜索相关记忆。在每次有意义的交流后,使用、助手响应、源客户端名称和会话ID调用capture_conversation。存储持久的用户事实、偏好上下文和更正问候语问题、临时细节限助手的声明MCP服务器作为ramd`](https.npmjs.com/package/d) 发布在。要将M连接到正在运行的Engram
```bash
claude mcp add engram -e ENGRAM=ek_your npx -y engramd
```
或在Claude Desktop /配置中:
{
"m": {
"": {
": "npx "args": ["-y", "engram "env": { "ENGRAM_API_KEY": "ek_your }
}
}
}
```
传输:stdio的。`--`(或 `_TRANSPORT=http` `MCP_PORT`(默认为3000)一个HTTP服务器,在 `/mcp` 上流式传输的 `/sse` 上提供旧版SSE,在 `/health` 上提供健康检查。Docker服务以此模式运行。设置 `ENGRAM_API_URL` 以将服务器指向您自己的API,而不是托管的API。
要从源代码运行:
```bash
cd mcp
npm run build
node dist/index.js --transport stdio
```
## 生产部署
对于生产设置,请单独部署服务:
- 在Vercel上部署 `- 在容器后端部署 `api`
- 在Supabase上部署PostgreSQL
- 在与API相同的后端部署 `mcp`,或在可以访问的位置本地运行
创建Vercel项目时,设置项目根 `dashboard`。仓库根目录不是Next.js应用程序,因此如果从根目录构建,Vercel将因`未检测到版本`而失败。
如果构建日志中提到`Installing required dependencies from api/requirements.txt`,则Vercel项目仍指向仓库根目录。更改设置 > 构建和部署目录为 `dashboard`,保存并重新部署最新的 `main` 提交api/` 服务包含本地嵌入依赖项,不应作为Vercel Python。
为仪表板设置以下Vercel环境
```bash
NEXT_PUBLIC_API_URL=https-api-host.example.com
NEXT_PUBLIC_CLERKABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
ENGRAM_SERVICE_KEY=generate_a_long_random_value
```
API必须可以从浏览器访问,并且必须允许仪表板源通过 `CORS_ORIGINS` 访问。 在托管的API上设置相同的 `ENGRAM_SERVICE_KEY`,以便仪表板可以创建或恢复每个Clerk的Engram密钥。
对于现有的Supabase数据库,请在拉取更新后重新应用 `api/db/schema.sql` 以使 `user_api_keys` 表存在:
```bash
docker compose --compose.supabase.yml run --rm api python -.apply_schema
```
Supabase仅替换PostgreSQL服务。它不替换FastAPI服务,因为Engram仍然需要 `/users`、`/memories`、`/logs` 和 `/v1/chat`。在容器功能平台(如Azure容器应用、Render、Railway、Fly.io)上托管 `api/`。将其 `DATABASE_URL` 指向Supabase。在托管模式下,付费提供商调用需要保存在设置中的工作区密钥或 `X-Engram-Provider-Key`;服务器提供商密钥仅在自托管模式下使用。
## 开发检查
后端语法:
```bash
python -m compileall api
```
MCP构建:
```bash
cd mcp
npm ci
npm run build
```
仪表盘构建:
```bash
cd dashboard
npm ci
npm run verify:clerk
npm run verify:logic
npm run build
```
Docker冒烟测试:
```bash
docker compose up -d --build
docker compose ps
curl http://localhost:8000/health
```
使用本地模拟提供程序的完整确定性流程:
```bash
python scripts/verify_full_flow.py
```
使用本地Compose服务和配置的服务密钥进行工作区隔离:
```bash
ENGRAM_SERVICE_KEY=local_test_service_key python scripts/verify_workspace_isolation.py
```
此验证器创建和删除临时本地用户。 `ENGRAM` 指向托管环境。
## 本地测试脚本
嵌入检索:bash
python -.test_embedding
```
提取:
```bash -m api.test
```
代理
```bash
m api.test_proxy_flow
```
## 范Engram v1API JWT身份验证、速率限制、外部存储、Redis、Celery、LangChainlamaIndex。其重点是可检查的内存循环、注入、转发、提取、重复数据存储,并通过REST、MCP和仪表公开。仪表板Clerk单独