Memory Hybrid Stack
Overview
This stack splits agent memory across three stores:
- 1. Postgres + pgvector (
facts) — structured, durable knowledge with optional embeddings. - Redis (
state) — low-latency values that expire (locks, session flags, device status). - Qdrant (
vectors) — semantic recall for long-form text chunks, keyed by collection oc_memory.
All services run via Docker Compose (infra/memory-stack/docker-compose.yml). Connection defaults live in infra/memory-stack/.env; scripts in this skill auto-source that file unless you override MEMORY_STACK_ENV / MEMORY_STACK_ROOT.
Quick Start
- 1. Ensure the stack is running:
cd infra/memory-stack && docker compose ps (all three should be healthy). - INLINECODE10 or call scripts via absolute path.
- Use the helper scripts listed below (they inject host/port/user from
.env). - For schema/endpoint details, open
references/connection-map.md when needed.
| Layer | Script | Purpose |
|---|
| Postgres facts | INLINECODE13 | Run SQL/psql with pgvector enabled |
| Redis state |
scripts/state_kv.sh | Get/Set/Delete simple keys with optional TTL |
| Qdrant vectors |
scripts/qdrant_request.sh | Make raw HTTP calls (
GET/POST/PUT/DELETE) with inline JSON or
@file payloads |
Facts Layer (Postgres + pgvector)
- - Use when: recording validated facts, relationships, high-confidence summaries, or when you need SQL joins/filtering.
- Connection:
postgres://oc_memory:…@localhost:55432/oc_facts. Credentials auto-loaded from .env.
Common operations
CODEBLOCK0
Tips:
- - Store raw text inside
object JSON, e.g. { "value": "...", "summary": "..." }. - Use
embedding column when you already have a 1536-d vector (set via UPDATE facts SET embedding = '[...]'::vector WHERE id = ...). - Always tag rows (
tags text[]) so downstream filters are cheap.
State Layer (Redis)
- - Use when: caching short-lived context (current task, device status, throttles, locks).
- Key pattern:
state:<entity>:<attribute>; keep payloads as JSON strings for readability.
Commands
CODEBLOCK1
Guidelines:
- - Keep TTLs short (seconds/minutes) unless the value is truly session-scoped.
- Use Redis for coordination (e.g.,
state:lock:calendar-sync) with low TTL to avoid deadlocks.
Vector Layer (Qdrant)
- - Use when: storing or retrieving semantic chunks that exceed Markdown recall.
- Endpoints: HTTP
http://localhost:6335, gRPC http://localhost:6336. - Default collection:
oc_memory (1536-d cosine). Created via scripts/init_qdrant.sh.
Helper usage
CODEBLOCK2
Notes:
- - The script accepts raw JSON strings or
@/path/file.json. - Generate embeddings via your preferred model (e.g., OpenAI
text-embedding-3-small); ensure dimension = 1536. - Keep payload timestamps (
timestamp) to enforce recency filtering.
Workflow Recommendations
- 1. Ephemeral -> Durable: log immediate events in Redis, then promote confirmed facts into Postgres/Qdrant.
- Fan-out writes: when capturing a new preference, update Postgres (structured) and Qdrant (semantic search) in the same turn.
- Read order: Redis (latest state) → Postgres (authoritative fact) → Qdrant (related context) → Markdown fallback.
- Tags & filters: align
tags (Postgres) with Qdrant payload keys so cross-store correlation is simple.
Troubleshooting
- -
docker compose ps shows unhealthy containers → check host ports (stack uses 55432/56379/6335/6336 to avoid clashes with ai-stack-*). - Scripts complain about missing
.env → copy .env.example → .env, or set env vars manually. - Qdrant health stuck on "starting" → ensure you rebuilt using
memory-qdrant:local (curl installed) or adjust healthcheck.
References
内存混合栈
概述
该栈将智能体内存分散存储在三个存储系统中:
- 1. Postgres + pgvector(facts) — 结构化、持久化的知识存储,支持可选的嵌入向量。
- Redis(state) — 低延迟、可过期值的存储(锁、会话标志、设备状态)。
- Qdrant(vectors) — 用于长文本块的语义召回,按集合 oc_memory 进行键控。
所有服务通过 Docker Compose(infra/memory-stack/docker-compose.yml)运行。连接默认值位于 infra/memory-stack/.env;除非你覆盖了 MEMORYSTACKENV / MEMORYSTACKROOT,否则该技能中的脚本会自动引用该文件。
快速开始
- 1. 确保栈正在运行:cd infra/memory-stack && docker compose ps(三个服务都应显示为 healthy)。
- cd skills/memory-hybrid-stack/scripts 或通过绝对路径调用脚本。
- 使用下面列出的辅助脚本(它们会自动从 .env 注入主机/端口/用户信息)。
- 如需了解模式/端点详情,请根据需要打开 references/connection-map.md。
| 层 | 脚本 | 用途 |
|---|
| Postgres facts | scripts/factssql.sh | 运行启用 pgvector 的 SQL/psql |
| Redis state |
scripts/statekv.sh | 获取/设置/删除简单键值,支持可选 TTL |
| Qdrant vectors | scripts/qdrant_request.sh | 发起原始 HTTP 调用(GET/POST/PUT/DELETE),支持内联 JSON 或 @file 负载 |
Facts 层(Postgres + pgvector)
- - 使用场景:记录已验证的事实、关系、高置信度摘要,或需要 SQL 连接/过滤时。
- 连接信息:postgres://ocmemory:…@localhost:55432/ocfacts。凭据从 .env 自动加载。
常用操作
bash
运行临时 SQL(字符串参数)
./scripts/facts_sql.sh SELECT subject, object->>value AS value FROM facts WHERE tags @> ARRAY[preference];
通过管道传入多行查询
cat <
buildobject(value, zh-CN),
chat/2026-03-18,
0.92,
ARRAY[preference,language]
)
ON CONFLICT (subject, predicate)
DO UPDATE SET object = EXCLUDED.object, updated_at = now();
SQL
提示:
- - 将原始文本存储在 object JSON 中,例如 { value: ..., summary: ... }。
- 当已有 1536 维向量时,使用 embedding 列(通过 UPDATE facts SET embedding = [...]::vector WHERE id = ... 设置)。
- 始终为行添加标签(tags text[]),以便下游过滤更高效。
State 层(Redis)
- - 使用场景:缓存短生命周期的上下文(当前任务、设备状态、限流、锁)。
- 键模式:state:<实体>:<属性>;为便于阅读,将负载保持为 JSON 字符串。
命令
bash
获取
./scripts/state_kv.sh get state:user:xiaobai:current-task
设置并指定 10 分钟 TTL
./scripts/statekv.sh set state:user:xiaobai:current-task {summary:researching, startedat:2026-03-18T19:00:00Z} 600
删除
./scripts/state_kv.sh del state:user:xiaobai:current-task
指南:
- - 保持 TTL 较短(秒/分钟),除非该值确实是会话级别的。
- 使用 Redis 进行协调(例如 state:lock:calendar-sync),并设置低 TTL 以避免死锁。
Vector 层(Qdrant)
- - 使用场景:存储或检索超出 Markdown 召回范围的语义块。
- 端点:HTTP http://localhost:6335,gRPC http://localhost:6336。
- 默认集合:ocmemory(1536 维余弦相似度)。通过 scripts/initqdrant.sh 创建。
辅助脚本使用
bash
检查集合
./scripts/qdrant_request.sh GET /collections
从文件上传点
cat > /tmp/points.json < 1536 个浮点数 /],
payload: {
subject: user:xiaobai,
text: 偏好深入、有来源的答案。,
tags: [preference],
timestamp: 2026-03-18T19:05:00Z
}
}
]
}
JSON
./scripts/qdrantrequest.sh PUT /collections/ocmemory/points @/tmp/points.json
语义搜索(内联向量或负载过滤)
./scripts/qdrantrequest.sh POST /collections/ocmemory/points/search {
vector: [/ 查询向量 /],
limit: 5,
with_payload: true,
filter: {must: [{key: subject, match: {value: user:xiaobai}}]}
}
注意:
- - 脚本接受原始 JSON 字符串或 @/path/file.json。
- 通过你偏好的模型(例如 OpenAI text-embedding-3-small)生成嵌入向量;确保维度为 1536。
- 保留负载中的时间戳(timestamp)以支持时效性过滤。
工作流建议
- 1. 临时 -> 持久化:将即时事件记录到 Redis,然后将确认的事实提升到 Postgres/Qdrant。
- 扇出写入:在捕获新偏好时,同时更新 Postgres(结构化)和 Qdrant(语义搜索)。
- 读取顺序:Redis(最新状态)→ Postgres(权威事实)→ Qdrant(相关上下文)→ Markdown 回退。
- 标签与过滤:将 Postgres 的 tags 与 Qdrant 的负载键对齐,以便跨存储关联更简单。
故障排除
- - docker compose ps 显示容器不健康 → 检查主机端口(栈使用 55432/56379/6335/6336 以避免与 ai-stack-* 冲突)。
- 脚本提示缺少 .env → 复制 .env.example 为 .env,或手动设置环境变量。
- Qdrant 健康检查卡在 starting → 确保使用 memory-qdrant:local(已安装 curl)重建,或调整健康检查配置。
参考