Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,13 @@ async def get_embeddings(
if encoding == "base64" and isinstance(item.embedding, str):
# Decode base64-encoded floats (little-endian IEEE 754)
raw = base64.b64decode(item.embedding)
if len(raw) % 4:
# A misaligned buffer would otherwise fail inside struct.unpack with a
# bare buffer-size error and no hint about which response item broke.
raise ValueError(
f"Base64 encoded embedding for input index {item.index} decoded to {len(raw)} bytes, "
"which cannot be split into 4-byte little-endian floats. The response payload is malformed."
)
vector = list(struct.unpack(f"<{len(raw) // 4}f", raw))
else:
vector = item.embedding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,35 @@ async def test_openai_base64_decoding(openai_unit_test_env: dict[str, str]) -> N
for expected, actual in zip(raw_floats, result[0].vector):
assert abs(expected - actual) < 1e-6

async def test_openai_base64_misaligned_payload_raises_descriptive_error(openai_unit_test_env: dict[str, str]) -> None:
"""A truncated base64 payload must fail with a clear error naming the input index,
not a bare struct buffer-size error."""
import base64
import struct

# One well formed float (4 bytes) plus a stray byte.
misaligned = base64.b64encode(struct.pack("<1f", 0.5) + b"\x00").decode()

mock_item = MagicMock()
mock_item.embedding = misaligned
mock_item.index = 0

mock_response = MagicMock()
mock_response.data = [mock_item]
mock_response.model = "text-embedding-3-small"
mock_response.usage = MagicMock(prompt_tokens=3, total_tokens=3)

client = OpenAIEmbeddingClient()
client.client = MagicMock()
client.client.embeddings = MagicMock()
client.client.embeddings.create = AsyncMock(return_value=mock_response)

options: OpenAIEmbeddingOptions = {"encoding_format": "base64"}

with pytest.raises(ValueError, match="cannot be split into 4-byte little-endian floats"):
await client.get_embeddings(["test"], options=options)



async def test_openai_error_when_no_model() -> None:
client = cast(Any, object.__new__(OpenAIEmbeddingClient))
Expand Down
Loading