echo-mem 0.5.2__tar.gz → 0.5.3__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.
- {echo_mem-0.5.2/src/echo_mem.egg-info → echo_mem-0.5.3}/PKG-INFO +27 -8
- {echo_mem-0.5.2 → echo_mem-0.5.3}/README.md +26 -7
- {echo_mem-0.5.2 → echo_mem-0.5.3}/pyproject.toml +1 -1
- {echo_mem-0.5.2 → echo_mem-0.5.3/src/echo_mem.egg-info}/PKG-INFO +27 -8
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_mem.egg-info/SOURCES.txt +8 -0
- echo_mem-0.5.3/src/echo_memory/cli/infer_causal.py +737 -0
- echo_mem-0.5.3/src/echo_memory/cli/llm.py +132 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/main.py +160 -1
- echo_mem-0.5.3/src/echo_memory/eval/external.py +713 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/write_episode.py +7 -0
- echo_mem-0.5.3/src/echo_memory/migrations/versions/0025_lexical_statistics.py +72 -0
- echo_mem-0.5.3/src/echo_memory/migrations/versions/0026_late_causal_extraction.py +111 -0
- echo_mem-0.5.3/src/echo_memory/migrations/versions/0027_lexical_staleness_without_a_scan.py +47 -0
- echo_mem-0.5.3/src/echo_memory/retrieval/bm25.py +304 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/retrieval/query_memory.py +229 -20
- echo_mem-0.5.3/src/echo_memory/retrieval/salience.py +98 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/server.py +13 -2
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/skill/SKILL.md +6 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/LICENSE +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/LICENSE-APACHE-2.0 +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/setup.cfg +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_mem.egg-info/dependency_links.txt +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_mem.egg-info/entry_points.txt +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_mem.egg-info/requires.txt +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_mem.egg-info/top_level.txt +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/audit/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/audit/get_audit_log.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/adopt.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/analyse.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/benchmark.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/calibrate.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/connect.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/dashboard.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/dashboard_html.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/export.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/graph.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/health.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/hooks.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/initdb.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/install.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/judge.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/merge.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/queue.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/quickstart.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/reattribute.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/reattribute_cmd.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/recall.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/reconcile.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/reindex.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/session_start.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/skill.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/status.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/stop_gate.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/trial.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/unmerge.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/cli/why.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/client.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/eval/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/eval/independent.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/eval/retrieval.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/eval/sweep.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/graph/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/graph/communities.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/infra/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/infra/config.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/infra/db.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/infra/logging.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/infra/pool.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/infra/project.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/activity.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/bootstrap.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/capture.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/embeddings.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/neighbourhood.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/ingestion/resolution.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/env.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0001_initial_schema.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0002_trial_observations.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0003_project_and_agent_provenance.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0004_bootstrap_state.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0005_recall_save_guards.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0006_project_analysis.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0007_backfill_unknown_agent.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0008_read_events.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0009_read_event_attribution.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0010_stop_gate_fired.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0011_backfill_absent_agent.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0012_read_event_agent.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0013_active_fact_indexes.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0014_session_activity.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0015_retracted_observations.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0016_one_node_per_name.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0017_writer_version.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0018_trial_runs_are_history.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0019_versions_expected_since.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0020_who_closed_a_queued_document.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0021_delivery_evidence.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0022_independent_evaluation.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0023_second_judge.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/migrations/versions/0024_node_by_id.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/retrieval/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/retrieval/causality.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/retrieval/fusion.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/trial/__init__.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/trial/check.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/trial/observations.py +0 -0
- {echo_mem-0.5.2 → echo_mem-0.5.3}/src/echo_memory/trial/reads.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: echo-mem
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: A long-horizon memory architecture for AI agents
|
|
5
5
|
License-Expression: BUSL-1.1
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -94,6 +94,8 @@ echo-memory export # everything, as JSON
|
|
|
94
94
|
echo-memory install --for cursor # wire one client, project scoped
|
|
95
95
|
echo-memory adopt # wire every MCP client on the machine, each with its own id
|
|
96
96
|
|
|
97
|
+
echo-memory infer-causal-hints # type the facts whose own sentence states a cause (dry run)
|
|
98
|
+
|
|
97
99
|
echo-memory eval # retrieval quality against your own store
|
|
98
100
|
echo-memory eval --context # what a recall costs against injecting everything
|
|
99
101
|
echo-memory eval --context --sweep # the same, as a curve across corpus size
|
|
@@ -138,13 +140,30 @@ this happen" is an ordered chain and similarity cannot produce one. "A led_to B"
|
|
|
138
140
|
caused_by A" are one claim written from opposite ends, and both assemble into the same
|
|
139
141
|
chain.
|
|
140
142
|
|
|
141
|
-
A fact with no hint is associative, which is the default and usually correct.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
A fact with no hint is associative, which is the default and usually correct. An empty
|
|
144
|
+
answer from `trace_cause` says which kind of empty it is: nobody recorded a cause here is
|
|
145
|
+
a different fact about a store than there are no chains.
|
|
146
|
+
|
|
147
|
+
**Filling it in, for a store that predates it.** Facts written before 0.5.0 carry no
|
|
148
|
+
hint, so on an existing store `trace_cause` has nothing to walk.
|
|
149
|
+
`echo-memory infer-causal-hints` re-reads the fact text already stored with your own
|
|
150
|
+
model (`ECHO_MEMORY_LLM_API_KEY`, `ECHO_MEMORY_LLM_MODEL`) and types the edges whose own
|
|
151
|
+
sentence states the relation. Dry run by default; `--write` applies what it printed and
|
|
152
|
+
`--clear --write` takes it back.
|
|
153
|
+
|
|
154
|
+
This is extraction done late, not causal discovery, and the difference is enforced rather
|
|
155
|
+
than promised. A sentence with no causal connective is never sent to a model, so
|
|
156
|
+
co-occurrence is refused before it costs anything. Every proposal has to quote the words
|
|
157
|
+
that state the relation, and a quote that is not literally in the fact is dropped, so a
|
|
158
|
+
model reasoning from the world instead of reading the sentence gets nothing stored. Each
|
|
159
|
+
hint written is audited and marked as extracted late, which is what makes `--clear`
|
|
160
|
+
able to remove exactly these and never one you wrote at write time.
|
|
145
161
|
|
|
146
162
|
**No inference on the write path.** Extraction happens in the calling agent, so storing
|
|
147
|
-
a memory invokes no model on the server.
|
|
163
|
+
a memory invokes no model on the server. `infer-causal-hints` above is not an exception
|
|
164
|
+
to that and is worth being precise about: it is a command a person types against facts
|
|
165
|
+
already stored, it never runs as part of a write, a migration or a hook, and a store that
|
|
166
|
+
never runs it never causes a model call. The cost moved rather than vanished: the agent
|
|
148
167
|
has to arrive with entities and facts already extracted, which is what the
|
|
149
168
|
[tool contract](docs/DEVELOPMENT.md) spells out. The comparison that makes this matter is
|
|
150
169
|
Zep/Graphiti, the closest architectural match, whose own description of ingestion is that
|
|
@@ -169,8 +188,8 @@ difference nobody sized is not a result.
|
|
|
169
188
|
|---|---|---|
|
|
170
189
|
| Context per recall vs injecting everything | **96.7% less**, hit@10 0.872 over 1,190 questions | `echo-memory eval --context` |
|
|
171
190
|
| The same saving across 8x of corpus growth | 75.5% at 32 facts rising to **96.4% at 261**, hit@10 0.900 to 0.946 | `echo-memory eval --context --sweep` |
|
|
172
|
-
| LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 **0.601**, hit@10 0.658, MRR 0.460 | `
|
|
173
|
-
| LongMemEval retrieval, 90 questions, 15 per type | session@10 **0.
|
|
191
|
+
| LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 **0.601**, hit@10 0.658, MRR 0.460, session@10 0.850 | `echo-memory eval-external locomo` |
|
|
192
|
+
| LongMemEval retrieval, 90 questions, 15 per type | session@10 **0.937**, recall@10 0.727, MRR 0.428 | `echo-memory eval-external longmemeval --per-type 15` |
|
|
174
193
|
| Server side model calls per write | **0** | `echo-memory benchmark` |
|
|
175
194
|
| Write, query, digest latency (median) | 15ms, 8ms, 1ms | `echo-memory benchmark` |
|
|
176
195
|
| Entity resolution AUC | 0.666, 95% CI [0.421, 0.881] | `echo-memory calibrate` |
|
|
@@ -71,6 +71,8 @@ echo-memory export # everything, as JSON
|
|
|
71
71
|
echo-memory install --for cursor # wire one client, project scoped
|
|
72
72
|
echo-memory adopt # wire every MCP client on the machine, each with its own id
|
|
73
73
|
|
|
74
|
+
echo-memory infer-causal-hints # type the facts whose own sentence states a cause (dry run)
|
|
75
|
+
|
|
74
76
|
echo-memory eval # retrieval quality against your own store
|
|
75
77
|
echo-memory eval --context # what a recall costs against injecting everything
|
|
76
78
|
echo-memory eval --context --sweep # the same, as a curve across corpus size
|
|
@@ -115,13 +117,30 @@ this happen" is an ordered chain and similarity cannot produce one. "A led_to B"
|
|
|
115
117
|
caused_by A" are one claim written from opposite ends, and both assemble into the same
|
|
116
118
|
chain.
|
|
117
119
|
|
|
118
|
-
A fact with no hint is associative, which is the default and usually correct.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
A fact with no hint is associative, which is the default and usually correct. An empty
|
|
121
|
+
answer from `trace_cause` says which kind of empty it is: nobody recorded a cause here is
|
|
122
|
+
a different fact about a store than there are no chains.
|
|
123
|
+
|
|
124
|
+
**Filling it in, for a store that predates it.** Facts written before 0.5.0 carry no
|
|
125
|
+
hint, so on an existing store `trace_cause` has nothing to walk.
|
|
126
|
+
`echo-memory infer-causal-hints` re-reads the fact text already stored with your own
|
|
127
|
+
model (`ECHO_MEMORY_LLM_API_KEY`, `ECHO_MEMORY_LLM_MODEL`) and types the edges whose own
|
|
128
|
+
sentence states the relation. Dry run by default; `--write` applies what it printed and
|
|
129
|
+
`--clear --write` takes it back.
|
|
130
|
+
|
|
131
|
+
This is extraction done late, not causal discovery, and the difference is enforced rather
|
|
132
|
+
than promised. A sentence with no causal connective is never sent to a model, so
|
|
133
|
+
co-occurrence is refused before it costs anything. Every proposal has to quote the words
|
|
134
|
+
that state the relation, and a quote that is not literally in the fact is dropped, so a
|
|
135
|
+
model reasoning from the world instead of reading the sentence gets nothing stored. Each
|
|
136
|
+
hint written is audited and marked as extracted late, which is what makes `--clear`
|
|
137
|
+
able to remove exactly these and never one you wrote at write time.
|
|
122
138
|
|
|
123
139
|
**No inference on the write path.** Extraction happens in the calling agent, so storing
|
|
124
|
-
a memory invokes no model on the server.
|
|
140
|
+
a memory invokes no model on the server. `infer-causal-hints` above is not an exception
|
|
141
|
+
to that and is worth being precise about: it is a command a person types against facts
|
|
142
|
+
already stored, it never runs as part of a write, a migration or a hook, and a store that
|
|
143
|
+
never runs it never causes a model call. The cost moved rather than vanished: the agent
|
|
125
144
|
has to arrive with entities and facts already extracted, which is what the
|
|
126
145
|
[tool contract](docs/DEVELOPMENT.md) spells out. The comparison that makes this matter is
|
|
127
146
|
Zep/Graphiti, the closest architectural match, whose own description of ingestion is that
|
|
@@ -146,8 +165,8 @@ difference nobody sized is not a result.
|
|
|
146
165
|
|---|---|---|
|
|
147
166
|
| Context per recall vs injecting everything | **96.7% less**, hit@10 0.872 over 1,190 questions | `echo-memory eval --context` |
|
|
148
167
|
| The same saving across 8x of corpus growth | 75.5% at 32 facts rising to **96.4% at 261**, hit@10 0.900 to 0.946 | `echo-memory eval --context --sweep` |
|
|
149
|
-
| LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 **0.601**, hit@10 0.658, MRR 0.460 | `
|
|
150
|
-
| LongMemEval retrieval, 90 questions, 15 per type | session@10 **0.
|
|
168
|
+
| LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 **0.601**, hit@10 0.658, MRR 0.460, session@10 0.850 | `echo-memory eval-external locomo` |
|
|
169
|
+
| LongMemEval retrieval, 90 questions, 15 per type | session@10 **0.937**, recall@10 0.727, MRR 0.428 | `echo-memory eval-external longmemeval --per-type 15` |
|
|
151
170
|
| Server side model calls per write | **0** | `echo-memory benchmark` |
|
|
152
171
|
| Write, query, digest latency (median) | 15ms, 8ms, 1ms | `echo-memory benchmark` |
|
|
153
172
|
| Entity resolution AUC | 0.666, 95% CI [0.421, 0.881] | `echo-memory calibrate` |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# (`-m echo_memory.server`) and every existing install reference it, and
|
|
7
7
|
# renaming the module would break live configuration to fix a cosmetic mismatch.
|
|
8
8
|
name = "echo-mem"
|
|
9
|
-
version = "0.5.
|
|
9
|
+
version = "0.5.3"
|
|
10
10
|
description = "A long-horizon memory architecture for AI agents"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
# BUSL-1.1 is the SPDX identifier for the Business Source License 1.1, so
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: echo-mem
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: A long-horizon memory architecture for AI agents
|
|
5
5
|
License-Expression: BUSL-1.1
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -94,6 +94,8 @@ echo-memory export # everything, as JSON
|
|
|
94
94
|
echo-memory install --for cursor # wire one client, project scoped
|
|
95
95
|
echo-memory adopt # wire every MCP client on the machine, each with its own id
|
|
96
96
|
|
|
97
|
+
echo-memory infer-causal-hints # type the facts whose own sentence states a cause (dry run)
|
|
98
|
+
|
|
97
99
|
echo-memory eval # retrieval quality against your own store
|
|
98
100
|
echo-memory eval --context # what a recall costs against injecting everything
|
|
99
101
|
echo-memory eval --context --sweep # the same, as a curve across corpus size
|
|
@@ -138,13 +140,30 @@ this happen" is an ordered chain and similarity cannot produce one. "A led_to B"
|
|
|
138
140
|
caused_by A" are one claim written from opposite ends, and both assemble into the same
|
|
139
141
|
chain.
|
|
140
142
|
|
|
141
|
-
A fact with no hint is associative, which is the default and usually correct.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
A fact with no hint is associative, which is the default and usually correct. An empty
|
|
144
|
+
answer from `trace_cause` says which kind of empty it is: nobody recorded a cause here is
|
|
145
|
+
a different fact about a store than there are no chains.
|
|
146
|
+
|
|
147
|
+
**Filling it in, for a store that predates it.** Facts written before 0.5.0 carry no
|
|
148
|
+
hint, so on an existing store `trace_cause` has nothing to walk.
|
|
149
|
+
`echo-memory infer-causal-hints` re-reads the fact text already stored with your own
|
|
150
|
+
model (`ECHO_MEMORY_LLM_API_KEY`, `ECHO_MEMORY_LLM_MODEL`) and types the edges whose own
|
|
151
|
+
sentence states the relation. Dry run by default; `--write` applies what it printed and
|
|
152
|
+
`--clear --write` takes it back.
|
|
153
|
+
|
|
154
|
+
This is extraction done late, not causal discovery, and the difference is enforced rather
|
|
155
|
+
than promised. A sentence with no causal connective is never sent to a model, so
|
|
156
|
+
co-occurrence is refused before it costs anything. Every proposal has to quote the words
|
|
157
|
+
that state the relation, and a quote that is not literally in the fact is dropped, so a
|
|
158
|
+
model reasoning from the world instead of reading the sentence gets nothing stored. Each
|
|
159
|
+
hint written is audited and marked as extracted late, which is what makes `--clear`
|
|
160
|
+
able to remove exactly these and never one you wrote at write time.
|
|
145
161
|
|
|
146
162
|
**No inference on the write path.** Extraction happens in the calling agent, so storing
|
|
147
|
-
a memory invokes no model on the server.
|
|
163
|
+
a memory invokes no model on the server. `infer-causal-hints` above is not an exception
|
|
164
|
+
to that and is worth being precise about: it is a command a person types against facts
|
|
165
|
+
already stored, it never runs as part of a write, a migration or a hook, and a store that
|
|
166
|
+
never runs it never causes a model call. The cost moved rather than vanished: the agent
|
|
148
167
|
has to arrive with entities and facts already extracted, which is what the
|
|
149
168
|
[tool contract](docs/DEVELOPMENT.md) spells out. The comparison that makes this matter is
|
|
150
169
|
Zep/Graphiti, the closest architectural match, whose own description of ingestion is that
|
|
@@ -169,8 +188,8 @@ difference nobody sized is not a result.
|
|
|
169
188
|
|---|---|---|
|
|
170
189
|
| Context per recall vs injecting everything | **96.7% less**, hit@10 0.872 over 1,190 questions | `echo-memory eval --context` |
|
|
171
190
|
| The same saving across 8x of corpus growth | 75.5% at 32 facts rising to **96.4% at 261**, hit@10 0.900 to 0.946 | `echo-memory eval --context --sweep` |
|
|
172
|
-
| LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 **0.601**, hit@10 0.658, MRR 0.460 | `
|
|
173
|
-
| LongMemEval retrieval, 90 questions, 15 per type | session@10 **0.
|
|
191
|
+
| LoCoMo retrieval, 1,982 questions, 5,882 turns | recall@10 **0.601**, hit@10 0.658, MRR 0.460, session@10 0.850 | `echo-memory eval-external locomo` |
|
|
192
|
+
| LongMemEval retrieval, 90 questions, 15 per type | session@10 **0.937**, recall@10 0.727, MRR 0.428 | `echo-memory eval-external longmemeval --per-type 15` |
|
|
174
193
|
| Server side model calls per write | **0** | `echo-memory benchmark` |
|
|
175
194
|
| Write, query, digest latency (median) | 15ms, 8ms, 1ms | `echo-memory benchmark` |
|
|
176
195
|
| Entity resolution AUC | 0.666, 95% CI [0.421, 0.881] | `echo-memory calibrate` |
|
|
@@ -25,9 +25,11 @@ src/echo_memory/cli/export.py
|
|
|
25
25
|
src/echo_memory/cli/graph.py
|
|
26
26
|
src/echo_memory/cli/health.py
|
|
27
27
|
src/echo_memory/cli/hooks.py
|
|
28
|
+
src/echo_memory/cli/infer_causal.py
|
|
28
29
|
src/echo_memory/cli/initdb.py
|
|
29
30
|
src/echo_memory/cli/install.py
|
|
30
31
|
src/echo_memory/cli/judge.py
|
|
32
|
+
src/echo_memory/cli/llm.py
|
|
31
33
|
src/echo_memory/cli/main.py
|
|
32
34
|
src/echo_memory/cli/merge.py
|
|
33
35
|
src/echo_memory/cli/queue.py
|
|
@@ -45,6 +47,7 @@ src/echo_memory/cli/trial.py
|
|
|
45
47
|
src/echo_memory/cli/unmerge.py
|
|
46
48
|
src/echo_memory/cli/why.py
|
|
47
49
|
src/echo_memory/eval/__init__.py
|
|
50
|
+
src/echo_memory/eval/external.py
|
|
48
51
|
src/echo_memory/eval/independent.py
|
|
49
52
|
src/echo_memory/eval/retrieval.py
|
|
50
53
|
src/echo_memory/eval/sweep.py
|
|
@@ -89,10 +92,15 @@ src/echo_memory/migrations/versions/0021_delivery_evidence.py
|
|
|
89
92
|
src/echo_memory/migrations/versions/0022_independent_evaluation.py
|
|
90
93
|
src/echo_memory/migrations/versions/0023_second_judge.py
|
|
91
94
|
src/echo_memory/migrations/versions/0024_node_by_id.py
|
|
95
|
+
src/echo_memory/migrations/versions/0025_lexical_statistics.py
|
|
96
|
+
src/echo_memory/migrations/versions/0026_late_causal_extraction.py
|
|
97
|
+
src/echo_memory/migrations/versions/0027_lexical_staleness_without_a_scan.py
|
|
92
98
|
src/echo_memory/retrieval/__init__.py
|
|
99
|
+
src/echo_memory/retrieval/bm25.py
|
|
93
100
|
src/echo_memory/retrieval/causality.py
|
|
94
101
|
src/echo_memory/retrieval/fusion.py
|
|
95
102
|
src/echo_memory/retrieval/query_memory.py
|
|
103
|
+
src/echo_memory/retrieval/salience.py
|
|
96
104
|
src/echo_memory/skill/SKILL.md
|
|
97
105
|
src/echo_memory/trial/__init__.py
|
|
98
106
|
src/echo_memory/trial/check.py
|