Files
wehub-resource-sync e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:00:43 +08:00

177 lines
6.1 KiB
Python

"""Tests for OpenAICompatibleEmbeddingAdapter._extract_embeddings_from_response."""
from __future__ import annotations
import pytest
from deeptutor.services.embedding.adapters.openai_compatible import (
OpenAICompatibleEmbeddingAdapter,
)
_extract = OpenAICompatibleEmbeddingAdapter._extract_embeddings_from_response
# ---------------------------------------------------------------------------
# Standard OpenAI schema: {"data": [{"embedding": [...]}, ...]}
# ---------------------------------------------------------------------------
class TestOpenAIStandardSchema:
def test_single_embedding(self) -> None:
data = {"data": [{"embedding": [0.1, 0.2, 0.3]}]}
result = _extract(data)
assert result == [[0.1, 0.2, 0.3]]
def test_multiple_embeddings(self) -> None:
data = {
"data": [
{"embedding": [0.1, 0.2]},
{"embedding": [0.3, 0.4]},
]
}
result = _extract(data)
assert result == [[0.1, 0.2], [0.3, 0.4]]
def test_with_extra_fields(self) -> None:
data = {
"object": "list",
"model": "text-embedding-3-small",
"data": [
{"object": "embedding", "index": 0, "embedding": [1.0, 2.0]},
],
"usage": {"prompt_tokens": 5, "total_tokens": 5},
}
result = _extract(data)
assert result == [[1.0, 2.0]]
# ---------------------------------------------------------------------------
# Proxy schema: {"embeddings": [[...], ...]}
# ---------------------------------------------------------------------------
class TestProxySchema:
def test_nested_lists(self) -> None:
data = {"embeddings": [[0.1, 0.2], [0.3, 0.4]]}
result = _extract(data)
assert result == [[0.1, 0.2], [0.3, 0.4]]
def test_single_vector(self) -> None:
data = {"embeddings": [[0.5, 0.6, 0.7]]}
result = _extract(data)
assert result == [[0.5, 0.6, 0.7]]
# ---------------------------------------------------------------------------
# Ollama /api/embeddings: {"embedding": [...]} (singular, flat vector)
# ---------------------------------------------------------------------------
class TestOllamaSingularEmbedding:
def test_flat_float_vector(self) -> None:
data = {"embedding": [0.1, 0.2, 0.3, 0.4]}
result = _extract(data)
assert result == [[0.1, 0.2, 0.3, 0.4]]
def test_flat_int_vector(self) -> None:
data = {"embedding": [1, 2, 3]}
result = _extract(data)
assert result == [[1, 2, 3]]
def test_with_ollama_metadata(self) -> None:
data = {
"embedding": [0.01, -0.02, 0.03],
"model": "nomic-embed-text",
"total_duration": 123456789,
}
result = _extract(data)
assert result == [[0.01, -0.02, 0.03]]
def test_high_dimensional(self) -> None:
vec = [float(i) / 1000 for i in range(768)]
data = {"embedding": vec}
result = _extract(data)
assert len(result) == 1
assert len(result[0]) == 768
assert result[0] == vec
# ---------------------------------------------------------------------------
# Nested result/output variants
# ---------------------------------------------------------------------------
class TestNestedSchemas:
def test_result_data_with_embedding_objects(self) -> None:
data = {"result": {"data": [{"embedding": [0.1, 0.2]}]}}
result = _extract(data)
assert result == [[0.1, 0.2]]
def test_result_embeddings_nested_lists(self) -> None:
data = {"result": {"embeddings": [[0.1, 0.2], [0.3, 0.4]]}}
result = _extract(data)
assert result == [[0.1, 0.2], [0.3, 0.4]]
def test_output_data_with_embedding_objects(self) -> None:
data = {"output": {"data": [{"embedding": [0.5, 0.6]}]}}
result = _extract(data)
assert result == [[0.5, 0.6]]
def test_output_embeddings_nested_lists(self) -> None:
data = {"output": {"embeddings": [[0.7, 0.8]]}}
result = _extract(data)
assert result == [[0.7, 0.8]]
# ---------------------------------------------------------------------------
# Error conditions
# ---------------------------------------------------------------------------
class TestErrorHandling:
def test_non_dict_raises(self) -> None:
with pytest.raises(ValueError, match="not a JSON object"):
_extract([1, 2, 3])
def test_error_payload_string(self) -> None:
with pytest.raises(ValueError, match="error payload"):
_extract({"error": "something went wrong"})
def test_error_payload_dict_with_message(self) -> None:
with pytest.raises(ValueError, match="model not found"):
_extract({"error": {"message": "model not found", "code": 404}})
def test_error_payload_dict_with_detail(self) -> None:
with pytest.raises(ValueError, match="invalid key"):
_extract({"error": {"detail": "invalid key"}})
def test_unknown_schema_raises_with_keys(self) -> None:
with pytest.raises(ValueError, match="Cannot parse embeddings"):
_extract({"foo": "bar", "baz": 42})
def test_empty_data_list_falls_through(self) -> None:
with pytest.raises(ValueError, match="Cannot parse embeddings"):
_extract({"data": []})
def test_empty_embeddings_list_falls_through(self) -> None:
with pytest.raises(ValueError, match="Cannot parse embeddings"):
_extract({"embeddings": []})
def test_empty_embedding_singular_falls_through(self) -> None:
with pytest.raises(ValueError, match="Cannot parse embeddings"):
_extract({"embedding": []})
def test_none_embedding_value_replaced_with_empty_list(self) -> None:
"""When a provider returns {"embedding": null}, use [] instead of None.
Prevents TypeError in LlamaIndex similarity computation (issue #346).
"""
data = {
"data": [
{"embedding": [0.1, 0.2]},
{"embedding": None},
{"embedding": [0.3, 0.4]},
]
}
result = _extract(data)
assert result == [[0.1, 0.2], [], [0.3, 0.4]]