method=vector over episodes never reads the episode vector column — it depends entirely on atomic_fact
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 45/100
調査の方向性
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.
索引モデルが issue の本文から書いたものです。
説明
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).
- 主要言語
- Python
- スター
- 13.3k
- フォーク
- 926
- 平均マージ
- 17時間 40分
- マージ済み PR(30日)
- 31
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
EverMind-AI/EverOS のほかの issue
-
難易度 2/5 半日 初心者へのやさしさ 62/100
EverMind-AI/EverOS#414 ·
メンテナーはふだん 1 日以内に返信
-
[Offer] Free independent recomputation of your published memory benchmarks (assayed-tier upgrade)オープン
難易度 4/5 1〜2日 初心者へのやさしさ 3/100
EverMind-AI/EverOS#504 ·
メンテナーはふだん 1 日以内に返信
-
enhancement
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
EverMind-AI/EverOS#501 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
EverMind-AI/EverOS#498 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
EverMind-AI/EverOS#485 ·
メンテナーはふだん 1 日以内に返信
EverMind-AI/EverOS の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
PolicyEngine/policyengine-us#10262 ·
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
kellyjonbrazil/jc#788 ·
メンテナーはふだん 2 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
`/search.json` ignores the documented `editions.sort` parameter対応中かも @PranavD2905 が今日担当しました。 オープンAffects: Server Good First Issue Module: Solr Needs: Triage Theme: Public APIs Theme: Search
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
internetarchive/openlibrary#13989 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug P2: misleading query
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
jeffknupp/association#478 ·