fix(vertex_ai): keep all embeddings in multimodal embedding response

An instance that carries both `text` and `image` makes Vertex return
`textEmbedding` and `imageEmbedding` in the same prediction, but
transform_embedding_response_to_openai chained the branches with `elif`,
so only the first match was emitted and every other embedding was
silently dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
wakanapo 2026-08-03 15:35:34 +09:00
parent 491eda319c
commit f22e9b09c4
No known key found for this signature in database
3 changed files with 51 additions and 4 deletions

View file

@ -287,14 +287,14 @@ class VertexAIMultimodalEmbeddingConfig(BaseEmbeddingConfig):
object="embedding",
)
openai_embeddings.append(openai_embedding_object)
elif "imageEmbedding" in _prediction:
if "imageEmbedding" in _prediction:
openai_embedding_object = Embedding(
embedding=_prediction["imageEmbedding"],
index=idx,
object="embedding",
)
openai_embeddings.append(openai_embedding_object)
elif "videoEmbeddings" in _prediction:
if "videoEmbeddings" in _prediction:
for video_embedding in _prediction["videoEmbeddings"]:
openai_embedding_object = Embedding(
embedding=video_embedding["embedding"],

View file

@ -1880,8 +1880,9 @@ async def test_vertexai_multimodal_embedding():
assert args_to_vertexai == expected_payload
assert response.model == "multimodalembedding@001"
assert len(response.data) == 1
response_data = response.data[0]
assert len(response.data) == 2
assert response.data[0]["embedding"] == [0.4, 0.5, 0.6]
assert response.data[1]["embedding"] == [0.1, 0.2, 0.3]
# Optional: Print for debugging
print("Arguments passed to Vertex AI:", args_to_vertexai)

View file

@ -179,3 +179,49 @@ class TestVertexMultimodalEmbedding:
headers={},
)
assert "parameters" not in request
def test_response_keeps_both_text_and_image_embeddings(self):
predictions = {
"predictions": [
{
"textEmbedding": [0.4, 0.5, 0.6],
"imageEmbedding": [0.1, 0.2, 0.3],
}
]
}
result = self.config.transform_embedding_response_to_openai(predictions)
assert [e["embedding"] for e in result] == [[0.4, 0.5, 0.6], [0.1, 0.2, 0.3]]
assert [e["index"] for e in result] == [0, 0]
def test_response_keeps_text_and_video_embeddings(self):
predictions = {
"predictions": [
{
"textEmbedding": [0.4, 0.5, 0.6],
"videoEmbeddings": [
{
"startOffsetSec": 0,
"endOffsetSec": 5,
"embedding": [0.7, 0.8, 0.9],
}
],
}
]
}
result = self.config.transform_embedding_response_to_openai(predictions)
assert [e["embedding"] for e in result] == [[0.4, 0.5, 0.6], [0.7, 0.8, 0.9]]
@pytest.mark.parametrize(
"prediction, expected",
[
({"textEmbedding": [0.1, 0.2]}, [[0.1, 0.2]]),
({"imageEmbedding": [0.3, 0.4]}, [[0.3, 0.4]]),
(
{"videoEmbeddings": [{"startOffsetSec": 0, "endOffsetSec": 5, "embedding": [0.5]}]},
[[0.5]],
),
],
)
def test_response_single_modality_unchanged(self, prediction, expected):
result = self.config.transform_embedding_response_to_openai({"predictions": [prediction]})
assert [e["embedding"] for e in result] == expected