Archived
feat(engram): semantic search layer via nomic-embed-text (cosine ∪ lexical) #67
Closed
will.anderson
wants to merge 0 commits from
feat/engram-semantic-search into hotfix/elc-fixes
pull from: feat/engram-semantic-search
merge into: :hotfix/elc-fixes
:main
:stage
:dev
:fix/runtime-stack-on-dev
:fix/runtime-growth-guard
:fix/runtime-shim-retire
:fix/runtime-extract-text
:feat/el-speaks
:wire/write-realizes-signal
:fix/singleton-guards-the-state
:fix/transduce-decomposition
:design/correspondence-and-censorship
:docs/correspondence-and-ownership-2026-08-16
:fix/geometry-readable
:docs/builtin-recipe-gate
:fix/sigpipe
:feat/grounding-gradient
:fix/utf8-truncation
:fix/ground-echo-and-self
:fix/think-stance
:fix/cross-cutting-concerns
:feat/el-geometry-transduce
:fix/awareness-thread-engram-race
:fix/think-anchor
:fix/geometry-ingest
:fix/state-get-leak
:wt/soul-runtime-reconcile
:fix/bool-is-int-like
:fix/eq-operand-inference
:fix/missing-import-is-an-error
:feat/alloc-accounting-containers
:fix/math-log-base10
:fix/compiler-quadratic-strlen
:feat/alloc-accounting
:fix/elc-rebuildable-compiler-builtins
:fix/engram-query-param-and-seed-link
:merge-pr103-v2
:merge-swarm-ccr-v2
:feat/engram-ggml-cosine-batch
:improve/ggml-cosine-fp32-and-init
:fix/nsbx-tooling-hardening
:feat/transduce-unify
:fix/engram-search-latency-reconciled
:feat/engram-metal-cosine-batch
:feat/reframe-region-setop
:worktree-agent-a1bb8ac67d9006e08
:feat/neuron-sandbox
:worktree-agent-af50f3458d7754f19
:worktree-agent-acc02900ef4ade35e
:worktree-agent-aaf04b0a9714c4070
:worktree-agent-a6577c8211c332c5b
:worktree-agent-a6177cda24c71d1df
:worktree-agent-a55d5c2d0e8f2c88b
:worktree-agent-a7e7a591a07291058
:worktree-agent-a456e0cf8cd2ee361
:worktree-agent-a0dc4a33cf5558d4e
:worktree-agent-ac2381b0b9615ab20
:wt/swarm-ccr
:integration/langfaculty-20260814
:feat/nsbx-dev-env
:stage-elp-native-lang
:docs/operator-naming-convention
:stage-elp-lang-consolidation
:stage-elp-es-port
:engram-tiered-storage
:feat/engram-reseed-route
:feat/el-route-decorators
:test/dev-ci-baseline
:fix/cgi-identity-emission-clean
:fix/cgi-identity-emission
:reconcile/el-cluster-windows-runtime
:fix/durable-response-truncation
:fix/engram-lexical-tokenized-search
:fix/http-fs-read-len
:hotfix/ci-stage-main-publish-hardening
:hotfix/ci-dev-publish-hardening
:hotfix/stage-elc-engram-integration
:feat/ranked-engram-search
:hotfix/win-runtime-portability
:hotfix/runtime-engram-get-node-by-label
:feat/engram-semantic-search
:hotfix/elc-fixes
:hotfix/el-runtime-leak-and-persist
:integrate/local-main-commits
:fix/runtime-load-merge-2026-06-30
:fix/windows-rusage-guard
:fix/http-response-truncation
:salvage/tim-wip-presync-20260625
:feat/windows-el-runtime
:fix/runtime-integrity-reconcile
:fix/engram-save-atomic-darwin
:chore/live-darwin-runtime
:feat/wm-api-and-http-serve-async
:fix/engram-node-full-field-corruption
:fix/llm-model-and-utf8
:fix/elb-monolithic-link
:fix/ci-gcloud-install-order
:fix/native-test-precompile-runtime
:fix/ci-base-dev-first-run
:fix/elc-parser-elb-build
:fix/elc-oom-checkout
:fix/css-str-join-separator
:fix/html-template-if-style-script
:fix/elb-gcc-bracket-depth
:fix/ci-openssl-linker
:feat/ci-hook-test
:feat/native-testing
:runtime/integrate
:fix/http-serve-1-arg-compat
:feat/el-html-templates
:feat/js-browser-runtime
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feat/engram-semantic-search"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Semantic search layer — nomic-embed-text (the upgrade beyond lexical)
Lexical
istr_containscan only match text that literally appears. It cannotsurface a node whose words never appear in the query but whose meaning
matches. This PR adds an optional dense-vector layer: node content and the
query are embedded via Ollama (
nomic-embed-text), ranked by cosinesimilarity, and unioned with lexical hits.
What changed (
el_runtime.c)A self-contained semantic block (embed client, FNV-1a-keyed in-memory vector
cache, cosine, one-shot probe) plus wiring into all three query entry
points — the routing reality is that
server.elcalls the_jsonbuiltins,so fixing only the internal twin would never reach
:8742:engram_search_json(HTTP/api/search): collect lexical ∪ semanticcandidates, score (lexical base
1.0 + cosine; pure-semantic= cosine),rank, emit top-N. Stable sort ⇒ byte-identical to old output when semantic
is off.
engram_search(internalel_val_ttwin): lexical ∪ semantic union.engram_activateseed loop (HTTP/api/activate): a node seeds if itlexically matches or clears the cosine threshold; pure-semantic seeds
enter scaled by cosine so a paraphrase spreads activation without
overpowering exact lexical seeds.
Degradable by design
The whole layer is gated on
HAVE_CURLand a runtime probe. If curl iscompiled out, Ollama is unreachable, or
ENGRAM_SEMANTIC=0, every entry pointyields zero semantic signal and callers fall back byte-for-byte to the
pre-existing lexical search. Verified against a dead endpoint and with the
flag off (see evidence).
Where vectors live
In-process cache keyed by node id, invalidated by an FNV-1a hash of content
(edited content re-embeds). The query is embedded once per call; the graph
is not re-embedded per query. nomic task prefixes
(
search_query:/search_document:) are applied — empirically they separatea paraphrase (0.72) cleanly from distractors (<0.48).
Config
ENGRAM_SEMANTIC(0disables),ENGRAM_EMBED_URL(def
http://localhost:11434/api/embeddings),ENGRAM_EMBED_MODEL(def
nomic-embed-text),ENGRAM_SEMANTIC_MIN(cosine threshold, def0.6).Build steps gain
-DHAVE_CURL(the engram artifact linked-lcurlbut neverdefined the guard, so the HTTP client + this layer were compiled out).
Evidence — rebuilt with
cc -DHAVE_CURL, run on:8797against a throwaway7-node snapshot (never touched live
:8742/:7770/~/.neuron):how are employee wages and salaries paidsem-payroll("Twice a month the organization transfers monetary compensation to its workforce…" — zero shared words)Will Andersonsem-willwindows msi signingsem-lexctlsem-payrollseeded at hops=0,act=0.5009(= salience 0.7 × cosine 0.716), spreads tosem-willENGRAM_SEMANTIC=00(pure lexical) — lexical queries still return0, server healthy, lexical still returnsCompiles clean with
-Wall -Wextraboth with and without-DHAVE_CURL.⚠️ Merge-order dependency — LEXICAL FIRST
This branch was cut from
hotfix/elc-fixesbefore the lexical tokenize+rankfix (
fix/engram-lexical-tokenized-search, commite3dabe3). Both branchesedit the same three match sites in
el_runtime.c. Merge the lexical PRfirst, then rebase this one. On rebase, the lexical predicate inside each
site (currently whole-query
istr_contains) should adopt the tokenized matcher— my changes wrap that predicate in
lex || sem, so reconciliation ismechanical. My semantic block, the ranking scaffold, and the
-DHAVE_CURLbuild flag are additive and independent of the lexical work.
Do not merge without the lexical PR landing first.
Documented as not-yet-done (partial scope, per brief)
cold process still pays O(N) embeds the first time each node is scanned. In
memory the cache already prevents per-query re-embedding.
is the next optimization). First semantic query on a large live graph will
be slow until warm — a boot-time warmup or persisted cache addresses this.
Lexical istr_contains alone can't surface a node whose words don't appear in the query. This adds an optional dense-vector layer: node content and the query are embedded through Ollama (nomic-embed-text), and nodes are ranked by cosine similarity unioned with lexical hits, so a paraphrase query reaches the right node. Wired into all three query entry points in el_runtime.c: - engram_search_json (HTTP /api/search): collect lexical ∪ semantic candidates, score (lexical base 1.0 + cosine; pure-semantic = cosine), rank, emit top-N. Stable sort preserves old order when semantic is off. - engram_search (internal el_val twin): lexical ∪ semantic union. - engram_activate seed loop (HTTP /api/activate): a node seeds if it lexically matches OR clears the cosine threshold; pure-semantic seeds enter scaled by cosine so paraphrase spreads without overpowering. Degradable by design: the whole layer is gated on HAVE_CURL plus a one-shot runtime probe. If curl is compiled out, Ollama is unreachable, or ENGRAM_SEMANTIC=0, every entry point yields zero semantic signal and callers fall back byte-for-byte to the pre-existing lexical search. Node embeddings are cached in process memory keyed by node id with an FNV-1a content hash for invalidation; the query is embedded once per call — so the graph is not re-embedded on every query. nomic task prefixes (search_query:/search_document:) are applied for retrieval separation. Build steps gain -DHAVE_CURL so the engram artifact compiles the layer in (-lcurl was already linked). Env: ENGRAM_SEMANTIC, ENGRAM_EMBED_URL, ENGRAM_EMBED_MODEL, ENGRAM_SEMANTIC_MIN (cosine threshold, default 0.6).Superseded by the reconciled el-cluster landing (feature #80 -> dev -> stage #81 -> main #82). Its content is included in that reconciled runtime now on the dev->stage->main chain. Closing to drive el open PRs to zero.