@pentatonic-ai/ai-agent-sdk 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -69
- package/bin/__tests__/callback-server.test.js +4 -1
- package/bin/cli.js +41 -164
- package/bin/commands/config.js +251 -0
- package/package.json +2 -1
- package/packages/doctor/__tests__/detect.test.js +2 -6
- package/packages/doctor/src/checks/local-memory.js +164 -196
- package/packages/doctor/src/detect.js +11 -3
- package/packages/memory/src/corpus/adapters.js +104 -0
- package/packages/memory/src/corpus/cli.js +72 -7
- package/packages/memory/src/corpus/index.js +1 -1
- package/packages/memory-engine/.env.example +13 -0
- package/packages/memory-engine/README.md +131 -0
- package/packages/memory-engine/bench/README.md +99 -0
- package/packages/memory-engine/bench/scorecards-engine/agent-coding__pentatonic-baseline__20260427-142523.json +1115 -0
- package/packages/memory-engine/bench/scorecards-engine/chat-recall__pentatonic-baseline__20260427-142648.json +819 -0
- package/packages/memory-engine/bench/scorecards-engine/circular-economy__pentatonic-baseline__20260427-142757.json +1278 -0
- package/packages/memory-engine/bench/scorecards-engine/customer-support__pentatonic-baseline__20260427-142900.json +1018 -0
- package/packages/memory-engine/bench/scorecards-engine/marketplace-ops__pentatonic-baseline__20260427-142957.json +1038 -0
- package/packages/memory-engine/bench/scorecards-engine/product-catalogue__pentatonic-baseline__20260427-143122.json +961 -0
- package/packages/memory-engine/bench/scorecards-engine-via-docker/agent-coding__pentatonic-memory__20260427-161812.json +1115 -0
- package/packages/memory-engine/bench/scorecards-engine-via-docker/chat-recall__pentatonic-memory__20260427-161701.json +819 -0
- package/packages/memory-engine/bench/scorecards-engine-via-docker/circular-economy__pentatonic-memory__20260427-161713.json +1278 -0
- package/packages/memory-engine/bench/scorecards-engine-via-docker/customer-support__pentatonic-memory__20260427-161723.json +1018 -0
- package/packages/memory-engine/bench/scorecards-engine-via-docker/marketplace-ops__pentatonic-memory__20260427-161732.json +1038 -0
- package/packages/memory-engine/bench/scorecards-engine-via-docker/product-catalogue__pentatonic-memory__20260427-161741.json +937 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/agent-coding__pentatonic-memory__20260427-184718.json +1115 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/chat-recall__pentatonic-memory__20260427-184614.json +819 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/circular-economy__pentatonic-memory__20260427-184809.json +1278 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/customer-support__pentatonic-memory__20260427-184854.json +1018 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/marketplace-ops__pentatonic-memory__20260427-184929.json +1038 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/product-catalogue__pentatonic-memory__20260427-185015.json +961 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/agent-coding__pentatonic-memory__20260427-175252.json +1115 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/chat-recall__pentatonic-memory__20260427-175312.json +819 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/circular-economy__pentatonic-memory__20260427-175335.json +1278 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/customer-support__pentatonic-memory__20260427-175355.json +1018 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/marketplace-ops__pentatonic-memory__20260427-175413.json +1038 -0
- package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/product-catalogue__pentatonic-memory__20260427-175430.json +883 -0
- package/packages/memory-engine/bench/scorecards-engine-via-shim/agent-coding__pentatonic-memory__20260427-155409.json +1115 -0
- package/packages/memory-engine/bench/scorecards-engine-via-shim/chat-recall__pentatonic-memory__20260427-155421.json +819 -0
- package/packages/memory-engine/bench/scorecards-engine-via-shim/circular-economy__pentatonic-memory__20260427-155433.json +1278 -0
- package/packages/memory-engine/bench/scorecards-engine-via-shim/customer-support__pentatonic-memory__20260427-155443.json +1018 -0
- package/packages/memory-engine/bench/scorecards-engine-via-shim/marketplace-ops__pentatonic-memory__20260427-155453.json +1038 -0
- package/packages/memory-engine/bench/scorecards-engine-via-shim/product-catalogue__pentatonic-memory__20260427-155503.json +937 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/agent-coding__pentatonic-memory-latest__20260427-145103.json +1115 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/agent-coding__pentatonic-memory__20260427-144909.json +1115 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/chat-recall__pentatonic-memory-latest__20260427-145153.json +819 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/chat-recall__pentatonic-memory__20260427-145120.json +542 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/circular-economy__pentatonic-memory-latest__20260427-145313.json +1278 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/circular-economy__pentatonic-memory__20260427-145207.json +894 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/customer-support__pentatonic-memory-latest__20260427-145412.json +1018 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/customer-support__pentatonic-memory__20260427-145327.json +680 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/marketplace-ops__pentatonic-memory-latest__20260427-145517.json +1038 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/marketplace-ops__pentatonic-memory__20260427-145422.json +693 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/product-catalogue__pentatonic-memory-latest__20260427-145616.json +961 -0
- package/packages/memory-engine/bench/scorecards-pentatonic-baseline/product-catalogue__pentatonic-memory__20260427-145528.json +727 -0
- package/packages/memory-engine/compat/Dockerfile +11 -0
- package/packages/memory-engine/compat/server.py +680 -0
- package/packages/memory-engine/docker-compose.yml +243 -0
- package/packages/memory-engine/docs/MIGRATION.md +178 -0
- package/packages/memory-engine/docs/RUNBOOK-AWS.md +375 -0
- package/packages/memory-engine/docs/why-v05-underperforms.md +138 -0
- package/packages/memory-engine/engine/README.md +52 -0
- package/packages/memory-engine/engine/l2-hybridrag-proxy.py +1543 -0
- package/packages/memory-engine/engine/l5-comms-layer.py +663 -0
- package/packages/memory-engine/engine/l6-document-store.py +1018 -0
- package/packages/memory-engine/engine/services/l2/Dockerfile +41 -0
- package/packages/memory-engine/engine/services/l2/init_databases.py +81 -0
- package/packages/memory-engine/engine/services/l2/l2-hybridrag-proxy.py +1543 -0
- package/packages/memory-engine/engine/services/l4/Dockerfile +15 -0
- package/packages/memory-engine/engine/services/l4/server.py +235 -0
- package/packages/memory-engine/engine/services/l5/Dockerfile +9 -0
- package/packages/memory-engine/engine/services/l5/l5-comms-layer.py +678 -0
- package/packages/memory-engine/engine/services/l6/Dockerfile +11 -0
- package/packages/memory-engine/engine/services/l6/l6-document-store.py +1016 -0
- package/packages/memory-engine/engine/services/nv-embed/Dockerfile +28 -0
- package/packages/memory-engine/engine/services/nv-embed/server.py +152 -0
- package/packages/memory-engine/pme_memory/__init__.py +0 -0
- package/packages/memory-engine/pme_memory/__main__.py +129 -0
- package/packages/memory-engine/pme_memory/artifacts.py +95 -0
- package/packages/memory-engine/pme_memory/embed.py +74 -0
- package/packages/memory-engine/pme_memory/health.py +36 -0
- package/packages/memory-engine/pme_memory/hygiene.py +159 -0
- package/packages/memory-engine/pme_memory/indexer.py +200 -0
- package/packages/memory-engine/pme_memory/needs.py +55 -0
- package/packages/memory-engine/pme_memory/provenance.py +80 -0
- package/packages/memory-engine/pme_memory/scoring.py +168 -0
- package/packages/memory-engine/pme_memory/search.py +52 -0
- package/packages/memory-engine/pme_memory/store.py +86 -0
- package/packages/memory-engine/pme_memory/synthesis.py +114 -0
- package/packages/memory-engine/pyproject.toml +65 -0
- package/packages/memory-engine/scripts/kg-extractor.py +557 -0
- package/packages/memory-engine/scripts/kg-preflexor-v2.py +738 -0
- package/packages/memory-engine/tests/test_api_contract.sh +57 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
name: pentatonic-memory-engine
|
|
2
|
+
|
|
3
|
+
# pentatonic-memory-engine v0.1
|
|
4
|
+
#
|
|
5
|
+
# Drop-in HTTP-compatible replacement for `pentatonic-memory` v0.5,
|
|
6
|
+
# backed by the 7-layer hybrid retrieval engine.
|
|
7
|
+
#
|
|
8
|
+
# Bring up: docker compose up -d
|
|
9
|
+
# API surface: http://localhost:8099 (matches pentatonic-memory v0.5)
|
|
10
|
+
# Health: curl http://localhost:8099/health
|
|
11
|
+
#
|
|
12
|
+
# Layers:
|
|
13
|
+
# l0 (in-process) — BM25 over SQLite FTS5 (inside L2 + L6)
|
|
14
|
+
# l1 (in-process) — Always-loaded core files (inside L2)
|
|
15
|
+
# l2 :8031 — HybridRAG proxy (RRF fusion)
|
|
16
|
+
# l3 :7474 — Knowledge Graph (Neo4j Community)
|
|
17
|
+
# l4 :8042 — sqlite-vec vector index
|
|
18
|
+
# l5 :8034 — Milvus comms layer
|
|
19
|
+
# l6 :8037 — Document store + cross-encoder reranker
|
|
20
|
+
# compat :8099 — pentatonic-memory v0.5 API translation shim
|
|
21
|
+
#
|
|
22
|
+
# nv-embed :8041 — NV-Embed-v2 4096d embedding service
|
|
23
|
+
#
|
|
24
|
+
# The nv-embed service requires a GPU. If running without GPU,
|
|
25
|
+
# override NV_EMBED_URL to point at an external embedding endpoint:
|
|
26
|
+
# - OpenAI's /v1/embeddings (text-embedding-3-large)
|
|
27
|
+
# - the Pentatonic AI Gateway
|
|
28
|
+
# - any OpenAI-compat embedding endpoint
|
|
29
|
+
|
|
30
|
+
x-engine-base: &engine-base
|
|
31
|
+
restart: unless-stopped
|
|
32
|
+
networks:
|
|
33
|
+
- engine-net
|
|
34
|
+
|
|
35
|
+
services:
|
|
36
|
+
# --------------------------------------------------------------------
|
|
37
|
+
# NV-Embed-v2 — 4096-dim embedding service (GPU required)
|
|
38
|
+
# --------------------------------------------------------------------
|
|
39
|
+
nv-embed:
|
|
40
|
+
<<: *engine-base
|
|
41
|
+
build:
|
|
42
|
+
context: ./engine/services/nv-embed
|
|
43
|
+
dockerfile: Dockerfile
|
|
44
|
+
container_name: pme-nv-embed
|
|
45
|
+
ports: ["127.0.0.1:${PME_NV_EMBED_PORT:-8041}:8041"]
|
|
46
|
+
volumes:
|
|
47
|
+
- pme-nv-embed-cache:/cache
|
|
48
|
+
deploy:
|
|
49
|
+
resources:
|
|
50
|
+
reservations:
|
|
51
|
+
devices:
|
|
52
|
+
- driver: nvidia
|
|
53
|
+
count: 1
|
|
54
|
+
capabilities: [gpu]
|
|
55
|
+
healthcheck:
|
|
56
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8041/health',timeout=3)"]
|
|
57
|
+
interval: 15s
|
|
58
|
+
timeout: 10s
|
|
59
|
+
retries: 20
|
|
60
|
+
start_period: 120s
|
|
61
|
+
|
|
62
|
+
# --------------------------------------------------------------------
|
|
63
|
+
# L3 — Knowledge Graph (Neo4j Community)
|
|
64
|
+
# --------------------------------------------------------------------
|
|
65
|
+
l3:
|
|
66
|
+
<<: *engine-base
|
|
67
|
+
image: neo4j:5-community
|
|
68
|
+
container_name: pme-l3
|
|
69
|
+
ports:
|
|
70
|
+
- "127.0.0.1:${PME_L3_HTTP_PORT:-7475}:7474" # HTTP browser
|
|
71
|
+
- "127.0.0.1:${PME_L3_BOLT_PORT:-7688}:7687" # bolt protocol
|
|
72
|
+
environment:
|
|
73
|
+
NEO4J_AUTH: ${NEO4J_AUTH:-neo4j/local-dev-pw}
|
|
74
|
+
NEO4J_PLUGINS: '["apoc"]'
|
|
75
|
+
NEO4J_dbms_memory_heap_max__size: 512m
|
|
76
|
+
volumes:
|
|
77
|
+
- pme-l3-data:/data
|
|
78
|
+
healthcheck:
|
|
79
|
+
test: ["CMD-SHELL", "wget -qO- http://localhost:7474 >/dev/null 2>&1 || exit 1"]
|
|
80
|
+
interval: 10s
|
|
81
|
+
timeout: 5s
|
|
82
|
+
retries: 30
|
|
83
|
+
start_period: 30s
|
|
84
|
+
|
|
85
|
+
# --------------------------------------------------------------------
|
|
86
|
+
# L4 — sqlite-vec sidecar
|
|
87
|
+
# --------------------------------------------------------------------
|
|
88
|
+
l4:
|
|
89
|
+
<<: *engine-base
|
|
90
|
+
build:
|
|
91
|
+
context: ./engine/services/l4
|
|
92
|
+
dockerfile: Dockerfile
|
|
93
|
+
container_name: pme-l4
|
|
94
|
+
# Default 18042 to avoid port collisions on 8042.
|
|
95
|
+
# Override via PME_L4_PORT for bench setups that intentionally replace it.
|
|
96
|
+
ports: ["127.0.0.1:${PME_L4_PORT:-18042}:8042"]
|
|
97
|
+
environment:
|
|
98
|
+
L4_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
|
|
99
|
+
L4_EMBED_MODEL: ${EMBED_MODEL_NAME:-nv-embed-v2}
|
|
100
|
+
L4_EMBED_API_KEY: ${EMBED_API_KEY:-}
|
|
101
|
+
L4_EMBED_DIM: ${EMBED_DIM:-4096}
|
|
102
|
+
L4_DB_PATH: /data/vec.db
|
|
103
|
+
extra_hosts:
|
|
104
|
+
- "host.docker.internal:host-gateway"
|
|
105
|
+
volumes:
|
|
106
|
+
- pme-l4-data:/data
|
|
107
|
+
healthcheck:
|
|
108
|
+
test: ["CMD", "python", "-c", "import urllib.request,sys; urllib.request.urlopen('http://localhost:8042/health',timeout=3)"]
|
|
109
|
+
interval: 10s
|
|
110
|
+
timeout: 5s
|
|
111
|
+
retries: 30
|
|
112
|
+
|
|
113
|
+
# --------------------------------------------------------------------
|
|
114
|
+
# L5 — Qdrant comms layer
|
|
115
|
+
# --------------------------------------------------------------------
|
|
116
|
+
l5:
|
|
117
|
+
<<: *engine-base
|
|
118
|
+
build:
|
|
119
|
+
context: ./engine/services/l5
|
|
120
|
+
dockerfile: Dockerfile
|
|
121
|
+
container_name: pme-l5
|
|
122
|
+
# Default 18034 to avoid port collisions on 8034.
|
|
123
|
+
# Override via PME_L5_PORT for bench setups that intentionally replace it.
|
|
124
|
+
ports: ["127.0.0.1:${PME_L5_PORT:-18034}:8034"]
|
|
125
|
+
environment:
|
|
126
|
+
L5_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
|
|
127
|
+
L5_EMBED_MODEL: ${EMBED_MODEL_NAME:-nv-embed-v2}
|
|
128
|
+
L5_EMBED_API_KEY: ${EMBED_API_KEY:-}
|
|
129
|
+
L5_EMBED_DIM: ${EMBED_DIM:-4096}
|
|
130
|
+
L5_OLLAMA_DIM: ${OLLAMA_DIM:-768}
|
|
131
|
+
L5_OLLAMA_EMBED_URL: ${L5_OLLAMA_EMBED_URL:-http://host.docker.internal:11434/api/embed}
|
|
132
|
+
L5_OLLAMA_EMBED_MODEL: ${L5_OLLAMA_EMBED_MODEL:-nomic-embed-text}
|
|
133
|
+
L5_DB_PATH: /data/comms.db
|
|
134
|
+
PME_WORKSPACE: /data/workspace
|
|
135
|
+
extra_hosts:
|
|
136
|
+
- "host.docker.internal:host-gateway"
|
|
137
|
+
volumes:
|
|
138
|
+
- pme-l5-data:/data
|
|
139
|
+
|
|
140
|
+
# --------------------------------------------------------------------
|
|
141
|
+
# L6 — Document store + cross-encoder reranker
|
|
142
|
+
# --------------------------------------------------------------------
|
|
143
|
+
l6:
|
|
144
|
+
<<: *engine-base
|
|
145
|
+
build:
|
|
146
|
+
context: ./engine/services/l6
|
|
147
|
+
dockerfile: Dockerfile
|
|
148
|
+
container_name: pme-l6
|
|
149
|
+
# Default 18037 to avoid colliding with Spark Core L6 doc-store on 8037.
|
|
150
|
+
# Override via PME_L6_PORT for bench setups that intentionally replace it.
|
|
151
|
+
ports: ["127.0.0.1:${PME_L6_PORT:-18037}:8037"]
|
|
152
|
+
environment:
|
|
153
|
+
L6_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
|
|
154
|
+
L6_EMBED_MODEL: ${EMBED_MODEL_NAME:-nv-embed-v2}
|
|
155
|
+
L6_EMBED_API_KEY: ${EMBED_API_KEY:-}
|
|
156
|
+
L6_EMBED_DIM: ${EMBED_DIM:-4096}
|
|
157
|
+
L6_DATA_DIR: /data
|
|
158
|
+
extra_hosts:
|
|
159
|
+
- "host.docker.internal:host-gateway"
|
|
160
|
+
volumes:
|
|
161
|
+
- pme-l6-data:/data
|
|
162
|
+
|
|
163
|
+
# --------------------------------------------------------------------
|
|
164
|
+
# L2 — HybridRAG orchestrator (RRF fusion across all layers)
|
|
165
|
+
# --------------------------------------------------------------------
|
|
166
|
+
l2:
|
|
167
|
+
<<: *engine-base
|
|
168
|
+
build:
|
|
169
|
+
context: ./engine/services/l2
|
|
170
|
+
dockerfile: Dockerfile
|
|
171
|
+
container_name: pme-l2
|
|
172
|
+
ports: ["127.0.0.1:${PME_L2_PORT:-8131}:8031"]
|
|
173
|
+
environment:
|
|
174
|
+
PME_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
|
|
175
|
+
PME_NEO4J_URI: bolt://l3:7687
|
|
176
|
+
PME_NEO4J_PASSWORD: ${NEO4J_PASSWORD:-local-dev-pw}
|
|
177
|
+
NEO4J_PASSWORD: ${NEO4J_PASSWORD:-local-dev-pw}
|
|
178
|
+
PME_L5_URL: http://l5:8034
|
|
179
|
+
PME_L6_URL: http://l6:8037
|
|
180
|
+
# HyDE off (deliberate — hurts precision on retrieval-graded benches)
|
|
181
|
+
PME_HYDE_ENABLED: "false"
|
|
182
|
+
# Cross-encoder reranker on (boosts top-K precision)
|
|
183
|
+
PME_RERANK_ENABLED: "true"
|
|
184
|
+
PME_WORKSPACE: /data/workspace
|
|
185
|
+
PME_QMD_DB: /data/qmd.sqlite
|
|
186
|
+
PME_MEMORY_DB: /data/workspace.db
|
|
187
|
+
extra_hosts:
|
|
188
|
+
- "host.docker.internal:host-gateway"
|
|
189
|
+
volumes:
|
|
190
|
+
- pme-l2-data:/data
|
|
191
|
+
depends_on:
|
|
192
|
+
l3: { condition: service_healthy }
|
|
193
|
+
l5: { condition: service_started }
|
|
194
|
+
l6: { condition: service_started }
|
|
195
|
+
|
|
196
|
+
# --------------------------------------------------------------------
|
|
197
|
+
# Compat shim — exposes pentatonic-memory v0.5 API on :8099
|
|
198
|
+
#
|
|
199
|
+
# Now routes /search through the L2 7-layer proxy by default. L6-only
|
|
200
|
+
# bypass (BYPASS_L2_PROXY=1) is still available for isolated testing.
|
|
201
|
+
# --------------------------------------------------------------------
|
|
202
|
+
compat:
|
|
203
|
+
<<: *engine-base
|
|
204
|
+
build:
|
|
205
|
+
context: ./compat
|
|
206
|
+
dockerfile: Dockerfile
|
|
207
|
+
container_name: pme-compat
|
|
208
|
+
ports:
|
|
209
|
+
- "127.0.0.1:${PME_PORT:-8099}:8099"
|
|
210
|
+
environment:
|
|
211
|
+
L0_URL: http://l2:8031
|
|
212
|
+
L2_PROXY_URL: http://l2:8031
|
|
213
|
+
L3_KG_URL: http://l3:7474
|
|
214
|
+
L4_VEC_URL: http://l4:8042
|
|
215
|
+
L5_MILVUS_URL: http://l5:8034
|
|
216
|
+
L6_DOC_URL: http://l6:8037
|
|
217
|
+
NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
|
|
218
|
+
CLIENT_ID: ${CLIENT_ID:-default}
|
|
219
|
+
BYPASS_L2_PROXY: ${BYPASS_L2_PROXY:-0}
|
|
220
|
+
extra_hosts:
|
|
221
|
+
- "host.docker.internal:host-gateway"
|
|
222
|
+
depends_on:
|
|
223
|
+
l2: { condition: service_started }
|
|
224
|
+
l4: { condition: service_started }
|
|
225
|
+
l5: { condition: service_started }
|
|
226
|
+
l6: { condition: service_started }
|
|
227
|
+
healthcheck:
|
|
228
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8099/health',timeout=3)"]
|
|
229
|
+
interval: 10s
|
|
230
|
+
timeout: 5s
|
|
231
|
+
retries: 30
|
|
232
|
+
start_period: 60s
|
|
233
|
+
|
|
234
|
+
networks:
|
|
235
|
+
engine-net:
|
|
236
|
+
|
|
237
|
+
volumes:
|
|
238
|
+
pme-nv-embed-cache:
|
|
239
|
+
pme-l2-data:
|
|
240
|
+
pme-l3-data:
|
|
241
|
+
pme-l4-data:
|
|
242
|
+
pme-l5-data:
|
|
243
|
+
pme-l6-data:
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Migration Guide
|
|
2
|
+
|
|
3
|
+
## From `pentatonic-memory` v0.5.x → `pentatonic-memory-engine`
|
|
4
|
+
|
|
5
|
+
### TL;DR
|
|
6
|
+
|
|
7
|
+
```diff
|
|
8
|
+
- export PENTATONIC_MEMORY_URL=http://your-pm-host:8099
|
|
9
|
+
+ export PENTATONIC_MEMORY_URL=http://your-engine-host:8099
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
That's it. Same SDK, same code, same `/store` `/search` `/health` calls. Engine returns the same response shape with one optional addition (`engine_layer` field on results, naming which layer carried the hit — purely informational).
|
|
13
|
+
|
|
14
|
+
### Detailed wire-format compatibility
|
|
15
|
+
|
|
16
|
+
#### `POST /store`
|
|
17
|
+
|
|
18
|
+
Request:
|
|
19
|
+
```json
|
|
20
|
+
{ "content": "...", "metadata": { "key": "value" } }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Response (v0.5.x):
|
|
24
|
+
```json
|
|
25
|
+
{ "id": "mem_abc...", "content": "...", "layerId": "ml_default_episodic" }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Response (engine):
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"id": "abc...",
|
|
32
|
+
"content": "...",
|
|
33
|
+
"layerId": "ml_default_episodic",
|
|
34
|
+
"engine": { "l5": 1, "l6": 1 } // ← new, optional
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `engine` field is informational only. Existing SDK clients that ignore unknown fields (the default for both Node.js and Python clients) work without modification.
|
|
39
|
+
|
|
40
|
+
#### `POST /search`
|
|
41
|
+
|
|
42
|
+
Request:
|
|
43
|
+
```json
|
|
44
|
+
{ "query": "...", "limit": 10, "min_score": 0.0001 }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Response (v0.5.x):
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"results": [
|
|
51
|
+
{
|
|
52
|
+
"id": "mem_abc...", "content": "...", "metadata": {},
|
|
53
|
+
"similarity": 0.81, "layer_id": "ml_default_episodic", "client_id": "default"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Response (engine):
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"results": [
|
|
63
|
+
{
|
|
64
|
+
"id": "abc...", "content": "...", "metadata": {},
|
|
65
|
+
"similarity": 0.81, "layer_id": "ml_default_episodic", "client_id": "default",
|
|
66
|
+
"source": "doc1.md", // ← passes through engine's source_file
|
|
67
|
+
"engine_layer": "L4 vec" // ← new, optional, names the winning layer
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### `GET /health`
|
|
74
|
+
|
|
75
|
+
Request: no body.
|
|
76
|
+
|
|
77
|
+
Response (v0.5.x):
|
|
78
|
+
```json
|
|
79
|
+
{ "status": "ok", "client": "default", "version": "0.5.6", "memories": 249 }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Response (engine):
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"status": "ok",
|
|
86
|
+
"client": "default",
|
|
87
|
+
"version": "0.1.0",
|
|
88
|
+
"engine": "pentatonic-memory-engine",
|
|
89
|
+
"layers": {
|
|
90
|
+
"l0": "ok", "l1": "ok", "l2": "ok", "l3": "ok",
|
|
91
|
+
"l4": "ok", "l5": "ok", "l6": "ok",
|
|
92
|
+
"nv_embed": "ok"
|
|
93
|
+
},
|
|
94
|
+
"memories": 249
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Reports per-layer status across all 7 layers of the `sequential-hybridrag-7-layer` engine.
|
|
99
|
+
|
|
100
|
+
#### `POST /store-batch` (NEW — not in v0.5.x)
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
// Request
|
|
104
|
+
{
|
|
105
|
+
"records": [
|
|
106
|
+
{ "id": "doc1", "content": "...", "metadata": {} },
|
|
107
|
+
{ "id": "doc2", "content": "...", "metadata": {} }
|
|
108
|
+
],
|
|
109
|
+
"arena": "general"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Response
|
|
113
|
+
{
|
|
114
|
+
"status": "ok",
|
|
115
|
+
"inserted": 2,
|
|
116
|
+
"ids": ["doc1", "doc2"],
|
|
117
|
+
"engine": { "l5": 2, "l6": 2 },
|
|
118
|
+
"duration_ms": 234.5
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
30-50× faster than calling `/store` N times when ingesting more than ~5 records.
|
|
123
|
+
|
|
124
|
+
#### `POST /forget` (RESTORED — was in v0.4.x, removed in v0.5.x)
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
// Delete one record
|
|
128
|
+
{ "id": "doc1" }
|
|
129
|
+
|
|
130
|
+
// Or delete all records matching a metadata filter
|
|
131
|
+
{ "metadata_contains": { "bench_tag": "test-run-12345" } }
|
|
132
|
+
|
|
133
|
+
// Response
|
|
134
|
+
{ "deleted": 17, "engine": "pentatonic-memory-engine" }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Required for: test pollution control, GDPR data deletion, multi-tenant isolation, bench harnesses.
|
|
138
|
+
|
|
139
|
+
### Data migration
|
|
140
|
+
|
|
141
|
+
There is no automated dump-and-replay tool. Two paths:
|
|
142
|
+
|
|
143
|
+
**Path A — Re-ingest from source.**
|
|
144
|
+
If your Pentatonic deployment was populated from a known source (chat archives, document repository, TES events), re-run the ingestion against the engine. Use `/store-batch` for speed.
|
|
145
|
+
|
|
146
|
+
**Path B — Dump-and-replay from Postgres.**
|
|
147
|
+
If you only have the v0.5 Postgres database:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Dump as JSONL
|
|
151
|
+
psql $DATABASE_URL -A -t -c \
|
|
152
|
+
"SELECT json_build_object('id', id, 'content', content, 'metadata', metadata)::text
|
|
153
|
+
FROM memory_nodes WHERE client_id = 'your-client'" \
|
|
154
|
+
> export.jsonl
|
|
155
|
+
|
|
156
|
+
# Replay against the engine
|
|
157
|
+
python tools/replay.py export.jsonl --target http://your-engine-host:8099
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
A `tools/replay.py` reference implementation lives under `tools/` in this package.
|
|
161
|
+
|
|
162
|
+
### What you lose
|
|
163
|
+
|
|
164
|
+
- **The `metadata.hypothetical_queries` field stops being generated at ingest time.** The engine generates HyDE queries at SEARCH time instead, against the user's actual query (better matching, faster ingest).
|
|
165
|
+
- **`metadata.distilled_from` atoms are no longer auto-generated.** If you were relying on the v0.5+ atomic-fact distillation behaviour, that's a feature of v0.5+ specifically — not a portable feature. The engine treats memories as canonical raw chunks. You can still run distillation as a separate post-processing step if needed.
|
|
166
|
+
|
|
167
|
+
### What you gain
|
|
168
|
+
|
|
169
|
+
- ~5× retrieval accuracy on substring/exact-match benches (~17.6% → ~82.4% mean)
|
|
170
|
+
- 30-50× faster bulk ingest via `/store-batch`
|
|
171
|
+
- Restored `/forget` endpoint
|
|
172
|
+
- Cross-encoder reranking on top-50
|
|
173
|
+
- Knowledge-graph-aware retrieval (entity overlap signal)
|
|
174
|
+
- Per-layer health visibility
|
|
175
|
+
|
|
176
|
+
### Rollback
|
|
177
|
+
|
|
178
|
+
The engine doesn't write to your existing Postgres. Roll back by switching the env var back. No data lost.
|