本地化"活动采集 → AI 总结 → 向量记忆 → 工具调用"系统。全部服务运行于 127.0.0.1,无外部网络依赖。
┌─────────────────────────────────────────────────────────────────┐
│ supervisor (守护) │
│ 崩溃自动重启 / 开机自启 / 统一日志 │
└──────────────┬──────────────┬──────────────┬────────────────────┘
│ │ │
┌────────▼───┐ ┌───────▼──────┐ ┌────▼──────────┐
│ activity- │ │ memory- │ │ llama-server │
│ logger │ │ engine │ │ (chat) │
│ 采集事件 │ │ 总结+向量化 │ │ OpenAI API │
│ REST :8082 │ │ REST :8083 │ │ :8080 │
└─────┬──────┘ └──────┬───────┘ └──┬───▲────────┘
│ │ │ │
│ events.jsonl │ │ │ MCP (stdio)
└───────────────►│ │ │
│ embedding │ │
│ :8081 │ │
└──────┬──────┘ │
│ │
┌─────▼─────┐ │
│ sqlite │ ┌──┴─────────┐
│ memory.db│ │ memory-mcp │
│ (vec0) │ │ MCP Server │
└───────────┘ └─────▲──────┘
│ HTTP :8083
└────────────┘
| 服务 | 端口 | 协议 | 说明 |
|---|---|---|---|
| persona-proxy | 8080 | HTTP | 透明代理,自动注入猫娘人设 system 消息,转发到 chat-server (8085) |
| llama-server (chat) | 8085 | HTTP + MCP 客户端 | Qwen2.5-7B,OpenAI 兼容接口,已挂载 3 个记忆工具 |
| llama-server (embed) | 8081 | HTTP | Qwen3-Embedding-0.6B,向量化 |
| activity-logger | 8082 | HTTP REST | 活动事件采集与查询 |
| memory-engine | 8083 | HTTP REST | 记忆总结、向量检索、画像、高频文件扫描 |
| memory-mcp | — (stdio) | MCP | 将 memory-engine API 包装为 MCP 工具 |
所有接口为 JSON,UTF-8 编码。鉴权:除 /health 外,所有 API 需要携带 API Key(Authorization: Bearer <key> 或 X-API-Key: <key> 头),Key 存储在 D:\projects\lemon\ai\api.key(32 位随机字符串)。无 Key 文件时为开发模式(不鉴权)。
人设注入(彩蛋功能):对 8080 的所有 /v1/chat/completions 请求自动注入猫娘人设(绒绒)作为 system 消息;已有 system 消息则被替换。memory-engine 直连 8085,系统自动总结不受人设影响。人设文案定义在 persona-proxy\src\main.rs 的 PERSONA_SYSTEM。
⚠️ 彩蛋性质:猫娘人设属于娱乐性彩蛋,仅供个人娱乐使用,正式场合不建议使用。关闭:直连 8085 或从 supervisor 移除 persona-proxy。
GET /health
{"status": "ok", "service": "activity-logger"}GET /api/v1/events?since={ISO8601}&limit={n}
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| since | string (ISO8601) | 否 | 无 | 只返回该时间之后的事件 |
| limit | int | 否 | 100 | 返回条数,最大 1000 |
响应:
{
"events": [
{
"type": "process_event",
"time": "2026-08-07T20:57:14.512+08:00",
"name": "cargo.exe",
"started": false
}
],
"count": 1
}事件 type 三种:
window_session:前台窗口会话{"type": "window_session", "start": "...", "end": "...", "exe": "code.exe", "title": "main.rs", "keys": 120, "clicks": 45}process_event:进程启动/退出{"type": "process_event", "time": "...", "name": "chrome.exe", "started": true}file_op:文件操作(创建/修改/删除){"type": "file_op", "time": "...", "kind": "Modified", "path": "D:\\doc\\a.txt"}
| 状态码 | 含义 |
|---|---|
| 200 | 成功 |
| 404 | 路径不存在 |
GET /health
{"status": "ok", "service": "memory-engine"}GET /api/v1/memories?layer={L1|L2|L3}&limit={n}
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| layer | string | 否 | L1 | L1 活动总结 / L2 每日总结 / L3 用户画像 / L4-Weekly 周报 / L4-Monthly 月报 |
| limit | int | 否 | 10 | 返回条数,最大 100 |
响应:
{
"memories": [
{"id": 42, "time": "2026-08-07T20:30:53+08:00", "layer": "L1", "content": "[2026-08-07 20:29 - 20:30] 用户活动\n- 用户启动了多个 powershell 进程..."}
],
"count": 1
}POST /api/v1/search
Content-Type: application/json
请求体:
{"query": "用户最近在做什么项目", "limit": 5}| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| query | string | 是 | — | 自然语言查询,自动向量化后召回 |
| limit | int | 否 | 5 | 返回条数,最大 20 |
响应:
{
"memories": [
{"id": 42, "time": "2026-08-07T20:30:53+08:00", "content": "...", "distance": 0.955}
],
"count": 1
}distance 越小相关性越高。
GET /api/v1/profile
{"profile": "[用户画像]\n{\"interests\": [\"Rust\"], \"projects\": [], \"tools\": [\"cargo\"], \"habits\": []}"}无画像时返回 {"profile": ""}。
模型服务通过 memory-engine\config.json 配置,支持任何 OpenAI 兼容 的本地模型服务(llama.cpp、Ollama、LM Studio、vLLM 等)。修改配置后需重启 memory-engine 生效。
{
"chat": {
"base_url": "http://127.0.0.1:8085/v1",
"model": "",
"api_key": ""
},
"embedding": {
"base_url": "http://127.0.0.1:8081/v1",
"model": "",
"api_key": ""
}
}| 字段 | 说明 |
|---|---|
chat.base_url |
对话/总结服务的 OpenAI 兼容地址,如 Ollama: http://127.0.0.1:11434/v1 |
chat.model |
模型名(Ollama/LM Studio 必填,如 qwen2.5:7b;llama.cpp 可留空) |
chat.api_key |
需要鉴权的服务填写(如 vLLM 配置了 key) |
embedding.base_url |
向量化服务的 OpenAI 兼容地址 |
embedding.model |
embedding 模型名,同上 |
embedding.api_key |
同上 |
设备空闲时(CPU < 30%、可用内存 > 4GB、LLM 无任务),自动读取用户高频修改的文件 和项目文档,生成"文件洞察/文档洞察"并入 L1 记忆,同时更新用户画像 L3。每天最多自动触发一次。
- 触发:daemon 启动后每分钟检查一次资源状态,资源充足且当天未扫描时自动执行
- 手动触发:
memory-engine.exe scan - 两类数据来源:
- 高频文件:events.jsonl 中的 file_op 事件聚合(按修改次数排序,Top 15)
- 项目文档:先匹配白名单(plan.md/roadmap.md/todo.md/readme.md/design.md/architecture.md/spec.md 等),配额不足才递归补足其它文档
- 哈希去重:文档内容未变化不重复读取(
docs_seen.json) - 过滤规则:
- 跳过敏感路径(
.ssh、.git、secrets、credentials、wallet、AppData等) - 跳过敏感文件名(
.env、password、token、api_key等) - 跳过构建目录(target、node_modules、dist 等)
- 仅文本类扩展名(md/txt/json/rs/py/ts 等)
- 单文件大小上限 100KB
- 跳过敏感路径(
- 入库格式:
[文件洞察] 路径 (N 次修改) <模型洞察>/[文档洞察] 路径 <模型洞察> - 游标:
memory-engine\filescan.meta记录上次扫描时间
| 状态码 | 含义 |
|---|---|
| 200 | 成功 |
| 400 | 参数错误(如 query 为空) |
| 404 | 路径不存在 |
| 500 | 数据库错误 |
| 502 | embedding 服务不可用 |
标准 OpenAI Chat Completions 接口,模型已挂载 MCP 记忆工具。对外访问走 8080 代理(自动注入人设);直接调用 8085 则无系统人设。
POST /v1/chat/completions
{
"messages": [{"role": "user", "content": "我最近在做什么?"}],
"tools": [
{"type": "function", "function": {"name": "memory_search_memory", "description": "...", "parameters": {...}}}
]
}工具定义可实时获取:
GET /tools
返回 3 个已注册工具(前缀 memory_):
| 工具名 | 说明 |
|---|---|
memory_search_memory |
语义检索历史活动记忆 |
memory_get_profile |
获取用户长期画像 |
memory_recent_memories |
获取最近记忆(按层) |
POST /v1/embeddings
{"input": "用户在写 Rust 项目"}响应 data[0].embedding 为 1024 维向量。
由 llama-server 通过 --mcp-servers-config 启动,配置见 memory-engine\mcp-servers.json。通过标准 MCP 协议(JSON-RPC 2.0 over stdio)暴露工具:
| 工具 | 底层调用 |
|---|---|
search_memory(query, limit) |
POST :8083/api/v1/search |
get_profile() |
GET :8083/api/v1/profile |
recent_memories(layer, limit) |
GET :8083/api/v1/memories |
supervisor.exe # 守护运行(托管 4 个服务)
supervisor.exe status # 查看服务与端口状态
supervisor.exe stop # 停止全部服务
supervisor.exe install # 注册开机自启(启动文件夹)
supervisor.exe uninstall # 移除自启
日志:supervisor\target\release\logs\(supervisor.log 统一事件流,各服务独立日志)。
| 路径 | 说明 |
|---|---|
activity_logs\events-YYYY-MM-DD.jsonl |
事件流(按天分文件,保留 30 天自动清理) |
activity_logs\activity-YYYY-MM-DD.txt |
当日人类可读报告(每 5 分钟刷新) |
memory-engine\memory.db |
SQLite + sqlite-vec 向量库(L1/L2/L3/L4 全层记忆) |
memory-engine\events.offset |
事件流消费游标(昨天文件续读位置) |
memory-engine\filescan.meta |
高频文件扫描游标 |
memory-engine\docs_seen.json |
文档哈希去重表(path→hash) |
# 状态
supervisor.exe status
# 读取 API Key(以下请求都需携带)
$key = (Get-Content "D:\projects\lemon\ai\api.key" -Raw).Trim()
$auth = @{"X-API-Key" = $key}
# 查最近 5 条事件
Invoke-RestMethod "http://127.0.0.1:8082/api/v1/events?limit=5" -Headers $auth
# 语义检索记忆
Invoke-RestMethod -Uri "http://127.0.0.1:8083/api/v1/search" -Method Post -Headers $auth -ContentType "application/json" -Body '{"query":"我最近在做什么"}'
# 手动触发高频文件扫描
memory-engine.exe scan
# 让 AI 使用记忆回答(Web UI,浏览器自动使用本地服务)
# 浏览器打开 http://127.0.0.1:8080