memvara 0.1.0__py3-none-any.whl
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.
- memvara/__init__.py +130 -0
- memvara/aio.py +670 -0
- memvara/compat/__init__.py +56 -0
- memvara/compat/_notes.py +183 -0
- memvara/compat/mem0.py +544 -0
- memvara/compat/mem0_import.py +569 -0
- memvara/consolidate/__init__.py +99 -0
- memvara/consolidate/decay.py +118 -0
- memvara/consolidate/merge.py +248 -0
- memvara/consolidate/sweep.py +141 -0
- memvara/core.py +2118 -0
- memvara/embed/__init__.py +35 -0
- memvara/embed/base.py +151 -0
- memvara/embed/fingerprint.py +147 -0
- memvara/embed/local.py +50 -0
- memvara/entities.py +446 -0
- memvara/integrations/__init__.py +85 -0
- memvara/integrations/_common.py +148 -0
- memvara/integrations/crewai.py +571 -0
- memvara/integrations/langchain.py +511 -0
- memvara/integrations/langgraph.py +948 -0
- memvara/integrations/llamaindex.py +369 -0
- memvara/llm/__init__.py +26 -0
- memvara/llm/_shape.py +242 -0
- memvara/llm/anthropic.py +155 -0
- memvara/llm/base.py +265 -0
- memvara/llm/openai.py +174 -0
- memvara/py.typed +0 -0
- memvara/redact.py +501 -0
- memvara/rerank/__init__.py +73 -0
- memvara/rerank/base.py +64 -0
- memvara/rerank/cross.py +105 -0
- memvara/rerank/lexical.py +130 -0
- memvara/rerank/stage.py +105 -0
- memvara/retrieve/__init__.py +45 -0
- memvara/retrieve/analyze.py +124 -0
- memvara/retrieve/calibrate.py +162 -0
- memvara/retrieve/fusion.py +71 -0
- memvara/retrieve/hybrid.py +842 -0
- memvara/retrieve/scoring.py +283 -0
- memvara/retrieve/traverse.py +678 -0
- memvara/schema.py +526 -0
- memvara/server/__init__.py +43 -0
- memvara/server/__main__.py +11 -0
- memvara/server/cli.py +102 -0
- memvara/server/config.py +259 -0
- memvara/server/mcp.py +209 -0
- memvara/server/protocol.py +99 -0
- memvara/server/tools.py +635 -0
- memvara/server/validate.py +143 -0
- memvara/store/__init__.py +11 -0
- memvara/store/base.py +806 -0
- memvara/store/sqlite.py +2837 -0
- memvara/telemetry.py +565 -0
- memvara/types.py +987 -0
- memvara/write/__init__.py +19 -0
- memvara/write/fast.py +288 -0
- memvara/write/gate.py +152 -0
- memvara/write/pipeline.py +757 -0
- memvara/write/reconcile.py +636 -0
- memvara-0.1.0.dist-info/METADATA +1403 -0
- memvara-0.1.0.dist-info/RECORD +65 -0
- memvara-0.1.0.dist-info/WHEEL +4 -0
- memvara-0.1.0.dist-info/entry_points.txt +2 -0
- memvara-0.1.0.dist-info/licenses/LICENSE +202 -0
memvara/__init__.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Memvara — bitemporal memory for AI agents.
|
|
2
|
+
|
|
3
|
+
What it does differently from mem0 and friends:
|
|
4
|
+
|
|
5
|
+
* **Facts are structured and bitemporal.** A memory is a `Claim` — a (subject, predicate,
|
|
6
|
+
object) triple carrying both when it was true in the world and when we believed it.
|
|
7
|
+
Two clocks, asked independently: `known_at=T` answers "what did we think in March?",
|
|
8
|
+
`valid_at=T` answers "what do we think *today* about how March was?", and `as_of=T`
|
|
9
|
+
moves both at once. The middle one is why the axes are separate — a correction that
|
|
10
|
+
arrives in August about June cannot be seen from a belief clock rewound to June.
|
|
11
|
+
* **Contradictions resolve deterministically.** A predicate schema says whether a
|
|
12
|
+
relation is single-valued, so a conflict is an indexed lookup on (subject, predicate)
|
|
13
|
+
rather than a top-k similarity search plus an LLM adjudication that may miss it.
|
|
14
|
+
* **The write path avoids the LLM.** Hash dedupe, near-duplicate detection, a salience
|
|
15
|
+
gate, and rule-based extraction run first; the model is consulted only for turns that
|
|
16
|
+
survive all of them, batched. `WriteReceipt.llm_calls` reports the cost every time.
|
|
17
|
+
With no `llm=` there is no fourth tier at all, so turns the rules do not recognise are
|
|
18
|
+
not stored — `Memvara()` warns once about that, and `WriteReceipt.unextracted` counts
|
|
19
|
+
it per write.
|
|
20
|
+
* **Retrieval is hybrid and time-aware.** BM25 fused with vector search, reranked by
|
|
21
|
+
recency decay tuned per predicate, and every result explains why it surfaced.
|
|
22
|
+
* **Nothing is silently lost.** Superseded facts are retired, never deleted, and every
|
|
23
|
+
claim traces back to the source turns via `why()`.
|
|
24
|
+
|
|
25
|
+
from memvara import Memvara
|
|
26
|
+
|
|
27
|
+
mem = Memvara("memory.db", user="alice")
|
|
28
|
+
mem.add("I live in Berlin and work at Acme")
|
|
29
|
+
mem.add("Actually I moved to Lisbon last month")
|
|
30
|
+
|
|
31
|
+
mem.search("where do they live?") # -> Lisbon
|
|
32
|
+
mem.history("user", "lives_in") # -> Berlin (retired), Lisbon (current)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
from .aio import AsyncMemvara, AsyncScopedMemvara
|
|
36
|
+
from .consolidate import Consolidator
|
|
37
|
+
from .entities import EntityRegistry, EntityResolution, EntitySpec, entity_key
|
|
38
|
+
from .redact import PatternRedactor, Redactor
|
|
39
|
+
from .core import (
|
|
40
|
+
DegradedExtractionWarning,
|
|
41
|
+
EmbedderChangedWarning,
|
|
42
|
+
EmbedderMismatchError,
|
|
43
|
+
Memvara,
|
|
44
|
+
ScopedMemvara,
|
|
45
|
+
)
|
|
46
|
+
from .embed import (
|
|
47
|
+
CachedEmbedder,
|
|
48
|
+
Embedder,
|
|
49
|
+
EmbedderFingerprint,
|
|
50
|
+
HashingEmbedder,
|
|
51
|
+
default_embedder,
|
|
52
|
+
)
|
|
53
|
+
from .llm import LLM, NullLLM
|
|
54
|
+
from .retrieve import (
|
|
55
|
+
HOP_DAMPING,
|
|
56
|
+
Edge,
|
|
57
|
+
EpisodeResult,
|
|
58
|
+
FloorReport,
|
|
59
|
+
GraphTraverser,
|
|
60
|
+
HybridRetriever,
|
|
61
|
+
Path,
|
|
62
|
+
Retrieved,
|
|
63
|
+
calibrate_min_score,
|
|
64
|
+
)
|
|
65
|
+
from .schema import Cardinality, PredicateRegistry, PredicateSpec, Volatility
|
|
66
|
+
from .store import SQLiteStore, Store
|
|
67
|
+
from .types import (
|
|
68
|
+
Claim,
|
|
69
|
+
Closure,
|
|
70
|
+
Derivation,
|
|
71
|
+
Episode,
|
|
72
|
+
Explanation,
|
|
73
|
+
MemoryType,
|
|
74
|
+
Provenance,
|
|
75
|
+
Result,
|
|
76
|
+
Scope,
|
|
77
|
+
WriteReceipt,
|
|
78
|
+
time_axes,
|
|
79
|
+
utcnow,
|
|
80
|
+
)
|
|
81
|
+
from .telemetry import MemoryRecorder, NullRecorder, Recorder
|
|
82
|
+
from .write import FastExtractor, Reconciler, SalienceGate, WritePipeline
|
|
83
|
+
from .write.reconcile import backfill_entities
|
|
84
|
+
|
|
85
|
+
__version__ = "0.1.0"
|
|
86
|
+
|
|
87
|
+
__all__ = [
|
|
88
|
+
"Memvara", "ScopedMemvara", "AsyncMemvara", "AsyncScopedMemvara",
|
|
89
|
+
# data model
|
|
90
|
+
"Claim", "Episode", "Scope", "Result", "Explanation", "Provenance",
|
|
91
|
+
"WriteReceipt", "MemoryType", "Derivation", "utcnow", "time_axes",
|
|
92
|
+
# Which clock a write stops when it ends a claim: "ended" (the world changed) or
|
|
93
|
+
# "retired" (the record was wrong). Exported because it is in `Reconciler.apply`'s
|
|
94
|
+
# signature and in four facade methods, so a typed caller needs to be able to name it.
|
|
95
|
+
"Closure",
|
|
96
|
+
# schema
|
|
97
|
+
"PredicateRegistry", "PredicateSpec", "Cardinality", "Volatility",
|
|
98
|
+
# pluggable backends
|
|
99
|
+
"Store", "SQLiteStore",
|
|
100
|
+
"Embedder", "HashingEmbedder", "CachedEmbedder", "default_embedder",
|
|
101
|
+
"EmbedderFingerprint",
|
|
102
|
+
"LLM", "NullLLM", "AnthropicLLM", "OpenAILLM",
|
|
103
|
+
# diagnostics: importable so they can be filtered or caught by category
|
|
104
|
+
"DegradedExtractionWarning", "EmbedderChangedWarning", "EmbedderMismatchError",
|
|
105
|
+
# subsystems
|
|
106
|
+
"WritePipeline", "SalienceGate", "FastExtractor", "Reconciler",
|
|
107
|
+
"HybridRetriever", "Retrieved", "EpisodeResult",
|
|
108
|
+
# multi-hop traversal. `Path` is a chain of claims, not a filesystem path.
|
|
109
|
+
"GraphTraverser", "Path", "Edge", "HOP_DAMPING",
|
|
110
|
+
"EntityRegistry", "EntityResolution", "EntitySpec", "entity_key",
|
|
111
|
+
"backfill_entities",
|
|
112
|
+
"Recorder", "NullRecorder", "MemoryRecorder",
|
|
113
|
+
"Redactor", "PatternRedactor", "Consolidator",
|
|
114
|
+
# relevance floors are measured per deployment, never assumed
|
|
115
|
+
"calibrate_min_score", "FloorReport",
|
|
116
|
+
"__version__",
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def __getattr__(name: str):
|
|
121
|
+
# Kept out of the eager imports so `import memvara` works with neither hosted SDK.
|
|
122
|
+
if name == "AnthropicLLM":
|
|
123
|
+
from .llm.anthropic import AnthropicLLM
|
|
124
|
+
|
|
125
|
+
return AnthropicLLM
|
|
126
|
+
if name == "OpenAILLM":
|
|
127
|
+
from .llm.openai import OpenAILLM
|
|
128
|
+
|
|
129
|
+
return OpenAILLM
|
|
130
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|