NoMemory 是一个“记忆基础设施”:只存原始事件(evidence),不持久化“现成的记忆结论”;在需要时通过“回忆(recall)”按场景合成可用的记忆视图(memory view)。
- Evidence-first:事件是唯一权威来源;一切“记忆结论”都可重建、可失效、可追溯。
- Synthesize on demand:记忆在读取时由回忆 Agent 合成,而不是写入时抽取固化。
- Pluggable by Skills:场景差异通过 Skills(策略/提示词/工具编排/校验器)完成“微调”。
-
事件层(Event Log)
- 只负责可靠地写入/存储/检索“发生过的原始事件”
- 中事件以对话消息为核心:一个
user_id对应一条按时间排序的消息序列
-
查询层(Query Layer / Recall API)
- 在事件之上提供多维检索能力(可组合)
- 典型维度:时间窗、关键词检索、语义检索、邻域上下文等
-
适配层(回忆 Agent + Skills)
- 回忆 Agent = Agent + 可加载的回忆 skill(标准 Agent Skill)
- 回忆 Agent 使用查询层工具进行多轮检索与重写查询
- 将召回的事件“合成”为一次性记忆视图(memory view),供调用方选择是否采纳
- 不固化“裁决结果”:回忆时可通过继续检索尽力裁决,但不把结论写回为长期事实(除非调用方另行存储)
- Message(消息):chat 场景的一条对话消息(用户/助手/system)。
- Query(查询):对消息集合的检索请求(时间/关键词/语义/过滤/分页;顺序通常由接口固定定义)。
- Recall(回忆):基于查询结果,由回忆 Agent 合成“记忆视图”的过程。
- Memory View(记忆视图):一次性生成的“当前可用记忆”(例如:用户偏好/背景),应携带可追溯引用(
message_id)。 - Skill(技能):一组可配置策略与工具编排,用于约束/提升回忆效果(召回范围、查询改写、输出格式、引用要求、覆盖范围声明等)。
- 在本文档体系里,Skill 以“标准 Agent Skill”的形式存在(Skill 目录 +
SKILL.md)。
- 在本文档体系里,Skill 以“标准 Agent Skill”的形式存在(Skill 目录 +
docs/README.md:文档目录与阅读顺序docs/query-api.md:查询接口(范围读取 / lexical_search / semantic_search / neighbors 等)docs/recall-service.md:检索服务(绑定 user_id 并向 Agent 暴露不含 user_id 的工具)docs/recall-agent-playbook.md:回忆 Agent 技术方案(如何检索与合成)docs/retrieval-skill-creator.md:creator skill 设计(生成回忆 skill)
Skills 的目标是“同一份事件数据,用不同策略生成不同的记忆视图”。常见能力:
- 召回范围:默认时间窗、是否只看
role=user - 检索编排:多轮查询、查询重写(更好的
query_text)、必要时补neighbors - 输出约束:固定结构、必须给出
message_id引用、声明覆盖范围(limits)
- 不把“总结后的记忆”作为系统内的事实来源长期保存
- 不在存储层固化“真值”(回忆时可通过继续检索尽力裁决,但不把裁决结果写回为长期事实)
- 不强制规定调用方如何缓存/是否回忆(NoMemory 提供原语与契约)
产物目录:experiments/locomo/20260211T034355Z/
| run_id | samples | qa_total | f1_mean | judge_mean | summary |
|---|---|---|---|---|---|
20260211T034355Z |
10 | 1540 | 0.5394 | 0.7922 | experiments/locomo/20260211T034355Z/summary.json |
judge_mean:LLM-as-judge(LLM 评分正确/错误的均值,范围 0~1)。
| Category | Count | F1 Mean | Judge Mean |
|---|---|---|---|
| Multi-hop | 282 | 0.3664 | 0.7340 |
| Temporal | 321 | 0.5045 | 0.7321 |
| Open-domain | 96 | 0.2464 | 0.5000 |
| Single-hop | 841 | 0.6443 | 0.8680 |
产物目录:experiments/locomo/20260213T015814Z/
| run_id | samples | qa_total | f1_mean | judge_mean | summary |
|---|---|---|---|---|---|
20260213T015814Z |
10 | 1540 | 0.5837 | 0.7201 | experiments/locomo/20260213T015814Z/summary.json |
| Category | Count | F1 Mean | Judge Mean |
|---|---|---|---|
| Multi-hop | 282 | 0.3945 | 0.4184 |
| Temporal | 321 | 0.5998 | 0.7383 |
| Open-domain | 96 | 0.2670 | 0.5000 |
| Single-hop | 841 | 0.6771 | 0.8395 |
- 一键启动(推荐)
chmod +x ./scripts/dev-up.sh
./scripts/dev-up.sh默认端口为 8001(可用环境变量覆盖:PORT=8000 ./scripts/dev-up.sh)。
- 手动启动(可选)
1.1) 启动数据库(Docker)
docker compose up -d db1.2) 配置环境变量
- 复制
.env.example为.env并填写BIGMODEL_API_KEY(若你要启用 embedding/LLM)
1.3) 安装依赖并迁移(示例以 uv 为例)
uv sync
uv run alembic upgrade head1.4) 启动服务
uv run uvicorn app.main:app --reload1.5) 写入消息(唯一写入接口)
POST /v1/users/{user_id}/messages:batch
调用示例:
curl -X POST "http://127.0.0.1:8001/v1/users/u_123/messages:batch" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"ts": "2026-02-02T08:00:00Z",
"role": "user",
"content": "我不吃辣",
"meta": { "conversation_id": "c_001" }
},
{
"ts": "2026-02-02T08:01:00Z",
"role": "assistant",
"content": "好的,我记住了",
"meta": { "conversation_id": "c_001" }
}
]
}'响应会返回服务端生成的 message_ids(与请求顺序一致)。
1.6) 回忆
POST /v1/recall,带X-User-Id: <user_id>
调用示例:
curl -X POST "http://127.0.0.1:8001/v1/recall" \
-H "Content-Type: application/json" \
-H "X-User-Id: u_123" \
-d '{ "question": "我有哪些饮食偏好?" }'1.7) 查询(Query API)
GET /v1/users/{user_id}/messages:范围读取(支持since/until/role/page_size/cursor)POST /v1/messages/lexical_search:关键词检索(FTS)POST /v1/messages/semantic_search:语义检索(pgvector,若用query_text需配置BIGMODEL_API_KEY以生成 query embedding)GET /v1/users/{user_id}/messages/{message_id}/neighbors:邻域上下文
调用示例:
# 1) 范围读取
curl "http://127.0.0.1:8001/v1/users/u_123/messages?page_size=20"
# 2) 关键词检索(FTS)
curl -X POST "http://127.0.0.1:8001/v1/messages/lexical_search" \
-H "Content-Type: application/json" \
-d '{
"user_id": "u_123",
"query_text": "\"不吃辣\"",
"filter": { "role": "user", "time_range": { "since": "2026-01-01T00:00:00Z" } },
"page_size": 20
}'
# 3) 语义检索(需要 BIGMODEL_API_KEY,服务端会用 query_text 生成 embedding)
curl -X POST "http://127.0.0.1:8001/v1/messages/semantic_search" \
-H "Content-Type: application/json" \
-d '{
"user_id": "u_123",
"query_text": "饮食偏好 忌口 不吃辣",
"filter": { "role": "user", "time_range": { "since": "2026-01-01T00:00:00Z" } },
"top_k": 10,
"min_score": 0.2
}'
# 4) 邻域上下文(message_id 可从写入接口返回的 message_ids 中取得)
curl "http://127.0.0.1:8001/v1/users/u_123/messages/<message_id>/neighbors?before=8&after=0"