Repository navigation
Conversation
…d input payload
The multimodal embedding path always sends images with the vLLM chat embeddings
extension ({"messages": [...]}). Servers that do not implement that extension
reject the request before looking at the image, so vision support is unusable
outside vLLM. Gemini embedding endpoints answer:
Invalid JSON payload received. Unknown name "messages": Cannot find field.
and OpenAI-compatible gateways such as LiteLLM, which follow the standard
embeddings spec, drop the images and fail with INVALID_ARGUMENT.
Those providers do accept images, but as data URI elements of the standard
"input" array. Add a multimodal_embedding_format credential to pick the wire
format, keeping chat_embeddings as the default so vLLM setups are unaffected.
Images are sent one per request in the new path: providers reached this way may
fuse several input elements into a single embedding, and a response carrying a
different number of embeddings than inputs would shift every following vector,
so the count is now verified instead of trusted.
The request building and usage accounting shared with the text path are factored
into _post_embeddings() and _accumulate_usage() rather than duplicated.
…cted _invoke_multimodal() fell back to a bare "image" media type when the magic bytes matched none of the supported formats, producing "data:image;base64,...". A data URI needs a type/subtype pair, so providers that parse it strictly reject the request with an error that points nowhere near the real cause, while tolerant servers accept it and sniff the bytes themselves. Fail with an explicit message naming the supported formats instead. Guessing jpeg was deliberately dropped earlier, so the unknown case is now reported rather than mislabelled.
4 of 15 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3940.
Supersedes #3948, which was closed for merge conflicts after the dependency refresh (#4106–#4111). Rebased on the latest
main; the code is unchanged apart from the version bump.Image embedding only works against vLLM servers today.
_invoke_multimodal()always sends the vLLM chat embeddings extension ({"messages": [...]}), and providers that implement the OpenAI embeddings spec reject the request before they ever look at the image:Invalid JSON payload received. Unknown name "messages": Cannot find field./embeddings: Missing required parameter: 'input'.Those providers do accept images, but as
data:URI elements of the standardinputarray.This adds a
multimodal_embedding_formatcredential to choose the wire format:chat_embeddings— the current vLLM payload, and the default, so existing deployments are untouchedinput_array— the standard{"input": [...]}payload carrying the image as a data URIWhy a credential rather than auto-detection
encoding_format,user_identity_support,compatibility_mode).I kept
chat_embeddingsas the default to avoid silently changing behaviour for vLLM users, but I am happy to flip it if you would rather have the standard payload be the default.Why one image per request
Providers reached this way may fuse several input elements into a single embedding instead of returning one per element. Measured through a LiteLLM gateway (v1.98.0) in front of Vertex AI:
vertex_ai/gemini-embedding-2-previewvertex_ai/gemini-embedding-001vertex_ai/text-embedding-004Appending image data URIs to an existing batch would therefore return fewer embeddings than inputs, and
_embed_in_batches()would shift every following vector or raiseIndexErrorwith no indication of the cause. Each image is sent on its own request, and the response is now verified to carry exactly one embedding rather than trusted.This costs no extra round trips in practice:
get_customizable_model_schema()in the SDK pinsMAX_CHUNKSto 1, so the text path already sends one input per request.Changes
provider/openai_api_compatible.yaml: newmultimodal_embedding_formatselect, shown only fortext-embeddingwithvision_support: supportmodels/text_embedding/text_embedding.py:_embed_in_batches()_embed_multimodal_via_input_array()_post_embeddings()/_accumulate_usage()instead of duplicateddata:image;base64,...— a data URI with no subtype, which strict providers reject with an unrelated-looking error (separate commit)tests/test_text_embedding.py: 5 new testsmanifest.yaml: 0.0.73 → 0.0.75 (0.0.74 is already claimed by fix(openai_api_compatible): wire up the orphaned stream_function_calling credential #4068, fix(openai_api_compatible): accept gateways that report usage as input/output tokens #4131, fix(openai_api_compatible): carry video and audio attachments on the Responses path #4141, fix(openai_api_compatible): honor top_n=0 in text rerank #4142 and fix(openai_api_compatible): restore structured output capability #4146)_embed_multimodal_via_chat()is untouched.Release Notes
Added a "Multimodal embedding request format" option so image embeddings can be sent as a standard
inputarray for providers that reject the vLLM chat-embeddings payload.Change Type
Areas affected by this change (check all that apply)
Screenshots / Videos
Indexing the same PDF with images into a knowledge base,
gemini-embedding-2-previewbehind a LiteLLM gateway:error:/embeddings: Missing required parameter: 'input'.completed, 576 segmentsVersion
versioninmanifest.yaml(not the one undermeta)dify_plugin>=0.3.0,<0.11.0is declared inpyproject.tomland locked inuv.lockpyproject.tomlalready declaresdify_plugin>=0.9.0and is unchanged by this PR.Testing
uv run pytest tests -q→ all green, including 5 new cases: image sent as a data URI ininput, one request per image with order preserved across mixed text/image input,endpoint_model_nameandencoding_formatpropagation, usage accumulation, a fused response rejected, the default staying onchat_embeddingsfor unset/explicit/unknown values, and an undetectable image format reported instead of sent.End to end against a knowledge base, indexing the same PDF containing images, with
gemini-embedding-2-previewserved through a LiteLLM gateway in front of Vertex AI:multimodal_embedding_formatinput_arrayerrorcompleted/embeddings: Missing required parameter: 'input'.The same dataset and document were reused, so the only difference is the wire format. With the credential left unset the run reproduces the original failure, confirming the default path is unchanged.