BUG: no embedding model concept — embeddings routed only to active chat model #38
Labels
No labels
blocked:lint-failed
blocked:needs-decision
blocked:no-changes
blocked:no-procedure
blocked:preflight
blocked:verify-failed
bug
feature-request
in-progress
lint-cleanup
ops-task
quickfix
security/high
security/medium
test-coverage
triage-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/vllm_mm#38
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Summary
vllm_mm has no concept of model type (chat vs embedding). The proxy's
/v1/embeddingsendpoint routes to whatever model is currentlyis_active=True, which is expected to be a chat model. There is no way to register, load, or route to a dedicated embedding model. llama.cpp's llama-server supports--embeddingmode at startup for embedding-only models, but vllm_mm never wires this in.The VRAM profiler already has a
can_fit(required_gb)method intended to check if a secondary embedding model can fit alongside the chat model — but nothing in the request flow ever calls it.What's missing
Model type field:
modelstable (SQLite) has nomodel_typecolumn or equivalent. All registered models are implicitly chat models.Embedding-specific settings:
llamacpp_backend.pybuild_subprocess_commanddoes not include--embedding,--pooling, or any embedding-mode flags.Endpoint routing:
proxy.py:927-944(/v1/embeddings) only looks atis_active=True. There's no concept of an "active embedding model" separate from the "active chat model."Concurrent loading UI: Users cannot register an embedding-only model (e.g.,
nomic-embed-text-v1.5-Q8_0.gguf~130MB) and have it stay loaded alongside the chat model. The UI'sadd-edit-model-dialog.tsxhas no field for this.What works today
POST /v1/embeddingsworks against whichever chat model is currentlyis_active=True, IF that model supports embeddings. llama-server can do this for embedding-capable chat models, but with degraded behavior since the model wasn't optimized for it.Workaround
For now, the only embedding path is:
ggml-org(e.g., Qwen3-Embedding or BGE)./v1/embeddingsagainst the active model.This doesn't satisfy the use case of having a small dedicated embedding model (e.g., nomic-embed, BGE-small) loaded alongside a chat model on the same GPU.
Why it matters
Files
backend/app/services/vram_profiler.py:64-87—can_fitexists, unusedbackend/app/routers/proxy.py:927-944— embeddings endpoint, single-modelbackend/app/services/backends/llamacpp_backend.py—build_subprocess_command, no--embeddingflagbackend/app/services/process_manager.py— port allocator (_find_free_portsupports concurrent), but no model-type discriminationsrc/components/dialogs/add-edit-model-dialog.tsx— UI, no model type fieldsrc/lib/validations/model.ts— schema, no model type fieldRelated
Closing as fixed by commit
ea16ebf9("Fix #38: introduce embedding model concept — dedicated /v1/embeddings routing"), now on origin/main.The fix introduces a
model_typeenum (chat | embedding) on themodelstable with a back-compat migration (backend/migrations/add_model_type.py), wires--embeddingand--poolingflags intoLlamaCppBackend.build_subprocess_command, routes/v1/embeddingsto prefer a dedicated embedding model with chat-model fallback, and exposes a Model Type selector in the add/edit model dialog. Backend tests pass (96 passed, 2 skipped across test_backends.py / test_model_repository.py / test_proxy.py).Note: the repo has 77 pre-existing ruff errors at HEAD (86 on origin/main before this fix) — none introduced by this commit (the diff net-fixes 9 ruff violations). The kilo-gsd Lint gate tripped on the baseline dirt, not on this change. Filed as Mark/vllm_mm#43 (lint cleanup) so future feature dispatches land cleanly.