prme 0.15.0__tar.gz
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.
- prme-0.15.0/PKG-INFO +329 -0
- prme-0.15.0/README.md +268 -0
- prme-0.15.0/pyproject.toml +103 -0
- prme-0.15.0/src/prme/__init__.py +317 -0
- prme-0.15.0/src/prme/_temporal.py +9 -0
- prme-0.15.0/src/prme/api/__init__.py +20 -0
- prme-0.15.0/src/prme/api/__main__.py +64 -0
- prme-0.15.0/src/prme/api/app.py +106 -0
- prme-0.15.0/src/prme/api/models.py +584 -0
- prme-0.15.0/src/prme/api/routes.py +1389 -0
- prme-0.15.0/src/prme/api/server.py +153 -0
- prme-0.15.0/src/prme/cli.py +1667 -0
- prme-0.15.0/src/prme/client.py +1135 -0
- prme-0.15.0/src/prme/config.py +1249 -0
- prme-0.15.0/src/prme/config_audit.py +318 -0
- prme-0.15.0/src/prme/epistemic/__init__.py +16 -0
- prme-0.15.0/src/prme/epistemic/inference.py +99 -0
- prme-0.15.0/src/prme/epistemic/matrix.py +135 -0
- prme-0.15.0/src/prme/epistemic/migration.py +160 -0
- prme-0.15.0/src/prme/ingestion/__init__.py +45 -0
- prme-0.15.0/src/prme/ingestion/claim_merge.py +122 -0
- prme-0.15.0/src/prme/ingestion/entity_merge.py +158 -0
- prme-0.15.0/src/prme/ingestion/entity_references.py +102 -0
- prme-0.15.0/src/prme/ingestion/errors.py +123 -0
- prme-0.15.0/src/prme/ingestion/extraction.py +1661 -0
- prme-0.15.0/src/prme/ingestion/graph_writer.py +224 -0
- prme-0.15.0/src/prme/ingestion/grounding.py +594 -0
- prme-0.15.0/src/prme/ingestion/novelty.py +181 -0
- prme-0.15.0/src/prme/ingestion/pipeline.py +1752 -0
- prme-0.15.0/src/prme/ingestion/planning.py +225 -0
- prme-0.15.0/src/prme/ingestion/resolution.py +517 -0
- prme-0.15.0/src/prme/ingestion/schema.py +301 -0
- prme-0.15.0/src/prme/ingestion/supersedence.py +316 -0
- prme-0.15.0/src/prme/ingestion/temporal.py +35 -0
- prme-0.15.0/src/prme/integrations/__init__.py +11 -0
- prme-0.15.0/src/prme/integrations/_chat_history.py +131 -0
- prme-0.15.0/src/prme/integrations/coding.py +316 -0
- prme-0.15.0/src/prme/integrations/coding_server.py +28 -0
- prme-0.15.0/src/prme/integrations/langchain.py +287 -0
- prme-0.15.0/src/prme/integrations/llamaindex.py +334 -0
- prme-0.15.0/src/prme/integrations/product_candidates.py +211 -0
- prme-0.15.0/src/prme/integrations/typesafe.py +579 -0
- prme-0.15.0/src/prme/mcp/__init__.py +22 -0
- prme-0.15.0/src/prme/mcp/__main__.py +5 -0
- prme-0.15.0/src/prme/mcp/server.py +1889 -0
- prme-0.15.0/src/prme/model_runtime/__init__.py +5 -0
- prme-0.15.0/src/prme/model_runtime/generation.py +109 -0
- prme-0.15.0/src/prme/models/__init__.py +84 -0
- prme-0.15.0/src/prme/models/aggregation.py +308 -0
- prme-0.15.0/src/prme/models/base.py +38 -0
- prme-0.15.0/src/prme/models/consolidation.py +217 -0
- prme-0.15.0/src/prme/models/credit.py +97 -0
- prme-0.15.0/src/prme/models/derivation.py +194 -0
- prme-0.15.0/src/prme/models/direct_store.py +54 -0
- prme-0.15.0/src/prme/models/edges.py +52 -0
- prme-0.15.0/src/prme/models/entity_identity.py +19 -0
- prme-0.15.0/src/prme/models/events.py +65 -0
- prme-0.15.0/src/prme/models/extraction.py +152 -0
- prme-0.15.0/src/prme/models/extraction_work.py +46 -0
- prme-0.15.0/src/prme/models/learning.py +547 -0
- prme-0.15.0/src/prme/models/nodes.py +109 -0
- prme-0.15.0/src/prme/models/owner_reference.py +32 -0
- prme-0.15.0/src/prme/models/processing.py +82 -0
- prme-0.15.0/src/prme/models/profile.py +166 -0
- prme-0.15.0/src/prme/models/provenance.py +38 -0
- prme-0.15.0/src/prme/models/relevance.py +730 -0
- prme-0.15.0/src/prme/models/speaker.py +136 -0
- prme-0.15.0/src/prme/models/temporal.py +193 -0
- prme-0.15.0/src/prme/models/value_bindings.py +368 -0
- prme-0.15.0/src/prme/organizer/__init__.py +50 -0
- prme-0.15.0/src/prme/organizer/alias_resolution.py +412 -0
- prme-0.15.0/src/prme/organizer/consolidation.py +589 -0
- prme-0.15.0/src/prme/organizer/contradiction.py +94 -0
- prme-0.15.0/src/prme/organizer/decay.py +178 -0
- prme-0.15.0/src/prme/organizer/deduplication.py +296 -0
- prme-0.15.0/src/prme/organizer/jobs.py +869 -0
- prme-0.15.0/src/prme/organizer/maintenance.py +323 -0
- prme-0.15.0/src/prme/organizer/merge_policy.py +36 -0
- prme-0.15.0/src/prme/organizer/models.py +57 -0
- prme-0.15.0/src/prme/organizer/oscillation.py +174 -0
- prme-0.15.0/src/prme/organizer/profiles.py +43 -0
- prme-0.15.0/src/prme/organizer/summarization.py +665 -0
- prme-0.15.0/src/prme/py.typed +1 -0
- prme-0.15.0/src/prme/quality/__init__.py +23 -0
- prme-0.15.0/src/prme/quality/feedback.py +116 -0
- prme-0.15.0/src/prme/quality/metrics.py +82 -0
- prme-0.15.0/src/prme/quality/tuner.py +198 -0
- prme-0.15.0/src/prme/retrieval/__init__.py +127 -0
- prme-0.15.0/src/prme/retrieval/abstention.py +140 -0
- prme-0.15.0/src/prme/retrieval/aggregation.py +511 -0
- prme-0.15.0/src/prme/retrieval/aggregation_planning.py +165 -0
- prme-0.15.0/src/prme/retrieval/answerability.py +547 -0
- prme-0.15.0/src/prme/retrieval/candidates.py +566 -0
- prme-0.15.0/src/prme/retrieval/claim_verification.py +1077 -0
- prme-0.15.0/src/prme/retrieval/config.py +787 -0
- prme-0.15.0/src/prme/retrieval/context_formatter.py +1014 -0
- prme-0.15.0/src/prme/retrieval/credit.py +151 -0
- prme-0.15.0/src/prme/retrieval/episode_context.py +194 -0
- prme-0.15.0/src/prme/retrieval/evidence_context.py +341 -0
- prme-0.15.0/src/prme/retrieval/execution.py +102 -0
- prme-0.15.0/src/prme/retrieval/filtering.py +175 -0
- prme-0.15.0/src/prme/retrieval/full_learning.py +275 -0
- prme-0.15.0/src/prme/retrieval/learning.py +265 -0
- prme-0.15.0/src/prme/retrieval/models.py +767 -0
- prme-0.15.0/src/prme/retrieval/packing.py +1026 -0
- prme-0.15.0/src/prme/retrieval/pipeline.py +1391 -0
- prme-0.15.0/src/prme/retrieval/query_analysis.py +382 -0
- prme-0.15.0/src/prme/retrieval/ranking_adjustments.py +19 -0
- prme-0.15.0/src/prme/retrieval/reformulation.py +214 -0
- prme-0.15.0/src/prme/retrieval/reranker.py +203 -0
- prme-0.15.0/src/prme/retrieval/scope.py +30 -0
- prme-0.15.0/src/prme/retrieval/scoring.py +984 -0
- prme-0.15.0/src/prme/retrieval/selection.py +151 -0
- prme-0.15.0/src/prme/retrieval/session_context.py +259 -0
- prme-0.15.0/src/prme/retrieval/snapshots.py +251 -0
- prme-0.15.0/src/prme/retrieval/temporal.py +293 -0
- prme-0.15.0/src/prme/retrieval/temporal_relation_models.py +99 -0
- prme-0.15.0/src/prme/retrieval/temporal_relation_providers.py +554 -0
- prme-0.15.0/src/prme/retrieval/temporal_relations.py +677 -0
- prme-0.15.0/src/prme/retrieval/time.py +12 -0
- prme-0.15.0/src/prme/retrieval/tokenization.py +15 -0
- prme-0.15.0/src/prme/storage/__init__.py +25 -0
- prme-0.15.0/src/prme/storage/_snapshot_json.py +117 -0
- prme-0.15.0/src/prme/storage/_threading.py +41 -0
- prme-0.15.0/src/prme/storage/alias_proposal.py +657 -0
- prme-0.15.0/src/prme/storage/alias_review.py +616 -0
- prme-0.15.0/src/prme/storage/blobs.py +90 -0
- prme-0.15.0/src/prme/storage/citations.py +117 -0
- prme-0.15.0/src/prme/storage/condition_evaluation.py +425 -0
- prme-0.15.0/src/prme/storage/consolidation_publication.py +762 -0
- prme-0.15.0/src/prme/storage/consolidation_retirement.py +163 -0
- prme-0.15.0/src/prme/storage/derivation.py +232 -0
- prme-0.15.0/src/prme/storage/derivation_registry.py +154 -0
- prme-0.15.0/src/prme/storage/derivation_staging.py +57 -0
- prme-0.15.0/src/prme/storage/duckpgq_graph.py +2020 -0
- prme-0.15.0/src/prme/storage/durable_queue.py +97 -0
- prme-0.15.0/src/prme/storage/embedding.py +512 -0
- prme-0.15.0/src/prme/storage/encryption.py +460 -0
- prme-0.15.0/src/prme/storage/engine.py +4360 -0
- prme-0.15.0/src/prme/storage/event_store.py +730 -0
- prme-0.15.0/src/prme/storage/extraction_work.py +388 -0
- prme-0.15.0/src/prme/storage/fast_ingest.py +165 -0
- prme-0.15.0/src/prme/storage/graph_store.py +573 -0
- prme-0.15.0/src/prme/storage/index_eviction.py +48 -0
- prme-0.15.0/src/prme/storage/lexical_index.py +873 -0
- prme-0.15.0/src/prme/storage/lifecycle.py +232 -0
- prme-0.15.0/src/prme/storage/metadata.py +30 -0
- prme-0.15.0/src/prme/storage/namespace_identity.py +33 -0
- prme-0.15.0/src/prme/storage/organizer_merge.py +216 -0
- prme-0.15.0/src/prme/storage/oscillation_penalty.py +418 -0
- prme-0.15.0/src/prme/storage/pack_manifest.py +118 -0
- prme-0.15.0/src/prme/storage/pack_tools.py +438 -0
- prme-0.15.0/src/prme/storage/pg/__init__.py +26 -0
- prme-0.15.0/src/prme/storage/pg/event_store.py +600 -0
- prme-0.15.0/src/prme/storage/pg/graph_store.py +1494 -0
- prme-0.15.0/src/prme/storage/pg/lexical_index.py +191 -0
- prme-0.15.0/src/prme/storage/pg/namespace.py +131 -0
- prme-0.15.0/src/prme/storage/pg/pool.py +35 -0
- prme-0.15.0/src/prme/storage/pg/schema.py +261 -0
- prme-0.15.0/src/prme/storage/pg/vector_index.py +240 -0
- prme-0.15.0/src/prme/storage/pg/vector_sql.py +44 -0
- prme-0.15.0/src/prme/storage/pg/workspace_catalog.py +75 -0
- prme-0.15.0/src/prme/storage/profile_collection.py +272 -0
- prme-0.15.0/src/prme/storage/profile_publication.py +270 -0
- prme-0.15.0/src/prme/storage/profile_registry.py +292 -0
- prme-0.15.0/src/prme/storage/profile_retirement.py +126 -0
- prme-0.15.0/src/prme/storage/profile_work.py +539 -0
- prme-0.15.0/src/prme/storage/provenance.py +101 -0
- prme-0.15.0/src/prme/storage/ranking_profiles.py +284 -0
- prme-0.15.0/src/prme/storage/reinforcement.py +281 -0
- prme-0.15.0/src/prme/storage/relevance.py +201 -0
- prme-0.15.0/src/prme/storage/retention.py +369 -0
- prme-0.15.0/src/prme/storage/schema.py +575 -0
- prme-0.15.0/src/prme/storage/supersedence.py +261 -0
- prme-0.15.0/src/prme/storage/transition_evidence.py +48 -0
- prme-0.15.0/src/prme/storage/vector_index.py +872 -0
- prme-0.15.0/src/prme/storage/write_queue.py +271 -0
- prme-0.15.0/src/prme/types.py +301 -0
- prme-0.15.0/src/prme/vision/__init__.py +44 -0
- prme-0.15.0/src/prme/vision/describe.py +71 -0
- prme-0.15.0/src/prme/vision/errors.py +33 -0
- prme-0.15.0/src/prme/vision/frames.py +343 -0
- prme-0.15.0/src/prme/vision/keyframes.py +158 -0
- prme-0.15.0/src/prme/vision/observe.py +375 -0
- prme-0.15.0/src/prme/vision/provider.py +98 -0
- prme-0.15.0/src/prme/vision/repeat.py +44 -0
- prme-0.15.0/src/prme/workspace.py +469 -0
prme-0.15.0/PKG-INFO
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: prme
|
|
3
|
+
Version: 0.15.0
|
|
4
|
+
Summary: Portable Relational Memory Engine - local-first memory substrate for LLM-powered systems
|
|
5
|
+
Keywords: memory,llm,ai,knowledge-graph,vector-search,event-sourcing,duckdb,agents,rag,long-term-memory,mcp
|
|
6
|
+
Author: Dwamian McLeish
|
|
7
|
+
Author-email: Dwamian McLeish <dwamian@journey.ly>
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Requires-Dist: duckdb>=1.4.0
|
|
18
|
+
Requires-Dist: usearch>=2.26.2
|
|
19
|
+
Requires-Dist: tantivy>=0.22.0
|
|
20
|
+
Requires-Dist: pydantic>=2.12
|
|
21
|
+
Requires-Dist: pydantic-settings>=2.9
|
|
22
|
+
Requires-Dist: fastembed>=0.7.4
|
|
23
|
+
Requires-Dist: structlog
|
|
24
|
+
Requires-Dist: pytz>=2025.2
|
|
25
|
+
Requires-Dist: instructor>=1.14
|
|
26
|
+
Requires-Dist: openai>=2.20
|
|
27
|
+
Requires-Dist: anthropic>=0.80
|
|
28
|
+
Requires-Dist: ollama>=0.6
|
|
29
|
+
Requires-Dist: dateparser>=1.2
|
|
30
|
+
Requires-Dist: cryptography>=43.0
|
|
31
|
+
Requires-Dist: filelock>=3.16
|
|
32
|
+
Requires-Dist: httpx>=0.27
|
|
33
|
+
Requires-Dist: tiktoken>=0.12
|
|
34
|
+
Requires-Dist: numpy>=1.26
|
|
35
|
+
Requires-Dist: pillow>=10.1
|
|
36
|
+
Requires-Dist: fastapi>=0.115 ; extra == 'api'
|
|
37
|
+
Requires-Dist: uvicorn[standard]>=0.30 ; extra == 'api'
|
|
38
|
+
Requires-Dist: tiktoken>=0.12 ; extra == 'evaluation'
|
|
39
|
+
Requires-Dist: langchain-core>=0.3 ; extra == 'langchain'
|
|
40
|
+
Requires-Dist: llama-index-core>=0.12 ; extra == 'llamaindex'
|
|
41
|
+
Requires-Dist: mcp>=1.26.0,<2 ; extra == 'mcp'
|
|
42
|
+
Requires-Dist: asyncpg>=0.29.0 ; extra == 'postgres'
|
|
43
|
+
Requires-Dist: pgvector>=0.3.0 ; extra == 'postgres'
|
|
44
|
+
Requires-Dist: sentence-transformers>=4.0 ; extra == 'reranker'
|
|
45
|
+
Requires-Dist: sentence-transformers>=4.0 ; extra == 'verification'
|
|
46
|
+
Requires-Python: >=3.11
|
|
47
|
+
Project-URL: Changelog, https://github.com/dwamianm/prism/blob/main/CHANGELOG.md
|
|
48
|
+
Project-URL: Documentation, https://github.com/dwamianm/prism/tree/main/docs
|
|
49
|
+
Project-URL: Homepage, https://github.com/dwamianm/prism
|
|
50
|
+
Project-URL: Issues, https://github.com/dwamianm/prism/issues
|
|
51
|
+
Project-URL: Repository, https://github.com/dwamianm/prism
|
|
52
|
+
Provides-Extra: api
|
|
53
|
+
Provides-Extra: evaluation
|
|
54
|
+
Provides-Extra: langchain
|
|
55
|
+
Provides-Extra: llamaindex
|
|
56
|
+
Provides-Extra: mcp
|
|
57
|
+
Provides-Extra: postgres
|
|
58
|
+
Provides-Extra: reranker
|
|
59
|
+
Provides-Extra: verification
|
|
60
|
+
Description-Content-Type: text/markdown
|
|
61
|
+
|
|
62
|
+
# PRME — Portable Relational Memory Engine
|
|
63
|
+
|
|
64
|
+
[](https://www.python.org/downloads/)
|
|
65
|
+
[](LICENSE)
|
|
66
|
+
[](https://github.com/dwamianm/prism/actions/workflows/ci.yml)
|
|
67
|
+
|
|
68
|
+
**Local-first, embeddable memory for LLM-powered applications.**
|
|
69
|
+
|
|
70
|
+
PRME gives agents and chatbots persistent memory through an append-only event
|
|
71
|
+
log, typed relationships, and hybrid retrieval. It preserves source evidence,
|
|
72
|
+
tracks changing claims, and packs relevant memories into a configurable token
|
|
73
|
+
budget. The default backend runs locally in a portable directory; PostgreSQL is
|
|
74
|
+
available for server deployments.
|
|
75
|
+
|
|
76
|
+
**Current release: v0.15.0.** Python 3.11+, synchronous and async clients, HTTP,
|
|
77
|
+
MCP, and LangChain/LlamaIndex integrations.
|
|
78
|
+
|
|
79
|
+
## Architecture
|
|
80
|
+
|
|
81
|
+
Four storage layers sit behind a unified memory API:
|
|
82
|
+
|
|
83
|
+
| Layer | Local implementation | Purpose |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| Event store | DuckDB | Immutable source events and durable operation records |
|
|
86
|
+
| Graph store | DuckDB tables and recursive CTEs | Typed memories, relationships, temporal validity, confidence, and provenance |
|
|
87
|
+
| Vector index | USearch | Semantic similarity search with versioned embeddings |
|
|
88
|
+
| Lexical index | Tantivy | BM25 full-text search |
|
|
89
|
+
|
|
90
|
+
The optional PostgreSQL backend uses PostgreSQL tables, pgvector, and full-text
|
|
91
|
+
search behind the same API. Both backends default to exact vector search;
|
|
92
|
+
approximate search is configurable.
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
Source text → event log → direct storage or LLM extraction → graph + indexes
|
|
96
|
+
|
|
97
|
+
Query → intent, entity, and time analysis
|
|
98
|
+
→ graph, vector, lexical, and recent-memory candidates
|
|
99
|
+
→ deterministic scoring and filtering
|
|
100
|
+
→ token-bounded context with provenance
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- **Ingestion:** `store()` writes a memory directly without an LLM.
|
|
104
|
+
`ingest()` extracts entities, facts, and relationships through a configured
|
|
105
|
+
provider. Deferred ingestion records durable work that can resume after restart.
|
|
106
|
+
- **Memory state:** typed nodes carry owner, scope, lifecycle, confidence,
|
|
107
|
+
validity windows, and source references. Explicit corrections and contradiction
|
|
108
|
+
operations preserve earlier claims; automatic store-time supersedence is opt-in.
|
|
109
|
+
- **Retrieval:** combines multiple search paths and packs selected evidence into
|
|
110
|
+
context. Structured assertion-state and aggregation APIs support exact stored
|
|
111
|
+
claim queries and decimal totals beyond semantic top-k retrieval.
|
|
112
|
+
- **Default retrieval behavior:** candidates are ranked by reciprocal rank
|
|
113
|
+
fusion of their semantic and lexical ranks, with a recency boost on
|
|
114
|
+
current-state questions and an event-time tie-break. Packing uses balanced
|
|
115
|
+
ordering and renders each record as one plain line (the `reader` context
|
|
116
|
+
format), while the full records stay in the bundle's sections and the
|
|
117
|
+
retrieval receipt. These defaults changed after v0.12.0;
|
|
118
|
+
[Default retrieval settings](docs/PACKING.md#default-retrieval-settings)
|
|
119
|
+
lists the earlier values and the environment variables that restore them.
|
|
120
|
+
- **Organizer:** maintains promotion, decay, summaries, deduplication, archival,
|
|
121
|
+
and index compaction. It runs opportunistically or through `prme organize`;
|
|
122
|
+
recurring schedules use an external timer. Shared stores should pass `user_id`.
|
|
123
|
+
- **Workspaces:** `MemoryWorkspace` manages named local packs or PostgreSQL
|
|
124
|
+
schemas with identity checks and scoped leases.
|
|
125
|
+
|
|
126
|
+
A local memory pack is a directory by default, or one file when you opt in:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
my_memories/ # directory pack (the default)
|
|
130
|
+
├── memory.duckdb
|
|
131
|
+
├── vectors.usearch
|
|
132
|
+
├── lexical_index/
|
|
133
|
+
└── manifest.json # only when encryption is on
|
|
134
|
+
|
|
135
|
+
memories.prme # single-file pack (opt-in)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Giving `MemoryClient` a path that ends in `.prme`, or setting `PRME_PACK_PATH`,
|
|
139
|
+
selects the single-file layout: one DuckDB file holds the event log, the graph,
|
|
140
|
+
the vector snapshot and a pack manifest, and the lexical index is rebuilt in
|
|
141
|
+
memory when the pack opens. `prme migrate` copies a directory pack into a new
|
|
142
|
+
`.prme` file, and [single-file packs](docs/INTEGRATION.md#single-file-packs)
|
|
143
|
+
covers encryption, compaction and how retrieval compares across the layouts.
|
|
144
|
+
|
|
145
|
+
Search indexes can be regenerated from the durable graph with `prme rebuild`.
|
|
146
|
+
Event time, ingestion time, and validity time remain distinct. The `knowledge_at`
|
|
147
|
+
filter applies an ingestion cutoff to current graph/index state; exact historical
|
|
148
|
+
state replay is not currently available.
|
|
149
|
+
|
|
150
|
+
## Current benchmarks
|
|
151
|
+
|
|
152
|
+
| Benchmark | Correct answers | Answer accuracy |
|
|
153
|
+
|---|---:|---:|
|
|
154
|
+
| LongMemEval-S | 453 / 500 | **90.6%** |
|
|
155
|
+
| LoCoMo, non-adversarial questions | 1,250 / 1,540 | **81.2%** |
|
|
156
|
+
|
|
157
|
+
### LongMemEval-S by question type
|
|
158
|
+
|
|
159
|
+
| Question type | Correct answers | Answer accuracy |
|
|
160
|
+
|---|---:|---:|
|
|
161
|
+
| Single-session user | 69 / 70 | 98.6% |
|
|
162
|
+
| Single-session assistant | 54 / 56 | 96.4% |
|
|
163
|
+
| Knowledge update | 71 / 78 | 91.0% |
|
|
164
|
+
| Temporal reasoning | 120 / 133 | 90.2% |
|
|
165
|
+
| Single-session preference | 26 / 30 | 86.7% |
|
|
166
|
+
| Multi-session | 113 / 133 | 85.0% |
|
|
167
|
+
|
|
168
|
+
### LoCoMo by question type
|
|
169
|
+
|
|
170
|
+
| Question type | Correct answers | Answer accuracy |
|
|
171
|
+
|---|---:|---:|
|
|
172
|
+
| Single-hop | 756 / 841 | 89.9% |
|
|
173
|
+
| Temporal | 256 / 321 | 79.8% |
|
|
174
|
+
| Multi-hop | 182 / 282 | 64.5% |
|
|
175
|
+
| Open-domain | 56 / 96 | 58.3% |
|
|
176
|
+
|
|
177
|
+
Measured on September 25, 2026 with the v0.13.0 retrieval defaults and a
|
|
178
|
+
3,996-token memory-context budget per question, over memory packs built with
|
|
179
|
+
`store()`, which never runs extraction. The defaults adopted on October 6
|
|
180
|
+
change what `ingest()` stores and how repeated text is packed, so they were
|
|
181
|
+
measured on a separate track over packs built through `ingest()`. See
|
|
182
|
+
[BENCHMARKS.md](BENCHMARKS.md) for both tracks, the method, earlier results
|
|
183
|
+
and reproducibility artifacts.
|
|
184
|
+
|
|
185
|
+
## Installation
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pip install prme
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Optional integrations:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
pip install "prme[postgres]" # PostgreSQL backend
|
|
195
|
+
pip install "prme[api]" # HTTP API
|
|
196
|
+
pip install "prme[mcp]" # MCP server
|
|
197
|
+
pip install "prme[langchain]" # LangChain retriever and chat history
|
|
198
|
+
pip install "prme[llamaindex]" # LlamaIndex retriever and chat store
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Quickstart
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from prme import MemoryClient
|
|
205
|
+
|
|
206
|
+
with MemoryClient("./my_memories") as memory:
|
|
207
|
+
memory.store("Alice prefers dark mode in her editors.", user_id="alice")
|
|
208
|
+
memory.store("The team decided to use PostgreSQL.", user_id="alice")
|
|
209
|
+
|
|
210
|
+
response = memory.retrieve("What are Alice's preferences?", user_id="alice")
|
|
211
|
+
for result in response.results:
|
|
212
|
+
print(f"[{result.composite_score:.3f}] {result.node.content}")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`MemoryClient` is synchronous; `MemoryEngine` provides the async API. Direct
|
|
216
|
+
storage and retrieval use local embeddings by default and require no LLM API key.
|
|
217
|
+
Use `ingest()` with an OpenAI, Anthropic, or Ollama extraction provider when you
|
|
218
|
+
want structured memories extracted from conversation text.
|
|
219
|
+
|
|
220
|
+
Configure PRME through `PRMEConfig`, `PRME_` environment variables, or a `.env`
|
|
221
|
+
file. Constructor values override the environment, which overrides `.env`.
|
|
222
|
+
The [configuration reference](documentation/configuration.md) lists the
|
|
223
|
+
settings and their defaults. To return to the v0.12.0 retrieval defaults, set
|
|
224
|
+
`PRME_SCORING__FUSION=weighted`, `PRME_PACKING__CONTEXT_FORMAT=auditable` and
|
|
225
|
+
`PRME_PACKING__MULTIPATH_ORDERING=balanced` (the last is the default again and
|
|
226
|
+
only makes it explicit; see
|
|
227
|
+
[Default retrieval settings](docs/PACKING.md#default-retrieval-settings)).
|
|
228
|
+
See the [integration reference](docs/INTEGRATION.md) and
|
|
229
|
+
[examples](examples/) for configuration and application patterns.
|
|
230
|
+
|
|
231
|
+
## Interfaces and tools
|
|
232
|
+
|
|
233
|
+
Use the CLI to initialize, inspect, search, and maintain a local pack:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
prme init ./my_memories
|
|
237
|
+
prme doctor ./my_memories
|
|
238
|
+
prme search ./my_memories/memory.duckdb "Alice's preferences" --user-id alice
|
|
239
|
+
prme organize ./my_memories/memory.duckdb --user-id alice
|
|
240
|
+
prme compact ./my_memories/memory.duckdb
|
|
241
|
+
prme migrate ./my_memories ./memories.prme
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`prme compact` rewrites a closed pack file to give back the space DuckDB never
|
|
245
|
+
returns, and `prme migrate` copies a directory pack into a new single-file pack,
|
|
246
|
+
leaving the directory in place. Every command that takes `memory.duckdb` also
|
|
247
|
+
takes a `.prme` file, and `prme init ./memories.prme` creates one. See the
|
|
248
|
+
[CLI reference](documentation/cli.md).
|
|
249
|
+
|
|
250
|
+
For a local assistant, install the MCP extra and run with a fixed owner:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
PRME_MCP_USER_ID=alice prme-mcp --db-path ./my_memories
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
`--db-path` also accepts a single-file pack, such as `./memories.prme`.
|
|
257
|
+
|
|
258
|
+
The HTTP extra provides a FastAPI service via `python -m prme.api`, which binds to
|
|
259
|
+
`127.0.0.1` and refuses a network bind without API credentials (see
|
|
260
|
+
[Running the Server](documentation/http-api.md#running-the-server)).
|
|
261
|
+
Shared HTTP deployments bind owners to credentials through `PRME_API_USER_KEYS`;
|
|
262
|
+
MCP Streamable HTTP uses its separate `PRME_MCP_USER_KEYS` setting.
|
|
263
|
+
See the [HTTP guide](docs/HTTP-API.md) and
|
|
264
|
+
[framework integration guide](docs/FRAMEWORK-INTEGRATIONS.md) for application setup.
|
|
265
|
+
|
|
266
|
+
To browse stored entries and explore their graph connections from a source
|
|
267
|
+
checkout, run `uv run --extra api python -m web.server` and open
|
|
268
|
+
**http://127.0.0.1:8080**. The standalone [memory explorer](web/README.md) lives in
|
|
269
|
+
`web/` and includes filters, source evidence, and an interactive relationship map.
|
|
270
|
+
|
|
271
|
+
## Milestones
|
|
272
|
+
|
|
273
|
+
| Milestone | Delivered |
|
|
274
|
+
|---|---|
|
|
275
|
+
| Core memory foundation, through v0.9 | Event sourcing, typed graph, hybrid retrieval, organizer jobs, encryption, CLI, evaluation harness, and index rebuilds |
|
|
276
|
+
| v0.10 | Deterministic vector search, batched ingestion indexing, and context-budget enforcement |
|
|
277
|
+
| v0.11 | Tenant-scoped maintenance, ownership and retrieval-filter fixes, and broader backend CI coverage |
|
|
278
|
+
| v0.12 | Durable ingestion and recovery, atomic lifecycle and correction records, scoped workspaces, structured assertion and quantity operations, retrieval receipts, and evaluated ranking profiles |
|
|
279
|
+
| v0.13 | Rank fusion with current-state recency, the one-line reader context format and balanced ordering as retrieval defaults; conversation participants with speaker names; refusal of unauthenticated network binds for the HTTP API; an offline evidence gate and paired answer runs for measuring retrieval changes |
|
|
280
|
+
| v0.14, current | A claim's own sentences as its text, a named speaker's I, me and my bound to the speaker, and each source text packed once, as `ingest()` and reader context defaults; repeated extracted claims merged into one current record; a browser memory explorer; benchmark packs built through `ingest()`, with the evidence gate and a DeepSeek answer track over them |
|
|
281
|
+
|
|
282
|
+
Experimental reranking (including the cross-encoder rank order), temporal-relation
|
|
283
|
+
guidance, model-assisted verification, temporal-first query intent, event-time
|
|
284
|
+
recency for the weighted formula, session context packing, windowed extraction,
|
|
285
|
+
self-contained fact text and speaker grounding remain opt-in.
|
|
286
|
+
Detailed changes are in the [changelog](CHANGELOG.md).
|
|
287
|
+
|
|
288
|
+
Current work follows [epic #77](https://github.com/dwamianm/prism/issues/77),
|
|
289
|
+
which acts on the 2026-09-23 benchmark gap audit: a reader-facing context,
|
|
290
|
+
better ranking, the context budget, and dated facts extracted at write time for
|
|
291
|
+
multi-hop and list questions. See the [roadmap](ROADMAP.md) for what has been
|
|
292
|
+
delivered and what is still open.
|
|
293
|
+
|
|
294
|
+
Images and video as memory sources are
|
|
295
|
+
[RFC-0018](docs/RFC-0018-Visual-Memory.md). Its phase 1 is implemented and
|
|
296
|
+
off by default: with `vision.enabled` set, `MemoryClient.observe()` and
|
|
297
|
+
`prme observe` turn a photo or a saved video into dated observation events
|
|
298
|
+
described by a local vision model, with a thumbnail of each keyframe kept in
|
|
299
|
+
the pack for provenance. The benchmark with real recordings is still open.
|
|
300
|
+
|
|
301
|
+
## Documentation
|
|
302
|
+
|
|
303
|
+
- [Developer guides](documentation/README.md) and [configuration reference](documentation/configuration.md)
|
|
304
|
+
- [Architecture and RFC index](docs/INDEX.md)
|
|
305
|
+
- [Integration reference](docs/INTEGRATION.md) and [framework adapters](docs/FRAMEWORK-INTEGRATIONS.md)
|
|
306
|
+
- [Context packing and default retrieval settings](docs/PACKING.md) and [retrieval feedback and learning](docs/LEARNING.md)
|
|
307
|
+
- [Experimental retrieval policies](docs/EXPERIMENTAL-RETRIEVAL-POLICIES.md)
|
|
308
|
+
- [Memory corrections](docs/MEMORY-CORRECTIONS.md)
|
|
309
|
+
- [Entity profiles](docs/ENTITY-PROFILES.md) and [entity identity](docs/ENTITY-IDENTITY.md)
|
|
310
|
+
- [Workspaces](docs/WORKSPACES.md) and [local resource control](docs/LOCAL-RESOURCES.md)
|
|
311
|
+
- [Custom embeddings](docs/CUSTOM-EMBEDDINGS.md) and [typed value bindings](docs/VALUE-BINDINGS.md)
|
|
312
|
+
- [HTTP API](docs/HTTP-API.md)
|
|
313
|
+
|
|
314
|
+
## Development
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
git clone https://github.com/dwamianm/prism.git
|
|
318
|
+
cd prism
|
|
319
|
+
uv sync --dev
|
|
320
|
+
uv run pytest tests/ -q
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
PostgreSQL tests require a live database configured through
|
|
324
|
+
`PRME_TEST_DATABASE_URL`. See [CONTRIBUTING.md](CONTRIBUTING.md) for development
|
|
325
|
+
setup, checks, and contribution guidelines.
|
|
326
|
+
|
|
327
|
+
## License
|
|
328
|
+
|
|
329
|
+
Apache License 2.0 — see [LICENSE](LICENSE).
|
prme-0.15.0/README.md
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# PRME — Portable Relational Memory Engine
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/downloads/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://github.com/dwamianm/prism/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
**Local-first, embeddable memory for LLM-powered applications.**
|
|
8
|
+
|
|
9
|
+
PRME gives agents and chatbots persistent memory through an append-only event
|
|
10
|
+
log, typed relationships, and hybrid retrieval. It preserves source evidence,
|
|
11
|
+
tracks changing claims, and packs relevant memories into a configurable token
|
|
12
|
+
budget. The default backend runs locally in a portable directory; PostgreSQL is
|
|
13
|
+
available for server deployments.
|
|
14
|
+
|
|
15
|
+
**Current release: v0.15.0.** Python 3.11+, synchronous and async clients, HTTP,
|
|
16
|
+
MCP, and LangChain/LlamaIndex integrations.
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
Four storage layers sit behind a unified memory API:
|
|
21
|
+
|
|
22
|
+
| Layer | Local implementation | Purpose |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Event store | DuckDB | Immutable source events and durable operation records |
|
|
25
|
+
| Graph store | DuckDB tables and recursive CTEs | Typed memories, relationships, temporal validity, confidence, and provenance |
|
|
26
|
+
| Vector index | USearch | Semantic similarity search with versioned embeddings |
|
|
27
|
+
| Lexical index | Tantivy | BM25 full-text search |
|
|
28
|
+
|
|
29
|
+
The optional PostgreSQL backend uses PostgreSQL tables, pgvector, and full-text
|
|
30
|
+
search behind the same API. Both backends default to exact vector search;
|
|
31
|
+
approximate search is configurable.
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
Source text → event log → direct storage or LLM extraction → graph + indexes
|
|
35
|
+
|
|
36
|
+
Query → intent, entity, and time analysis
|
|
37
|
+
→ graph, vector, lexical, and recent-memory candidates
|
|
38
|
+
→ deterministic scoring and filtering
|
|
39
|
+
→ token-bounded context with provenance
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- **Ingestion:** `store()` writes a memory directly without an LLM.
|
|
43
|
+
`ingest()` extracts entities, facts, and relationships through a configured
|
|
44
|
+
provider. Deferred ingestion records durable work that can resume after restart.
|
|
45
|
+
- **Memory state:** typed nodes carry owner, scope, lifecycle, confidence,
|
|
46
|
+
validity windows, and source references. Explicit corrections and contradiction
|
|
47
|
+
operations preserve earlier claims; automatic store-time supersedence is opt-in.
|
|
48
|
+
- **Retrieval:** combines multiple search paths and packs selected evidence into
|
|
49
|
+
context. Structured assertion-state and aggregation APIs support exact stored
|
|
50
|
+
claim queries and decimal totals beyond semantic top-k retrieval.
|
|
51
|
+
- **Default retrieval behavior:** candidates are ranked by reciprocal rank
|
|
52
|
+
fusion of their semantic and lexical ranks, with a recency boost on
|
|
53
|
+
current-state questions and an event-time tie-break. Packing uses balanced
|
|
54
|
+
ordering and renders each record as one plain line (the `reader` context
|
|
55
|
+
format), while the full records stay in the bundle's sections and the
|
|
56
|
+
retrieval receipt. These defaults changed after v0.12.0;
|
|
57
|
+
[Default retrieval settings](docs/PACKING.md#default-retrieval-settings)
|
|
58
|
+
lists the earlier values and the environment variables that restore them.
|
|
59
|
+
- **Organizer:** maintains promotion, decay, summaries, deduplication, archival,
|
|
60
|
+
and index compaction. It runs opportunistically or through `prme organize`;
|
|
61
|
+
recurring schedules use an external timer. Shared stores should pass `user_id`.
|
|
62
|
+
- **Workspaces:** `MemoryWorkspace` manages named local packs or PostgreSQL
|
|
63
|
+
schemas with identity checks and scoped leases.
|
|
64
|
+
|
|
65
|
+
A local memory pack is a directory by default, or one file when you opt in:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
my_memories/ # directory pack (the default)
|
|
69
|
+
├── memory.duckdb
|
|
70
|
+
├── vectors.usearch
|
|
71
|
+
├── lexical_index/
|
|
72
|
+
└── manifest.json # only when encryption is on
|
|
73
|
+
|
|
74
|
+
memories.prme # single-file pack (opt-in)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Giving `MemoryClient` a path that ends in `.prme`, or setting `PRME_PACK_PATH`,
|
|
78
|
+
selects the single-file layout: one DuckDB file holds the event log, the graph,
|
|
79
|
+
the vector snapshot and a pack manifest, and the lexical index is rebuilt in
|
|
80
|
+
memory when the pack opens. `prme migrate` copies a directory pack into a new
|
|
81
|
+
`.prme` file, and [single-file packs](docs/INTEGRATION.md#single-file-packs)
|
|
82
|
+
covers encryption, compaction and how retrieval compares across the layouts.
|
|
83
|
+
|
|
84
|
+
Search indexes can be regenerated from the durable graph with `prme rebuild`.
|
|
85
|
+
Event time, ingestion time, and validity time remain distinct. The `knowledge_at`
|
|
86
|
+
filter applies an ingestion cutoff to current graph/index state; exact historical
|
|
87
|
+
state replay is not currently available.
|
|
88
|
+
|
|
89
|
+
## Current benchmarks
|
|
90
|
+
|
|
91
|
+
| Benchmark | Correct answers | Answer accuracy |
|
|
92
|
+
|---|---:|---:|
|
|
93
|
+
| LongMemEval-S | 453 / 500 | **90.6%** |
|
|
94
|
+
| LoCoMo, non-adversarial questions | 1,250 / 1,540 | **81.2%** |
|
|
95
|
+
|
|
96
|
+
### LongMemEval-S by question type
|
|
97
|
+
|
|
98
|
+
| Question type | Correct answers | Answer accuracy |
|
|
99
|
+
|---|---:|---:|
|
|
100
|
+
| Single-session user | 69 / 70 | 98.6% |
|
|
101
|
+
| Single-session assistant | 54 / 56 | 96.4% |
|
|
102
|
+
| Knowledge update | 71 / 78 | 91.0% |
|
|
103
|
+
| Temporal reasoning | 120 / 133 | 90.2% |
|
|
104
|
+
| Single-session preference | 26 / 30 | 86.7% |
|
|
105
|
+
| Multi-session | 113 / 133 | 85.0% |
|
|
106
|
+
|
|
107
|
+
### LoCoMo by question type
|
|
108
|
+
|
|
109
|
+
| Question type | Correct answers | Answer accuracy |
|
|
110
|
+
|---|---:|---:|
|
|
111
|
+
| Single-hop | 756 / 841 | 89.9% |
|
|
112
|
+
| Temporal | 256 / 321 | 79.8% |
|
|
113
|
+
| Multi-hop | 182 / 282 | 64.5% |
|
|
114
|
+
| Open-domain | 56 / 96 | 58.3% |
|
|
115
|
+
|
|
116
|
+
Measured on September 25, 2026 with the v0.13.0 retrieval defaults and a
|
|
117
|
+
3,996-token memory-context budget per question, over memory packs built with
|
|
118
|
+
`store()`, which never runs extraction. The defaults adopted on October 6
|
|
119
|
+
change what `ingest()` stores and how repeated text is packed, so they were
|
|
120
|
+
measured on a separate track over packs built through `ingest()`. See
|
|
121
|
+
[BENCHMARKS.md](BENCHMARKS.md) for both tracks, the method, earlier results
|
|
122
|
+
and reproducibility artifacts.
|
|
123
|
+
|
|
124
|
+
## Installation
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
pip install prme
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Optional integrations:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install "prme[postgres]" # PostgreSQL backend
|
|
134
|
+
pip install "prme[api]" # HTTP API
|
|
135
|
+
pip install "prme[mcp]" # MCP server
|
|
136
|
+
pip install "prme[langchain]" # LangChain retriever and chat history
|
|
137
|
+
pip install "prme[llamaindex]" # LlamaIndex retriever and chat store
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Quickstart
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from prme import MemoryClient
|
|
144
|
+
|
|
145
|
+
with MemoryClient("./my_memories") as memory:
|
|
146
|
+
memory.store("Alice prefers dark mode in her editors.", user_id="alice")
|
|
147
|
+
memory.store("The team decided to use PostgreSQL.", user_id="alice")
|
|
148
|
+
|
|
149
|
+
response = memory.retrieve("What are Alice's preferences?", user_id="alice")
|
|
150
|
+
for result in response.results:
|
|
151
|
+
print(f"[{result.composite_score:.3f}] {result.node.content}")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`MemoryClient` is synchronous; `MemoryEngine` provides the async API. Direct
|
|
155
|
+
storage and retrieval use local embeddings by default and require no LLM API key.
|
|
156
|
+
Use `ingest()` with an OpenAI, Anthropic, or Ollama extraction provider when you
|
|
157
|
+
want structured memories extracted from conversation text.
|
|
158
|
+
|
|
159
|
+
Configure PRME through `PRMEConfig`, `PRME_` environment variables, or a `.env`
|
|
160
|
+
file. Constructor values override the environment, which overrides `.env`.
|
|
161
|
+
The [configuration reference](documentation/configuration.md) lists the
|
|
162
|
+
settings and their defaults. To return to the v0.12.0 retrieval defaults, set
|
|
163
|
+
`PRME_SCORING__FUSION=weighted`, `PRME_PACKING__CONTEXT_FORMAT=auditable` and
|
|
164
|
+
`PRME_PACKING__MULTIPATH_ORDERING=balanced` (the last is the default again and
|
|
165
|
+
only makes it explicit; see
|
|
166
|
+
[Default retrieval settings](docs/PACKING.md#default-retrieval-settings)).
|
|
167
|
+
See the [integration reference](docs/INTEGRATION.md) and
|
|
168
|
+
[examples](examples/) for configuration and application patterns.
|
|
169
|
+
|
|
170
|
+
## Interfaces and tools
|
|
171
|
+
|
|
172
|
+
Use the CLI to initialize, inspect, search, and maintain a local pack:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
prme init ./my_memories
|
|
176
|
+
prme doctor ./my_memories
|
|
177
|
+
prme search ./my_memories/memory.duckdb "Alice's preferences" --user-id alice
|
|
178
|
+
prme organize ./my_memories/memory.duckdb --user-id alice
|
|
179
|
+
prme compact ./my_memories/memory.duckdb
|
|
180
|
+
prme migrate ./my_memories ./memories.prme
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`prme compact` rewrites a closed pack file to give back the space DuckDB never
|
|
184
|
+
returns, and `prme migrate` copies a directory pack into a new single-file pack,
|
|
185
|
+
leaving the directory in place. Every command that takes `memory.duckdb` also
|
|
186
|
+
takes a `.prme` file, and `prme init ./memories.prme` creates one. See the
|
|
187
|
+
[CLI reference](documentation/cli.md).
|
|
188
|
+
|
|
189
|
+
For a local assistant, install the MCP extra and run with a fixed owner:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
PRME_MCP_USER_ID=alice prme-mcp --db-path ./my_memories
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`--db-path` also accepts a single-file pack, such as `./memories.prme`.
|
|
196
|
+
|
|
197
|
+
The HTTP extra provides a FastAPI service via `python -m prme.api`, which binds to
|
|
198
|
+
`127.0.0.1` and refuses a network bind without API credentials (see
|
|
199
|
+
[Running the Server](documentation/http-api.md#running-the-server)).
|
|
200
|
+
Shared HTTP deployments bind owners to credentials through `PRME_API_USER_KEYS`;
|
|
201
|
+
MCP Streamable HTTP uses its separate `PRME_MCP_USER_KEYS` setting.
|
|
202
|
+
See the [HTTP guide](docs/HTTP-API.md) and
|
|
203
|
+
[framework integration guide](docs/FRAMEWORK-INTEGRATIONS.md) for application setup.
|
|
204
|
+
|
|
205
|
+
To browse stored entries and explore their graph connections from a source
|
|
206
|
+
checkout, run `uv run --extra api python -m web.server` and open
|
|
207
|
+
**http://127.0.0.1:8080**. The standalone [memory explorer](web/README.md) lives in
|
|
208
|
+
`web/` and includes filters, source evidence, and an interactive relationship map.
|
|
209
|
+
|
|
210
|
+
## Milestones
|
|
211
|
+
|
|
212
|
+
| Milestone | Delivered |
|
|
213
|
+
|---|---|
|
|
214
|
+
| Core memory foundation, through v0.9 | Event sourcing, typed graph, hybrid retrieval, organizer jobs, encryption, CLI, evaluation harness, and index rebuilds |
|
|
215
|
+
| v0.10 | Deterministic vector search, batched ingestion indexing, and context-budget enforcement |
|
|
216
|
+
| v0.11 | Tenant-scoped maintenance, ownership and retrieval-filter fixes, and broader backend CI coverage |
|
|
217
|
+
| v0.12 | Durable ingestion and recovery, atomic lifecycle and correction records, scoped workspaces, structured assertion and quantity operations, retrieval receipts, and evaluated ranking profiles |
|
|
218
|
+
| v0.13 | Rank fusion with current-state recency, the one-line reader context format and balanced ordering as retrieval defaults; conversation participants with speaker names; refusal of unauthenticated network binds for the HTTP API; an offline evidence gate and paired answer runs for measuring retrieval changes |
|
|
219
|
+
| v0.14, current | A claim's own sentences as its text, a named speaker's I, me and my bound to the speaker, and each source text packed once, as `ingest()` and reader context defaults; repeated extracted claims merged into one current record; a browser memory explorer; benchmark packs built through `ingest()`, with the evidence gate and a DeepSeek answer track over them |
|
|
220
|
+
|
|
221
|
+
Experimental reranking (including the cross-encoder rank order), temporal-relation
|
|
222
|
+
guidance, model-assisted verification, temporal-first query intent, event-time
|
|
223
|
+
recency for the weighted formula, session context packing, windowed extraction,
|
|
224
|
+
self-contained fact text and speaker grounding remain opt-in.
|
|
225
|
+
Detailed changes are in the [changelog](CHANGELOG.md).
|
|
226
|
+
|
|
227
|
+
Current work follows [epic #77](https://github.com/dwamianm/prism/issues/77),
|
|
228
|
+
which acts on the 2026-09-23 benchmark gap audit: a reader-facing context,
|
|
229
|
+
better ranking, the context budget, and dated facts extracted at write time for
|
|
230
|
+
multi-hop and list questions. See the [roadmap](ROADMAP.md) for what has been
|
|
231
|
+
delivered and what is still open.
|
|
232
|
+
|
|
233
|
+
Images and video as memory sources are
|
|
234
|
+
[RFC-0018](docs/RFC-0018-Visual-Memory.md). Its phase 1 is implemented and
|
|
235
|
+
off by default: with `vision.enabled` set, `MemoryClient.observe()` and
|
|
236
|
+
`prme observe` turn a photo or a saved video into dated observation events
|
|
237
|
+
described by a local vision model, with a thumbnail of each keyframe kept in
|
|
238
|
+
the pack for provenance. The benchmark with real recordings is still open.
|
|
239
|
+
|
|
240
|
+
## Documentation
|
|
241
|
+
|
|
242
|
+
- [Developer guides](documentation/README.md) and [configuration reference](documentation/configuration.md)
|
|
243
|
+
- [Architecture and RFC index](docs/INDEX.md)
|
|
244
|
+
- [Integration reference](docs/INTEGRATION.md) and [framework adapters](docs/FRAMEWORK-INTEGRATIONS.md)
|
|
245
|
+
- [Context packing and default retrieval settings](docs/PACKING.md) and [retrieval feedback and learning](docs/LEARNING.md)
|
|
246
|
+
- [Experimental retrieval policies](docs/EXPERIMENTAL-RETRIEVAL-POLICIES.md)
|
|
247
|
+
- [Memory corrections](docs/MEMORY-CORRECTIONS.md)
|
|
248
|
+
- [Entity profiles](docs/ENTITY-PROFILES.md) and [entity identity](docs/ENTITY-IDENTITY.md)
|
|
249
|
+
- [Workspaces](docs/WORKSPACES.md) and [local resource control](docs/LOCAL-RESOURCES.md)
|
|
250
|
+
- [Custom embeddings](docs/CUSTOM-EMBEDDINGS.md) and [typed value bindings](docs/VALUE-BINDINGS.md)
|
|
251
|
+
- [HTTP API](docs/HTTP-API.md)
|
|
252
|
+
|
|
253
|
+
## Development
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
git clone https://github.com/dwamianm/prism.git
|
|
257
|
+
cd prism
|
|
258
|
+
uv sync --dev
|
|
259
|
+
uv run pytest tests/ -q
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
PostgreSQL tests require a live database configured through
|
|
263
|
+
`PRME_TEST_DATABASE_URL`. See [CONTRIBUTING.md](CONTRIBUTING.md) for development
|
|
264
|
+
setup, checks, and contribution guidelines.
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
Apache License 2.0 — see [LICENSE](LICENSE).
|