Skip to content

feat(abi): embeddings/pooling through the ONE surface — LlamaModel arch, PoolingRunner in the engine step, vllm_embed (ABI v15), live /v1/embeddings - #137

Closed
localai-bot wants to merge 1 commit into
mainfrom
row/EMBEDDINGS-ONE-SURFACE
Closed

feat(abi): embeddings/pooling through the ONE surface — LlamaModel arch, PoolingRunner in the engine step, vllm_embed (ABI v15), live /v1/embeddings#137
localai-bot wants to merge 1 commit into
mainfrom
row/EMBEDDINGS-ONE-SURFACE

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

ONE-SURFACE fold ROW 6 (task #285, row ARCH-ONE-SURFACE leaf).

The engine-side pooler (ENG-POOLER-SEQ / ENG-POOLING-RUNNER) exists but is never invoked live. This row folds it onto the one surface:

  • W1 registry+runner: register LlamaModel (upstream _EMBEDDING_MODELS, registry.py:230, as_embedding_model adapters.py:230) with is_pooling_model=true; the engine step routes pooling-model batches through the landed PoolingRunner instead of the sampler (model_runner.py:368-369, 1586-1607; scheduler.py:1718-1721). Refuse-by-task both directions.
  • W2 ABI: vllm_embed + vllm_embedding_result(_free), VLLM_ABI_VERSION 14→15, floor pin advanced, strict-C references.
  • W3 server: live /v1/embeddings (OpenAI shape), task-conditional registration, socket-level 404 pins both directions.
  • W4 guard/records: abi-capability-allowlist embeddings row removed (leaves 1: mm-input); FEATURES row → reachable; spec ROW 6 progress; records.

Correctness anchor: the pooling lane's cosine gate extended with a registry-path arm — the engine-path vectors must be IDENTICAL to the direct PoolingRunner path and match the double-precision LAST+normalize reference, on a committed tiny synthetic LlamaModel fixture (the #121 precedent). Real-checkpoint re-verification is a named residual.

Spec: .agents/specs/embeddings-one-surface.md

🤖 Generated with Claude Code

https://claude.ai/code/session_014fZAcg1WcU8V629k6HWKys

…oling arch, PoolingRunner in the engine step, vllm_embed (ABI v15), live /v1/embeddings

ARCH-ONE-SURFACE fold ROW 6 (task #285, branch row/EMBEDDINGS-ONE-SURFACE,
PR #137). The engine-side pooler
(ENG-POOLER-SEQ ops + ENG-POOLING-RUNNER PoolingRunner) is now INVOKED
LIVE through one path: vllm_engine_load on a pooling checkpoint ->
LLMEngine::embed -> scheduler -> GPUModelRunner::pool_tokens -> pooled
vector, driven identically by vllm_embed (ABI v15) and the live
task-conditional /v1/embeddings.

W1 registry+runner: NEW arch LlamaModel (llama_embedding_registry.cpp,
is_pooling_model=true) — the mirror of _EMBEDDING_MODELS
"LlamaModel": ("llama", "LlamaForCausalLM") (registry.py:230) +
as_embedding_model (adapters.py:230): the SHARED dense backbone to the
post-final-norm hidden with NO lm_head (Qwen3DenseModel::ForwardHidden,
additive tail; text callers byte-identical); loader accepts both name
layouts (adapters.py:178-181) and never loads lm_head. The runner
builds a PoolingRunner iff the registration declares pooling
(model_runner.py:368-369) and sample_tokens routes to pool_tokens()
(model_runner.py:1586-1607); validity == the discard predicate
(pooling_runner.py:40-41); scheduler pooling stop at the marked
DEFERRED site (scheduler.py:1718-1721); pooling_output out through
EngineCoreOutput/RequestOutput; async scheduling OFF for pooling
models (config/vllm.py:1068-1073 — the landed ResolveAsyncScheduling
arm now WIRED). Every hook task-gated on is_pooling_model /
pooling_params: default nullopt/false = byte-identical text path
(engine suites re-run green).

W2 ABI: vllm_embed + vllm_embedding_result_free, VLLM_ABI_VERSION
14 -> 15, floor pin >= 15; strict-C references; dlopen symbols;
refuse-by-task BOTH directions; FIXED en route: v13's
vllm_complete_tokens shipped without the v11 task guard (null-deref
on a transcription handle).

W3 server: handle_embeddings (OpenAI shape, embed/protocol.py:34,
173-185) registered ONLY when an embedder is attached; server main
dispatches pooling archs to a serving-less embedding server;
socket-level 404 pins BOTH directions.

W4 guard/records: abi-capability-allowlist embeddings row REMOVED
(1 left: mm-input); FEATURES row -> reachable; ARCH_TOKEN_RE widened
to bare *Model; the routing checker gains the POOLING classification;
runnable-baseline re-pinned; SERVE-POOLING-ENDPOINTS and
MODEL-EMBED-llama-llama-for-causal-lm rows ACTIVE;
STATUS/BENCHMARKS/NOW/state updated.

Correctness anchor: the pooling lane's cosine gate re-anchored THROUGH
the registry/runner path on the COMMITTED deterministic fixture
(scripts/mm/llama_embed_fixture_gen.py): test_llama_embedding_fold
4/4-231 — direct registry path == f64 LAST+normalize reference,
FULL-ENGINE path == direct path IDENTICAL vectors, chunked-prefill
is_valid arm — plus test_capi 48/48-462 (real fixture-checkpoint load
through the public ABI), test_dlopen 30/30, server suite 50/50,
registry 24/24-820. 9 mutation kills (floor pin, refusals both
directions, route gating both ways, engine-step invocation, scheduler
stop, registry info pin, async-off wire). Residual: REAL embedding
checkpoint (e5-mistral class) + the LLM(task="embed") oracle cosine —
no cosine-vs-oracle number fabricated.

FOLLOWING_AGENTS_PROTOCOL
Assisted-by: Claude Code:claude-fable-5 [ClaudeCode]
@mudler
mudler force-pushed the row/EMBEDDINGS-ONE-SURFACE branch from fde0a29 to e4c29b3 Compare August 8, 2026 08:34
@localai-bot
localai-bot marked this pull request as ready for review August 8, 2026 08:34
@localai-bot

Copy link
Copy Markdown
Collaborator Author

Implementation complete at e4c29b3 (rebased onto main e484a63; keyed records re-applied on main wholesale).

Gates (CPU): fold gate test_llama_embedding_fold 4/4 cases / 231 asserts (direct registry path == f64 LAST+normalize reference; FULL-ENGINE path == direct path IDENTICAL vectors; chunked-prefill is_valid arm) · test_capi 48/48 / 462 (v15 floor pin, real fixture-checkpoint load through the public ABI, refuse-both-directions, argument contract) · test_dlopen 30/30 · test_openai_api_server 50/50 / 624 (embeddings shape + socket smoke + BOTH-direction 404 pins) · test_model_registry 24/24 / 820 · engine suites green (scheduler 423, llm_engine 204, engine_core 44, output_processor 77, qwen3_forward 1557, async_llm 342, llama_forward 509, loaded_engine_dense 65, scheduler_config 32, pooling_runner 14) · checker mutation suites green (routing 31, supported-models+surface-coverage 57) · scripts/agent-preflight.sh EXIT=0, all gates green.

Mutation kills (each RED then reverted, 9): ABI floor 15→14 (floor pin RED) · embed-on-text refusal deleted (capi RED ×3) · generation-on-pooling refusal deleted (refusal case hangs → SIGTERM FAILURE) · if (embedder_)if (true) (text-server 404 pin RED) · generate route unconditional (embedding-server 404 pin RED) · engine-step pooling invocation deleted (fold gate RED ×2 cases) · scheduler pooling stop deleted (fold RED) · registry is_pooling_model=false (registry pin 819/820 + fold ×6 RED) · async-off wire dropped (fold engine arm RED + CHECK_FALSE(async) pin).

Allowlist diff: scripts/abi-capability-allowlist.txt embeddings/pooling row REMOVED — 1 row remains (multimodal input). example-abi-allowlist/ratchet UNTOUCHED (no example changes).

Residuals (honest): REAL embedding checkpoint (e5-mistral class) + vllm.LLM(task="embed").encode oracle cosine (committed synthetic fixture is the gate, the #121 precedent — no cosine-vs-oracle number fabricated); other _EMBEDDING_MODELS memberships (incl. MistralModel); /pooling+score/rerank/classify; matryoshka dimensions/base64/token-array inputs; vllm_embed batches sequentially through the synchronous engine (recorded deviation).

Note for the reviewer: the brief's premise that the pooling lane's gate ran "vs recorded oracle fixtures" was inaccurate — the existing gate is structural (double-precision reference; the qwen36_embed goldens are token-embedding LOOKUP goldens). Per the brief's own contingency, the gate was EXTENDED with the registry-path identity arm.

mudler added a commit that referenced this pull request Aug 8, 2026
…ch, PoolingRunner live, vllm_embed at ABI v15, /v1/embeddings (#137)

ONE-SURFACE fold ROW 6, the last capability fold before mm-input. The
pooling machinery that existed engine-side but was never invoked live
now runs through every surface: LlamaModel registered
is_pooling_model=true (the _EMBEDDING_MODELS registry.py:230 +
as_embedding_model adapters.py:230 mirror; bare-prefix no-lm_head
loader; Qwen3DenseModel::ForwardHidden additive tail), PoolingRunner
built iff pooling model and invoked task-gated in sample_tokens ->
pool_tokens (model_runner.py:1586-1607 mirror), scheduler pooling stop
at the previously-DEFERRED site, async scheduling off for pooling
(config/vllm.py:1068-1073). vllm_embed + vllm_embedding_result_free at
VLLM_ABI_VERSION 14->15 floor-pinned; task-conditional /v1/embeddings
(OpenAI shape) with both-direction socket-level 404 pins; capability
allowlist down to exactly ONE row (mm-input). LAST-pool + normalize
matches upstream defaults verbatim. Adjacent fix: v13's
vllm_complete_tokens shipped without the task guard - a confirmed
pre-existing null-deref/hang on transcription handles, now guarded and
pinned.

Review: fresh mutation review MERGE-CLEAN - every engine-step/scheduler
touch verified gated with the text path byte-identical (ungated
mutations red the text suites), both refusal guards load-bearing
(removal reproduces real HANGS), the fold gate's engine-vs-direct arms
independently killable, all upstream cites verbatim, fixture
regeneration byte-stable. One minor observation recorded for the next
row: the routing checker's NONE bucket silently absorbs pooling
registrations (its CI-bound mutation suite holds the pin). Operator:
fold/capi/dlopen/server/scheduler/llm_engine 6/6 SUCCESS on the merged
tree; nine record gates green; FEATURES conflict composed (embeddings
row from this PR, ROCm row from main's newer community-verified state).

FOLLOWING_AGENTS_PROTOCOL
Assisted-by: Claude Code:claude-fable-5 [ClaudeCode]
@localai-bot

Copy link
Copy Markdown
Collaborator Author

Landed on main as 57ed063 (mudler-authored squash, lease-guarded verified push). Fresh mutation review MERGE-CLEAN: every engine-step/scheduler pooling branch verified gated (text path byte-identical; ungated mutations red the text suites), both refusal guards load-bearing (removal reproduces real hangs), fold-gate arms independently killable, upstream cites verbatim, fixture byte-stable. Operator gates on the merged tree: six suites 6/6 SUCCESS, nine record gates green, FEATURES conflict composed with main's newer ROCm state. Embeddings are now embedder-reachable end-to-end: LlamaModel registry arch, live PoolingRunner, vllm_embed at ABI v15, /v1/embeddings. The capability tracker is at ONE remaining row (mm-input). The adjacent v13 vllm_complete_tokens guard fix rode along (confirmed pre-existing hang). Residuals as recorded: real-checkpoint cosine oracle, classify/score heads, matryoshka/base64 inputs, batched vllm_embed.

@localai-bot localai-bot closed this Aug 8, 2026
richiejp added a commit to richiejp/vllm.cpp that referenced this pull request Aug 8, 2026
Record the merged Gemma-4 MoE path as known merged-GEMM drift and close the stale embeddings claim after PR mudler#137 landed.

FOLLOWING_AGENTS_PROTOCOL

Assisted-by: Codex:gpt-5.6-sol [Codex]
richiejp added a commit to richiejp/vllm.cpp that referenced this pull request Aug 8, 2026
Record the merged Gemma-4 MoE path as known merged-GEMM drift and close the stale embeddings claim after PR mudler#137 landed.

FOLLOWING_AGENTS_PROTOCOL

Assisted-by: Codex:gpt-5.6-sol [Codex]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants