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
148 lines
4.8 KiB
Python
148 lines
4.8 KiB
Python
"""Tests for the DashScope (Aliyun) MultiModalEmbedding adapter."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import types
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from deeptutor.services.embedding.adapters.base import EmbeddingRequest
|
|
from deeptutor.services.embedding.adapters.dashscope_native import (
|
|
DashScopeMultiModalEmbeddingAdapter,
|
|
)
|
|
|
|
|
|
class _FakeResponse:
|
|
def __init__(
|
|
self,
|
|
*,
|
|
status_code: int = 200,
|
|
output: dict | None = None,
|
|
usage: dict | None = None,
|
|
code: str = "",
|
|
message: str = "",
|
|
request_id: str = "req-1",
|
|
) -> None:
|
|
self.status_code = status_code
|
|
self.output = output if output is not None else {"embeddings": []}
|
|
self.usage = usage or {}
|
|
self.code = code
|
|
self.message = message
|
|
self.request_id = request_id
|
|
|
|
|
|
def _install_fake_sdk(monkeypatch: pytest.MonkeyPatch, response: _FakeResponse) -> dict[str, Any]:
|
|
captured: dict[str, Any] = {}
|
|
|
|
def fake_call(*, api_key: str, model: str, input: dict, **kwargs: Any) -> _FakeResponse: # noqa: A002
|
|
captured.update(
|
|
api_key=api_key,
|
|
model=model,
|
|
input=input,
|
|
kwargs=kwargs,
|
|
)
|
|
return response
|
|
|
|
fake_module = types.SimpleNamespace(MultiModalEmbedding=types.SimpleNamespace(call=fake_call))
|
|
monkeypatch.setitem(sys.modules, "dashscope", fake_module)
|
|
return captured
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_text_only_translates_texts_to_contents(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
response = _FakeResponse(
|
|
output={"embeddings": [{"index": 0, "embedding": [0.1, 0.2, 0.3], "type": "vl"}]},
|
|
)
|
|
captured = _install_fake_sdk(monkeypatch, response)
|
|
|
|
adapter = DashScopeMultiModalEmbeddingAdapter(
|
|
{
|
|
"api_key": "sk-dashscope",
|
|
"base_url": "https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding",
|
|
"model": "qwen3-vl-embedding",
|
|
"dimensions": 1024,
|
|
"request_timeout": 5,
|
|
}
|
|
)
|
|
resp = await adapter.embed(
|
|
EmbeddingRequest(texts=["hello", "world"], model="qwen3-vl-embedding")
|
|
)
|
|
|
|
# SDK takes a flat list — it wraps as {"contents": ...} internally.
|
|
assert captured["input"] == [{"text": "hello"}, {"text": "world"}]
|
|
assert captured["model"] == "qwen3-vl-embedding"
|
|
assert captured["api_key"] == "sk-dashscope"
|
|
assert captured["kwargs"].get("dimension") == 1024
|
|
assert "enable_fusion" not in captured["kwargs"]
|
|
assert resp.embeddings == [[0.1, 0.2, 0.3]]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_multimodal_contents_passed_through(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
response = _FakeResponse(
|
|
output={"embeddings": [{"index": 0, "embedding": [0.4, 0.5], "type": "fusion"}]},
|
|
)
|
|
captured = _install_fake_sdk(monkeypatch, response)
|
|
|
|
adapter = DashScopeMultiModalEmbeddingAdapter(
|
|
{
|
|
"api_key": "sk-dashscope",
|
|
"base_url": "https://dashscope.aliyuncs.com/...",
|
|
"model": "qwen3-vl-embedding",
|
|
"dimensions": 0,
|
|
"request_timeout": 5,
|
|
}
|
|
)
|
|
contents = [{"text": "a slide"}, {"image": "https://example.com/img.png"}]
|
|
resp = await adapter.embed(
|
|
EmbeddingRequest(
|
|
texts=[],
|
|
model="qwen3-vl-embedding",
|
|
contents=contents,
|
|
enable_fusion=True,
|
|
)
|
|
)
|
|
# SDK takes a flat list — it wraps as {"contents": ...} internally.
|
|
assert captured["input"] == contents
|
|
assert captured["kwargs"].get("enable_fusion") is True
|
|
assert resp.embeddings == [[0.4, 0.5]]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_failure_raises_runtime_error(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
response = _FakeResponse(
|
|
status_code=400,
|
|
output={"embeddings": []},
|
|
code="InvalidParameter",
|
|
message="dimension out of range",
|
|
)
|
|
_install_fake_sdk(monkeypatch, response)
|
|
|
|
adapter = DashScopeMultiModalEmbeddingAdapter(
|
|
{
|
|
"api_key": "sk",
|
|
"base_url": "https://dashscope.aliyuncs.com/...",
|
|
"model": "qwen3-vl-embedding",
|
|
"request_timeout": 5,
|
|
}
|
|
)
|
|
with pytest.raises(RuntimeError) as ei:
|
|
await adapter.embed(EmbeddingRequest(texts=["x"], model="qwen3-vl-embedding"))
|
|
assert "InvalidParameter" in str(ei.value)
|
|
|
|
|
|
def test_get_model_info_reports_multimodal_capability() -> None:
|
|
adapter = DashScopeMultiModalEmbeddingAdapter(
|
|
{
|
|
"api_key": "sk",
|
|
"base_url": "https://...",
|
|
"model": "qwen3-vl-embedding",
|
|
}
|
|
)
|
|
info = adapter.get_model_info()
|
|
assert info["multimodal"] is True
|
|
assert info["provider"] == "aliyun"
|
|
assert 2560 in info["supported_dimensions"]
|