77
88from data_designer .config .models import ChatCompletionInferenceParams , ModelConfig
99from data_designer .config .run_config import RequestAdmissionTuningConfig , RunConfig
10- from data_designer .engine .models .errors import ModelAuthenticationError
10+ from data_designer .engine .models .errors import ModelAuthenticationError , ModelGenerationValidationFailureError
1111from data_designer .engine .models .facade import ModelFacade
1212from data_designer .engine .models .factory import create_model_registry
1313from data_designer .engine .models .registry import ModelRegistry
1414from data_designer .engine .models .usage import ModelUsageStats , RequestUsageStats , TokenCountSource , TokenUsageStats
15+ from data_designer .engine .testing import make_stub_completion_response
1516from data_designer .logging import LOG_INDENT
1617
1718
@@ -332,6 +333,8 @@ def test_run_health_check_success(
332333 mock_generate_image : object ,
333334 stub_model_registry : ModelRegistry ,
334335) -> None :
336+ mock_completion .return_value = make_stub_completion_response (content = "Hello!" )
337+ mock_generate_text_embeddings .return_value = [[0.1 ]]
335338 model_aliases = ["stub-text" , "stub-reasoning" , "stub-embedding" , "stub-image" ]
336339 stub_model_registry .run_health_check (model_aliases )
337340 assert mock_completion .call_count == 2
@@ -365,6 +368,7 @@ def test_run_health_check_embedding_authentication_error(
365368 stub_model_registry : ModelRegistry ,
366369) -> None :
367370 auth_error = ModelAuthenticationError ("Invalid API key for embedding model" )
371+ mock_completion .return_value = make_stub_completion_response (content = "Hello!" )
368372 mock_generate_text_embeddings .side_effect = auth_error
369373 model_aliases = ["stub-text" , "stub-reasoning" , "stub-embedding" ]
370374
@@ -375,12 +379,39 @@ def test_run_health_check_embedding_authentication_error(
375379 mock_generate_text_embeddings .assert_called_once ()
376380
377381
382+ @patch .object (ModelFacade , "completion" , autospec = True )
383+ def test_run_health_check_rejects_empty_completion_response (
384+ mock_completion : object ,
385+ stub_model_registry : ModelRegistry ,
386+ ) -> None :
387+ mock_completion .return_value = make_stub_completion_response (content = "" )
388+
389+ with pytest .raises (ModelGenerationValidationFailureError , match = "Health check response must be non-empty text" ):
390+ stub_model_registry .run_health_check (["stub-text" ])
391+
392+ mock_completion .assert_called_once ()
393+
394+
395+ @patch .object (ModelFacade , "generate_text_embeddings" , autospec = True )
396+ def test_run_health_check_rejects_empty_embedding_vector (
397+ mock_generate_text_embeddings : object ,
398+ stub_model_registry : ModelRegistry ,
399+ ) -> None :
400+ mock_generate_text_embeddings .return_value = [[]]
401+
402+ with pytest .raises (ModelGenerationValidationFailureError , match = "invalid embedding response" ):
403+ stub_model_registry .run_health_check (["stub-embedding" ])
404+
405+ mock_generate_text_embeddings .assert_called_once ()
406+
407+
378408@patch .object (ModelFacade , "completion" , autospec = True )
379409def test_run_health_check_skip_health_check_flag (
380410 mock_completion : object ,
381411 stub_secrets_resolver : object ,
382412 stub_model_provider_registry : object ,
383413) -> None :
414+ mock_completion .return_value = make_stub_completion_response (content = "Hello!" )
384415 # Create model configs: one with skip_health_check=True, others with default (False)
385416 model_configs = [
386417 ModelConfig (
@@ -436,6 +467,7 @@ async def test_arun_health_check_success(
436467 mock_agenerate_image : AsyncMock ,
437468 stub_model_registry : ModelRegistry ,
438469) -> None :
470+ mock_agenerate_text_embeddings .return_value = [[0.1 ]]
439471 model_aliases = ["stub-text" , "stub-reasoning" , "stub-embedding" , "stub-image" ]
440472 await stub_model_registry .arun_health_check (model_aliases )
441473 assert mock_agenerate .call_count == 2
@@ -461,6 +493,20 @@ async def test_arun_health_check_authentication_error(
461493 mock_agenerate_text_embeddings .assert_not_awaited ()
462494
463495
496+ @patch .object (ModelFacade , "agenerate_text_embeddings" , new_callable = AsyncMock )
497+ @pytest .mark .asyncio
498+ async def test_arun_health_check_rejects_empty_embedding_vector (
499+ mock_agenerate_text_embeddings : AsyncMock ,
500+ stub_model_registry : ModelRegistry ,
501+ ) -> None :
502+ mock_agenerate_text_embeddings .return_value = [[]]
503+
504+ with pytest .raises (ModelGenerationValidationFailureError , match = "invalid embedding response" ):
505+ await stub_model_registry .arun_health_check (["stub-embedding" ])
506+
507+ mock_agenerate_text_embeddings .assert_awaited_once ()
508+
509+
464510def test_get_aggregate_max_parallel_requests (stub_model_registry : ModelRegistry ) -> None :
465511 """get_aggregate_max_parallel_requests returns the sum across all model configs."""
466512 total = stub_model_registry .get_aggregate_max_parallel_requests ()
0 commit comments