mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-10-16 06:59:02 +08:00
Long-term memory chose its candidates before it looked at the question. Recall listed 400 items by `importance DESC, valid_from DESC`, loaded the vectors belonging to that list, and scored those; extraction did the same with a 200-item pool. Importance is uncorrelated with relevance, so the vector stage could only re-order what importance had already picked, and a memory below the cut was unreachable no matter how well it matched. The capacity cap goes up to 2000, so everything past the 400th most important memory was permanently unrecallable, and `memory_item_embeddings.vector` being a BYTEA blob meant pgvector was never involved. The store now answers "which of this person's memories is this question about": - Migration 000095 (and the SQLite mirror) add `embedding halfvec` plus a `(tenant_id, subject_id, model_id, dims)` index. The column is conditional on the vector extension, so a deployment whose retrieval driver excludes postgres keeps working. No HNSW: an approximate index is filtered after the fact, and one subject holds at most a couple of thousand rows, so exact ordering inside the scope is both correct and a few milliseconds. - `SearchItemsByVector` ranks in SQL over every vector the subject has, with the status, expiry and kind filters joined in so reaching past the candidate list cannot reach past the filters. SQLite and pgvector-less PostgreSQL fall back to scoring in process, still over the whole scope. - Recall fuses the lexical ranking with those hits and grows the candidate pool with matches the pool did not hold, which is what lets the search escape it. The lexical pool is now the capacity cap, so it can no longer be a second, invisible limit under the one that decides what stays active. - Extraction picks the memories it shows the model the same way. This matters more than recall: the memory a new statement contradicts is not reliably an important one, so an importance-ordered window hid exactly the collision that stops a duplicate being written. - Vectors are written to the searchable column in the upsert's transaction; rows predating the column are moved by `SyncVectorColumn` during maintenance, which costs no model calls. The embedding backfill goes from 50 to 200 per run — at 50, a subject at the capacity cap took over a month to become fully searchable. - Traces and logs report `outside_pool`, the number of semantic matches the lexical pool did not contain. It was structurally zero before, so it is the number to watch when asking whether semantic recall does anything. Tests cover whole-scope ranking, the lifecycle and kind filters, pool growth, the pool-size invariant, and extraction seeing a low-importance memory it would otherwise duplicate. A pgvector integration test (WEKNORA_MEMORY_TEST_POSTGRES_DSN) exercises the migration, the halfvec write, the SQL ranking and the column sync.
2 lines
41 B
SQL
2 lines
41 B
SQL
DROP INDEX IF EXISTS idx_mem_emb_search;
|