echo-mem 0.5.1__tar.gz → 0.5.2__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.1/src/echo_mem.egg-info → echo_mem-0.5.2}/PKG-INFO +1 -1
- {echo_mem-0.5.1 → echo_mem-0.5.2}/pyproject.toml +1 -1
- {echo_mem-0.5.1 → echo_mem-0.5.2/src/echo_mem.egg-info}/PKG-INFO +1 -1
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/retrieval/query_memory.py +68 -23
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/server.py +46 -7
- {echo_mem-0.5.1 → echo_mem-0.5.2}/LICENSE +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/LICENSE-APACHE-2.0 +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/README.md +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/setup.cfg +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_mem.egg-info/SOURCES.txt +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_mem.egg-info/dependency_links.txt +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_mem.egg-info/entry_points.txt +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_mem.egg-info/requires.txt +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_mem.egg-info/top_level.txt +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/audit/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/audit/get_audit_log.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/adopt.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/analyse.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/benchmark.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/calibrate.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/connect.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/dashboard.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/dashboard_html.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/export.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/graph.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/health.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/hooks.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/initdb.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/install.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/judge.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/main.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/merge.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/queue.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/quickstart.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/reattribute.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/reattribute_cmd.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/recall.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/reconcile.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/reindex.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/session_start.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/skill.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/status.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/stop_gate.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/trial.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/unmerge.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/cli/why.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/client.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/eval/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/eval/independent.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/eval/retrieval.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/eval/sweep.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/graph/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/graph/communities.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/infra/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/infra/config.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/infra/db.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/infra/logging.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/infra/pool.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/infra/project.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/activity.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/bootstrap.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/capture.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/embeddings.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/neighbourhood.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/resolution.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/ingestion/write_episode.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/env.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0001_initial_schema.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0002_trial_observations.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0003_project_and_agent_provenance.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0004_bootstrap_state.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0005_recall_save_guards.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0006_project_analysis.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0007_backfill_unknown_agent.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0008_read_events.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0009_read_event_attribution.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0010_stop_gate_fired.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0011_backfill_absent_agent.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0012_read_event_agent.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0013_active_fact_indexes.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0014_session_activity.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0015_retracted_observations.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0016_one_node_per_name.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0017_writer_version.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0018_trial_runs_are_history.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0019_versions_expected_since.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0020_who_closed_a_queued_document.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0021_delivery_evidence.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0022_independent_evaluation.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0023_second_judge.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0024_node_by_id.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/retrieval/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/retrieval/causality.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/retrieval/fusion.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/skill/SKILL.md +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/trial/__init__.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/trial/check.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/trial/observations.py +0 -0
- {echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/trial/reads.py +0 -0
|
@@ -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.2"
|
|
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
|
|
@@ -562,33 +562,68 @@ def _provenance(raw, agent_id, project) -> dict | None:
|
|
|
562
562
|
return out
|
|
563
563
|
|
|
564
564
|
|
|
565
|
+
def _missing_similarity(
|
|
566
|
+
conn, group_id: str, embedding: list[float], edge_ids: list[str]
|
|
567
|
+
) -> dict[str, float]:
|
|
568
|
+
"""Cosine for facts the vector channel never scored.
|
|
569
|
+
|
|
570
|
+
The lexical channel computes no similarity, so a fact only it found
|
|
571
|
+
arrived with score null. That is an implementation detail - which channel
|
|
572
|
+
happened to retrieve it - leaking into a field callers read as relevance.
|
|
573
|
+
|
|
574
|
+
Fixed by computing the number instead of omitting it. At most top_k rows,
|
|
575
|
+
by primary key, with the query embedding already in hand.
|
|
576
|
+
"""
|
|
577
|
+
if not edge_ids:
|
|
578
|
+
return {}
|
|
579
|
+
rows = conn.execute(
|
|
580
|
+
"""SELECT fe.edge_id::text, -(fe.embedding <#> %s::vector)
|
|
581
|
+
FROM public.fact_embedding fe
|
|
582
|
+
WHERE fe.group_id = %s
|
|
583
|
+
AND fe.edge_id = ANY(SELECT unnest(%s::text[])::graphid)""",
|
|
584
|
+
(embedding, group_id, list(edge_ids)),
|
|
585
|
+
).fetchall()
|
|
586
|
+
return {str(edge_id): float(score) for edge_id, score in rows}
|
|
587
|
+
|
|
588
|
+
|
|
565
589
|
def _annotate(
|
|
566
590
|
facts: list[dict], similarity: dict[str, float],
|
|
567
591
|
vector_ids: set[str], lexical_ids: set[str],
|
|
568
592
|
) -> None:
|
|
569
593
|
"""Say why each fact is in the answer, in place.
|
|
570
594
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
595
|
+
rank position in this answer, 1 first. THIS is the ordering to
|
|
596
|
+
trust and the one to truncate by. It is the fused result of
|
|
597
|
+
every channel, which is the system's whole opinion; score is
|
|
598
|
+
one input to it, and re-sorting by a single input discards
|
|
599
|
+
the fusion.
|
|
600
|
+
score cosine similarity to the query. Present on every fact of
|
|
601
|
+
every answer the MCP surface can ask for, and it means the
|
|
602
|
+
same thing for every fact whatever channel found it.
|
|
603
|
+
Diagnostic, NOT a correctness gate: a fact found by exact
|
|
604
|
+
keyword match can be the right answer at a low semantic
|
|
605
|
+
score.
|
|
606
|
+
|
|
607
|
+
Absent in exactly one place, and not one a tool caller can
|
|
608
|
+
reach: the UserPromptSubmit hook runs lexical_only in a fresh
|
|
609
|
+
process precisely to avoid a 6.2 second model load, so there
|
|
610
|
+
is no embedding to compare against and no honest number to
|
|
611
|
+
give. Omitted rather than faked.
|
|
612
|
+
matched which channels found it, as information rather than quality.
|
|
613
|
+
|
|
614
|
+
The null that used to appear here caused real harm and the shape of it is
|
|
615
|
+
worth keeping. score was omitted for lexical-only facts, a customer sorted
|
|
616
|
+
by score with nulls last, and every fact full text search had found went
|
|
617
|
+
to the back of the list - where a character budget truncated it and the
|
|
618
|
+
model filled the gap by inventing something. The fact it dropped was
|
|
619
|
+
correct and was in the store.
|
|
620
|
+
|
|
621
|
+
Their own calibration says why that is backwards. Over ten questions with
|
|
622
|
+
every fact judged against every question: lexical-only scored R@3 0.640
|
|
623
|
+
against vector-only's 0.460, and beat the fused ranking outright on two of
|
|
624
|
+
the ten. The channel that was being demoted has the better recall.
|
|
625
|
+
|
|
626
|
+
Absent on a digest too, which ranks nothing against nothing.
|
|
592
627
|
"""
|
|
593
628
|
for position, fact in enumerate(facts, start=1):
|
|
594
629
|
edge_id = fact["fact_id"]
|
|
@@ -599,7 +634,8 @@ def _annotate(
|
|
|
599
634
|
if not matched:
|
|
600
635
|
continue
|
|
601
636
|
fact["rank"] = position
|
|
602
|
-
|
|
637
|
+
if edge_id in similarity:
|
|
638
|
+
fact["score"] = round(similarity[edge_id], 4)
|
|
603
639
|
fact["matched"] = matched
|
|
604
640
|
|
|
605
641
|
|
|
@@ -653,6 +689,7 @@ def query_memory(
|
|
|
653
689
|
return {"error": str(e)}
|
|
654
690
|
|
|
655
691
|
similarity: dict[str, float] = {}
|
|
692
|
+
query_embedding: list[float] | None = None
|
|
656
693
|
if digest:
|
|
657
694
|
ranked_ids = _digest_candidates(conn, group_id, top_k)
|
|
658
695
|
vector_ids, lexical_ids = [], []
|
|
@@ -661,7 +698,7 @@ def query_memory(
|
|
|
661
698
|
lexical_ids = _lexical_any_candidates(conn, group_id, query, LIST_DEPTH)
|
|
662
699
|
ranked_ids = lexical_ids[:top_k]
|
|
663
700
|
else:
|
|
664
|
-
embedding = embedder.embed(query)
|
|
701
|
+
embedding = query_embedding = embedder.embed(query)
|
|
665
702
|
vector_ids = _vector_candidates(
|
|
666
703
|
conn, group_id, embedding, LIST_DEPTH, floor=floor, scores=similarity
|
|
667
704
|
)
|
|
@@ -732,6 +769,14 @@ def query_memory(
|
|
|
732
769
|
|
|
733
770
|
facts_by_id = _fetch_facts(conn, ranked_ids)
|
|
734
771
|
facts = [facts_by_id[edge_id] for edge_id in ranked_ids if edge_id in facts_by_id]
|
|
772
|
+
# Score whatever the vector channel did not, so every returned fact has
|
|
773
|
+
# one. Only on the query path: a digest ranks nothing and has no query to
|
|
774
|
+
# be similar to.
|
|
775
|
+
if query_embedding is not None:
|
|
776
|
+
unscored = [f["fact_id"] for f in facts if f["fact_id"] not in similarity]
|
|
777
|
+
similarity.update(
|
|
778
|
+
_missing_similarity(conn, group_id, query_embedding, unscored)
|
|
779
|
+
)
|
|
735
780
|
_annotate(facts, similarity, set(vector_ids), set(lexical_ids))
|
|
736
781
|
|
|
737
782
|
log_query_memory(
|
|
@@ -5,6 +5,7 @@ Runs over stdio by default (mcp.server.mcpserver's MCPServer.run default),
|
|
|
5
5
|
not a network listener at all, let alone one bound beyond localhost; see
|
|
6
6
|
the design doc's Constraints ("v1 is single-user, local-only")."""
|
|
7
7
|
|
|
8
|
+
import atexit
|
|
8
9
|
import inspect
|
|
9
10
|
import json
|
|
10
11
|
import threading
|
|
@@ -106,6 +107,30 @@ def startup(config: Config | None = None, embedder: Embedder | None = None) -> N
|
|
|
106
107
|
# a background task turns into confusing output somewhere else.
|
|
107
108
|
_state.warming = threading.Thread(target=_warm, args=(warm,), daemon=True)
|
|
108
109
|
_state.warming.start()
|
|
110
|
+
# Wait for it at exit, briefly, rather than letting the interpreter
|
|
111
|
+
# tear down underneath it.
|
|
112
|
+
#
|
|
113
|
+
# A daemon thread is killed abruptly at shutdown. This one is inside
|
|
114
|
+
# torch when that happens, and killing a thread mid C++ produces
|
|
115
|
+
# "terminate called without an active exception" and SIGABRT - exit
|
|
116
|
+
# code 134, after every test has already passed. CI saw exactly that:
|
|
117
|
+
# 771 passed, 5 skipped, then aborted. It is timing dependent, so it
|
|
118
|
+
# is rare on a machine with the model cached and common on one
|
|
119
|
+
# downloading it, which is the wrong way round for a release gate.
|
|
120
|
+
#
|
|
121
|
+
# Bounded, because the point of loading in the background is that
|
|
122
|
+
# nothing waits for it. A load still running after this long is one
|
|
123
|
+
# the process was never going to benefit from anyway.
|
|
124
|
+
atexit.register(_finish_warming)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
WARM_SHUTDOWN_GRACE_SECONDS = 10.0
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _finish_warming() -> None:
|
|
131
|
+
warming = getattr(_state, "warming", None)
|
|
132
|
+
if warming is not None and warming.is_alive():
|
|
133
|
+
warming.join(timeout=WARM_SHUTDOWN_GRACE_SECONDS)
|
|
109
134
|
|
|
110
135
|
|
|
111
136
|
def _warm(warm) -> None:
|
|
@@ -119,8 +144,16 @@ def _warm(warm) -> None:
|
|
|
119
144
|
"embedder_warm",
|
|
120
145
|
extra={"duration_ms": (time.perf_counter() - started) * 1000},
|
|
121
146
|
)
|
|
122
|
-
except Exception: # see docstring
|
|
123
|
-
|
|
147
|
+
except Exception: # noqa: BLE001 - see docstring
|
|
148
|
+
# Logging can itself fail here, and does: a thread still running while
|
|
149
|
+
# the interpreter shuts down finds the log stream closed and atexit
|
|
150
|
+
# refusing new registrations, so reporting the first failure raises a
|
|
151
|
+
# second one out of a thread with nowhere to put it. The report is
|
|
152
|
+
# best effort; the swallow is the contract in the docstring.
|
|
153
|
+
try:
|
|
154
|
+
_logger.warning("embedder_warm_failed", exc_info=True)
|
|
155
|
+
except Exception: # noqa: BLE001, S110 - nowhere left to report to
|
|
156
|
+
pass
|
|
124
157
|
|
|
125
158
|
|
|
126
159
|
def _tool(fn):
|
|
@@ -254,11 +287,17 @@ def query_memory(scope: str, query: str | None = None, top_k: int = 10, digest:
|
|
|
254
287
|
facts instead, as an opt-in "catch me up" convenience; call it
|
|
255
288
|
explicitly at session start if you want one, it's never automatic.
|
|
256
289
|
|
|
257
|
-
Each fact carries rank (1 first), score and matched.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
290
|
+
Each fact carries rank (1 first), score and matched.
|
|
291
|
+
|
|
292
|
+
If you must drop facts to fit a budget, drop by rank. It is the fused
|
|
293
|
+
result of every channel, which is this server's whole opinion; score is
|
|
294
|
+
one input to it, and re-sorting by a single input throws the rest away.
|
|
295
|
+
|
|
296
|
+
score is cosine similarity to your query, present on every fact and
|
|
297
|
+
comparable across queries. It is diagnostic, not a correctness test: a
|
|
298
|
+
fact found by exact keyword match can be the right answer at a low
|
|
299
|
+
score. matched names the channels that found it, as information - full
|
|
300
|
+
text search is not the weaker one, it has the better recall here.
|
|
262
301
|
|
|
263
302
|
A pending_ingest field appears when memory files have been written that
|
|
264
303
|
the graph hasn't heard about yet. Read each listed file and call
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0001_initial_schema.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0002_trial_observations.py
RENAMED
|
File without changes
|
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0004_bootstrap_state.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0005_recall_save_guards.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0006_project_analysis.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0007_backfill_unknown_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0009_read_event_attribution.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0010_stop_gate_fired.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0011_backfill_absent_agent.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0012_read_event_agent.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0013_active_fact_indexes.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0014_session_activity.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0015_retracted_observations.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0016_one_node_per_name.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0017_writer_version.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0018_trial_runs_are_history.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0021_delivery_evidence.py
RENAMED
|
File without changes
|
{echo_mem-0.5.1 → echo_mem-0.5.2}/src/echo_memory/migrations/versions/0022_independent_evaluation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|