Skip to content

feat(recall): wire neural embeddings into the live persona path (#40) - #1715

Merged
joelteply merged 1 commit into
canaryfrom
feat/neural-recall-live
Jun 21, 2026
Merged

feat(recall): wire neural embeddings into the live persona path (#40)#1715
joelteply merged 1 commit into
canaryfrom
feat/neural-recall-live

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

What

The live persona recall path (build_workspace_cycleRecallFaculty)
hard-coded the lexical bootstrap embedder. Now it uses neural embeddings (via
unsloth's /v1/embeddings, #1714) when the embed model actually serves, and
falls back to lexical otherwise — personas get semantic recall, not just
word-overlap, the moment an embed model is available. Builds directly on
#1713 (startup auto-fuel) + #1714 (create_embedding).

resolve_recall_embedder(adapter)

  • Prefers neural, but probes it once with a one-shot embed. Usable probe
    (non-empty, non-zero, all-finite) → neural; empty/zero/NaN probe (model not
    loaded, endpoint error) → lexical fallback. This is the no-signal guard:
    without it, an adapter that advertises embedding support but has no embed model
    loaded would embed every memory into a zero vector and recall would return
    nothing — strictly worse than lexical.
  • Process-stable (decided once at spawn, never per-embed): a query and the
    stored vectors must share one embedding space, so neural and lexical are never
    mixed per call (cosine across spaces is meaningless).
  • Wrapped in the content-addressed CachingEmbeddingProvider — each message
    embedded once and shared across every persona (the latency win). Further
    perf is a later pass.
  • Always returns a working embedder — never errors/panics. A box with no
    embed model still gets real lexical relevance ("solve for public users").

Wiring

  • PersonaBrainConfig gains embedder: Option<Arc<dyn EmbeddingProvider>>;
    build_workspace_cycle uses it, defaulting to lexical+cache when None.
  • The live supervisor spawn sets it via resolve_recall_embedder(adapter).
  • CANONICAL_EMBED_MODEL = "qwen3-embedding-0.6b" (dim 1024), overridable via
    UNSLOTH_EMBED_MODEL — one embedding space across the grid.

Tests

7 new: the probe gate (usable vs no-signal), and the resolver picking neural when
the model serves / falling back on empty-probe / using lexical when the adapter
lacks embedding support.

Scope

Does not delete fastembed — that path (the separate IPC Hippocampus /
PersonaMemoryManager, real blast radius into ORM vector + search) is the
follow-up trim, deferred per "get it working first, optimize once healthy."

🤖 Generated with Claude Code

The live persona recall path (build_workspace_cycle → RecallFaculty) hard-coded
the lexical bootstrap embedder. Now it uses neural embeddings (via unsloth's
/v1/embeddings, landed last commit) when the embed model actually serves, and
falls back to lexical otherwise — so personas get semantic recall, not just
word-overlap, the moment an embed model is available.

resolve_recall_embedder(adapter):
- Prefers NeuralEmbeddingProvider (semantic) but PROBES it once with a one-shot
  embed. A usable probe (non-empty, non-zero, all-finite) → neural; an empty /
  zero / NaN probe (model not loaded, endpoint error) → lexical fallback. This
  is the no-signal guard: without it, an adapter that advertises embedding
  support but has no embed model loaded would embed every memory into a zero
  vector and recall would return nothing — strictly worse than lexical.
- The choice is PROCESS-STABLE (decided once at spawn, never per-embed): a query
  and the stored vectors must live in the SAME embedding space, so neural and
  lexical are never mixed per call (cosine across spaces is meaningless).
- Result is wrapped in the content-addressed CachingEmbeddingProvider — each
  message embedded ONCE and shared across every persona (the latency win; the
  embed model slug is the cache/space key). Further perf is a later pass.
- Always returns a working embedder — never errors/panics. A box with no embed
  model still gets real lexical relevance ("solve for public users").

Wiring:
- PersonaBrainConfig gains `embedder: Option<Arc<dyn EmbeddingProvider>>`;
  build_workspace_cycle uses it, defaulting to lexical+cache when None (harnesses).
- The live supervisor spawn sets it via resolve_recall_embedder(adapter).
- CANONICAL_EMBED_MODEL = "qwen3-embedding-0.6b" (dim 1024), overridable via
  UNSLOTH_EMBED_MODEL — one embedding space across the grid.

7 new tests: the probe gate (usable vs no-signal), and the resolver picking
neural when the model serves / falling back to lexical on empty-probe / using
lexical when the adapter lacks embedding support.

Scope: this does NOT delete fastembed — that path (the separate IPC Hippocampus
/ PersonaMemoryManager, with real blast radius into ORM vector + search) is the
follow-up trim, deferred per "get it working first, optimize once healthy."

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@joelteply
joelteply merged commit 5cf3578 into canary Jun 21, 2026
4 checks passed
@joelteply
joelteply deleted the feat/neural-recall-live branch June 21, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant