method=vector over episodes never reads the episode vector column — it depends entirely on atomic_fact
Los mantenedores suelen responder en 1 día
Ya se ha fusionado un pull request relacionado.
- #509 de @gloryfromca — fusionado
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 45/100
Línea de trabajo
Start in memory/search/manager.py at the single-route branch where fusion_mode is None: KEYWORD goes to sparse_recall, while VECTOR goes to _maxsim_atomic_recall and never reaches EpisodeRecaller.dense_recall. Reproduce by running method=vector against a store with episodes but an empty atomic_fact table and confirming zero results. Done when the maintainers settle whether to fall back to dense_recall or log the empty case, and the chosen behaviour is covered by a test.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
POST /api/v2/memory/search with method="vector" does not run a dense search over the episode table. It routes through _maxsim_atomic_recall, which does ANN over atomic_fact, max-pools by memcell, and fetches the parent episodes. So when atomic_fact is empty or stale, method=vector returns zero episodes with HTTP 200 — while every episode carries a perfectly usable 1024-dim body vector that is never consulted, and method=keyword over the same store answers normally.
Where
memory/search/manager.py, the single-route branch (fusion_mode is None, around line 405):
if req.method == SearchMethod.KEYWORD:
cands = await self._ep.sparse_recall(...)
else:
cands = await self._maxsim_atomic_recall(req, where, top_k) # VECTOR lands here
EpisodeRecaller.dense_recall (the method that does query episode.vector) exists and is wired, but nothing on the method=vector path calls it for the episode kind.
Observed
EverOS 1.4.1 at a345d08, isolated root, 106 daily-log Markdown files / 1060 episode entries, all indexed, embeddings healthy.
episode rows = 1060 (vector: non-null, dim=1024; subject_vector: non-null, dim=1024)
atomic_fact rows = 0
Same query, three methods:
| method | episodes returned |
|---|---|
keyword |
5 |
vector |
0 |
hybrid |
5 |
No error, no log line, HTTP 200 with an empty array. Replaying dense_search's own query chain against the live table — nearest_to(v).column("vector").distance_type("cosine").nprobes(32) — returns 5 rows with _distance=0.2726, so the data, the index and the repo layer are all fine. hybrid returning 5 is not reassurance: its sparse leg carries those hits, so the dead dense leg is masked.
To be explicit about my setup: my atomic_fact table was empty because the corpus was materialised with EverOS's own EpisodeWriter rather than by running the OME extraction strategy. A store built normally through /add + /flush will have facts. The defect is not that I got 0 — it is that this configuration of a healthy index yields a silent 0 at all.
Why it matters beyond the test setup
Any store whose atomic_fact table is empty, lagging or broken loses vector search silently, while keyword keeps working — so the deployment looks half-alive rather than broken. Reachable states include:
- #434 — a sub-1024-dim embedding provider makes
atomic_factwrites fail terminally (retryable=FALSE) while/healthstill reportsembed: true. That lands exactly here. - A root re-indexed from Markdown where episodes are present but fact extraction has not caught up (facts are derived by an OME strategy, asynchronously, after the episode lands).
- Any deployment running with the extraction strategy disabled.
In each case the user-visible result is "vector recall quietly returns nothing", which in a memory system is indistinguishable from "nothing matched".
Questions for a maintainer
- Is the atomic-fact-only route intended for
method=vector? The docstring describes it as trading an extra ANN scan for finer-grained semantic match, which is a reasonable ranking choice — but it reads as an enrichment, not as the sole source of dense recall. - If intended, should it fall back? An empty or short
atomic_factpool could fall through toEpisodeRecaller.dense_recallrather than returning nothing. - Either way, it should not be silent. A dense route that recalls zero candidates because its backing table is empty deserves a log line at minimum, and arguably a
reasonsentry on/healthonce the fact table is empty while episodes exist.
Related: #434 (the most likely way to reach this state in production), #394 (the other case of a documented dense-search knob not doing what the docs say).
- Lenguaje dominante
- Python
- Estrellas
- 13.3k
- Forks
- 926
- Merge medio
- 17 h 8 min
- PR fusionados (30 d)
- 32
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de EverMind-AI/EverOS
-
Dificultad 2/5 Medio día Aptitud para principiantes 62/100
EverMind-AI/EverOS#414 ·
Los mantenedores suelen responder en 1 día
-
[Offer] Free independent recomputation of your published memory benchmarks (assayed-tier upgrade)Abierto
Dificultad 4/5 1-2 días Aptitud para principiantes 3/100
EverMind-AI/EverOS#504 ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
EverMind-AI/EverOS#501 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 55/100
EverMind-AI/EverOS#498 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
EverMind-AI/EverOS#485 ·
Los mantenedores suelen responder en 1 día
Todos los issues de EverMind-AI/EverOS
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
ok-oldking/ok-wuthering-waves#1785 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
healthchecks/healthchecks#1349 ·
-
deployment release-lag
Dificultad 1/5 Menos de una hora Aptitud para principiantes 68/100
nolte/kamerplanter#2374 ·
Los mantenedores suelen responder en 1 día
-
bug v1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
modelcontextprotocol/python-sdk#3725 ·
Los mantenedores suelen responder en 1 día
-
batchterms() drops queries without a similar() clause, misaligning results with inputsPosiblemente ocupada @MohammadHijjawi97 la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
Los mantenedores suelen responder en 1 día