| from __future__ import annotations |
|
|
| import tempfile |
| import unittest |
| from pathlib import Path |
| from unittest.mock import patch |
|
|
| from src import dialogue_engine |
|
|
|
|
| class DialogueEngineMultimodalTests(unittest.TestCase): |
| def test_build_user_content_adds_image_url(self): |
| with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as handle: |
| handle.write(b"\x89PNG\r\n\x1a\n") |
| image_path = Path(handle.name) |
|
|
| try: |
| content = dialogue_engine._build_user_content( |
| "看一下这张图", |
| {"images": [{"path": str(image_path)}]}, |
| ) |
| finally: |
| image_path.unlink(missing_ok=True) |
|
|
| self.assertIsInstance(content, list) |
| self.assertEqual(content[0], {"type": "text", "text": "看一下这张图"}) |
| self.assertEqual(content[1]["type"], "image_url") |
| self.assertTrue(content[1]["image_url"]["url"].startswith("data:image/png;base64,")) |
|
|
| def test_build_user_content_ignores_audio_attachment(self): |
| content = dialogue_engine._build_user_content( |
| "继续文字对话", |
| {"images": [], "audio": [{"path": "ignored.wav"}]}, |
| ) |
|
|
| self.assertEqual(content, [{"type": "text", "text": "继续文字对话"}]) |
|
|
| def test_vllm_failure_returns_regular_error_without_audio_fallback(self): |
| class FailingClient: |
| def __init__(self, *args, **kwargs): |
| pass |
|
|
| def __enter__(self): |
| return self |
|
|
| def __exit__(self, *args): |
| return False |
|
|
| def stream(self, *args, **kwargs): |
| raise RuntimeError("400 Bad Request") |
|
|
| with patch.dict("os.environ", {"VC_VLLM_RETRIES": "1"}, clear=False): |
| with patch("httpx.Client", FailingClient): |
| events = list( |
| dialogue_engine._stream_vllm_reply( |
| "https://example.test", |
| "你好", |
| [], |
| {"character": {"voice": {}}}, |
| {"images": []}, |
| {"enabled": False}, |
| ) |
| ) |
|
|
| errors = [event["message"] for event in events if event.get("type") == "error"] |
| self.assertTrue(any("Modal vLLM 调用失败" in message for message in errors)) |
|
|
|
|
| if __name__ == "__main__": |
| unittest.main() |
|
|