Skip to content

Commit 8077d57

Browse files
committed
Add multimodal tests for VoyageAI (text, image, video, async)
1 parent 32e1c08 commit 8077d57

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

tests/integration/test_vectorizers.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,3 +713,113 @@ def test_voyageai_context_model_detection():
713713
for model_name, expected in test_cases:
714714
# The _is_context_model method simply checks: "context" in self.model
715715
assert ("context" in model_name) == expected, f"Failed for {model_name}"
716+
717+
718+
@pytest.mark.requires_api_keys
719+
def test_voyageai_multimodal_text_only():
720+
"""Test VoyageAI multimodal vectorizer with text-only input."""
721+
vectorizer = VoyageAIVectorizer(model="voyage-multimodal-3")
722+
723+
# Test single text embedding via embed()
724+
embedding = vectorizer.embed("A red apple on a wooden table")
725+
assert isinstance(embedding, list)
726+
assert len(embedding) > 0
727+
assert all(isinstance(x, float) for x in embedding)
728+
729+
# Test another text embedding to verify consistency
730+
embedding2 = vectorizer.embed("A cat sleeping on a couch")
731+
assert isinstance(embedding2, list)
732+
assert len(embedding2) == len(embedding)
733+
734+
735+
@pytest.mark.requires_api_keys
736+
def test_voyageai_multimodal_image():
737+
"""Test VoyageAI multimodal vectorizer with image input."""
738+
import os
739+
import tempfile
740+
741+
from PIL import Image
742+
743+
vectorizer = VoyageAIVectorizer(model="voyage-multimodal-3")
744+
745+
# Create a simple test image
746+
img = Image.new("RGB", (100, 100), color="red")
747+
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
748+
img.save(f, format="PNG")
749+
temp_path = f.name
750+
751+
try:
752+
# Test embed_image
753+
embedding = vectorizer.embed_image(temp_path)
754+
assert isinstance(embedding, list)
755+
assert len(embedding) > 0
756+
assert all(isinstance(x, float) for x in embedding)
757+
finally:
758+
os.unlink(temp_path)
759+
760+
761+
@pytest.mark.requires_api_keys
762+
def test_voyageai_multimodal_video():
763+
"""Test VoyageAI multimodal vectorizer with video input."""
764+
import os
765+
import subprocess
766+
import tempfile
767+
768+
from PIL import Image
769+
770+
vectorizer = VoyageAIVectorizer(model="voyage-multimodal-3.5")
771+
772+
# Create a minimal test video using ffmpeg
773+
with tempfile.TemporaryDirectory() as tmpdir:
774+
# Create 3 frames
775+
for i in range(3):
776+
img = Image.new("RGB", (64, 64), color=(i * 80, 100, 150))
777+
img.save(os.path.join(tmpdir, f"frame_{i:03d}.png"))
778+
779+
video_path = os.path.join(tmpdir, "test_video.mp4")
780+
781+
# Create video from frames
782+
result = subprocess.run(
783+
[
784+
"ffmpeg",
785+
"-y",
786+
"-framerate",
787+
"1",
788+
"-i",
789+
os.path.join(tmpdir, "frame_%03d.png"),
790+
"-c:v",
791+
"libx264",
792+
"-pix_fmt",
793+
"yuv420p",
794+
"-t",
795+
"3",
796+
video_path,
797+
],
798+
capture_output=True,
799+
)
800+
801+
if result.returncode != 0:
802+
pytest.skip("ffmpeg not available or failed to create test video")
803+
804+
# Test embed_video
805+
embedding = vectorizer.embed_video(video_path)
806+
assert isinstance(embedding, list)
807+
assert len(embedding) > 0
808+
assert all(isinstance(x, float) for x in embedding)
809+
810+
811+
@pytest.mark.requires_api_keys
812+
@pytest.mark.asyncio
813+
async def test_voyageai_multimodal_async():
814+
"""Test VoyageAI multimodal vectorizer async methods."""
815+
vectorizer = VoyageAIVectorizer(model="voyage-multimodal-3")
816+
817+
# Test async text embedding
818+
embedding = await vectorizer.aembed("A beautiful sunset over mountains")
819+
assert isinstance(embedding, list)
820+
assert len(embedding) > 0
821+
822+
# Test async batch
823+
texts = ["Ocean waves", "Forest trees"]
824+
embeddings = await vectorizer.aembed_many(texts)
825+
assert len(embeddings) == 2

0 commit comments

Comments
 (0)