Skip to content

Commit e88dcdb

Browse files
committed
Add multimodal tests for VoyageAI (text, image, video, async)
1 parent 04461cd commit e88dcdb

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

tests/integration/test_vectorizers.py

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

0 commit comments

Comments
 (0)