diff --git a/.env.example b/.env.example index c9031db0..e1034e84 100644 --- a/.env.example +++ b/.env.example @@ -69,7 +69,7 @@ EVA_MODEL__LLM=gpt-5.2 # --- LLM mode: STT --- #i STT provider for the voice pipeline. #d enum -#e assemblyai,cartesia,cartesia-multilingual,deepgram,deepgram-flux,elevenlabs,nvidia,nvidia-baseten,openai +#e assemblyai,cartesia,cartesia-multilingual,deepgram,deepgram-flux,elevenlabs,nvidia,nvidia-baseten,openai,smallest #x pipeline_mode=LLM EVA_MODEL__STT=cartesia @@ -87,7 +87,7 @@ EVA_MODEL__STT_PARAMS='{"api_key": "your_cartesia_api_key", "model": "ink-2"}' # --- TTS (LLM and AudioLLM modes) --- #i TTS provider for the voice pipeline. #d enum -#e cartesia,chatterbox,elevenlabs,gemini,kokoro,nvidia-baseten,openai,xtts +#e cartesia,chatterbox,elevenlabs,gemini,kokoro,nvidia-baseten,openai,smallest,xtts #x pipeline_mode=LLM,AudioLLM EVA_MODEL__TTS=cartesia diff --git a/src/eva/__init__.py b/src/eva/__init__.py index eb2eaa6a..1a6de9c3 100644 --- a/src/eva/__init__.py +++ b/src/eva/__init__.py @@ -7,7 +7,7 @@ # Bump simulation_version when changes affect benchmark outputs (agent code, # user simulator, orchestrator, simulation prompts, agent configs, tool mocks). -simulation_version = "2.0.1" +simulation_version = "2.0.2" # Bump metrics_version when changes affect metric computation (metrics code, # judge prompts, pricing tables, postprocessor). diff --git a/src/eva/assistant/pipeline/services.py b/src/eva/assistant/pipeline/services.py index d4db940e..b8ae74fa 100644 --- a/src/eva/assistant/pipeline/services.py +++ b/src/eva/assistant/pipeline/services.py @@ -37,6 +37,8 @@ from pipecat.services.openai.realtime.llm import OpenAIRealtimeLLMService from pipecat.services.openai.stt import OpenAISTTService from pipecat.services.openai.tts import OpenAITTSService +from pipecat.services.smallest.stt import SmallestSTTService +from pipecat.services.smallest.tts import SmallestTTSService from pipecat.services.stt_service import STTService from pipecat.services.tts_service import TTSService from pipecat.services.xai.stt import XAISTTService @@ -279,6 +281,21 @@ def create_stt_service( ) return stt_service + elif model_lower == "smallest": + logger.info(f"Using Smallest Pulse STT: {params['model']}") + smallest_stt_settings_kwargs = { + k: params[k] for f in dataclasses.fields(SmallestSTTService.Settings) if (k := f.name) in params + } + return SmallestSTTService( + api_key=api_key, + base_url=url or "wss://api.smallest.ai", + sample_rate=params.get("sample_rate", SAMPLE_RATE), + settings=SmallestSTTService.Settings( + language=_to_language_enum(language_code), + **smallest_stt_settings_kwargs, + ), + ) + elif model_lower == "xai": logger.info("Using xAI STT") xai_settings_kwargs = { @@ -298,7 +315,7 @@ def create_stt_service( else: raise ValueError( - f"Unknown STT model: {model}. Available: assemblyai, cartesia, cartesia-multilingual, cohere, deepgram, deepgram-flux, elevenlabs, nvidia, nvidia-baseten, openai, xai" + f"Unknown STT model: {model}. Available: assemblyai, cartesia, cartesia-multilingual, cohere, deepgram, deepgram-flux, elevenlabs, nvidia, nvidia-baseten, openai, smallest, xai" ) @@ -500,6 +517,25 @@ def create_tts_service( return openai_tts + elif model_lower == "smallest": + logger.info(f"Using Smallest Lightning TTS: {params['model']}") + smallest_tts_settings_kwargs = { + k: params[k] for f in dataclasses.fields(SmallestTTSService.Settings) if (k := f.name) in params + } + if "voice_id" in params: + # Omit "voice" entirely when unset so pipecat's per-model default (e.g. "sophia" for + # lightning_v3.1, "meher" for lightning_v3.1_pro) applies instead of a hardcoded EVA default. + smallest_tts_settings_kwargs["voice"] = params["voice_id"] + return SmallestTTSService( + api_key=api_key, + base_url=url or "wss://api.smallest.ai", + sample_rate=SAMPLE_RATE, + settings=SmallestTTSService.Settings( + language=_to_language_enum(language_code), + **smallest_tts_settings_kwargs, + ), + ) + elif model_lower == "voxtral": logger.info(f"Using Voxtral TTS: {params['model']}") voxtral_tts = OpenAITTSService( @@ -557,7 +593,7 @@ def create_tts_service( else: raise ValueError( - f"Unknown TTS model: {model}. Available: cartesia, chatterbox, deepgram, elevenlabs, gemini, kokoro, nvidia-baseten, openai, xai, xtts" + f"Unknown TTS model: {model}. Available: cartesia, chatterbox, deepgram, elevenlabs, gemini, kokoro, nvidia-baseten, openai, smallest, voxtral, xai, xtts" ) diff --git a/tests/unit/assistant/test_services.py b/tests/unit/assistant/test_services.py index 2442760a..ef8a3a3d 100644 --- a/tests/unit/assistant/test_services.py +++ b/tests/unit/assistant/test_services.py @@ -151,6 +151,19 @@ def test_xai_stt_defaults_and_forwards(self): assert svc._settings.endpointing == 42 # Explicit override wins over the Eva default assert svc._settings.interim_results is True # EVA default preserved + def test_smallest_returns_smallest_service(self): + svc = create_stt_service("smallest", params={"api_key": "k", "model": "pulse"}) + assert "Smallest" in type(svc).__name__ + assert svc._settings.model == "pulse" + + def test_smallest_forwards_optional_settings(self): + svc = create_stt_service( + "smallest", + params={"api_key": "k", "model": "pulse", "word_timestamps": True, "diarize": True}, + ) + assert svc._settings.word_timestamps is True + assert svc._settings.diarize is True + def test_cartesia_is_ink2_turns_service(self): svc = create_stt_service("cartesia", params={"api_key": "k", "model": "ink-2"}) assert "Turns" in type(svc).__name__ @@ -256,6 +269,23 @@ def test_elevenlabs_forwards_voice_tuning(self): assert svc._settings.stability == 0.7 assert svc._settings.speed == 1.1 + def test_smallest_returns_smallest_service(self): + svc = create_tts_service("smallest", params={"api_key": "k", "model": "lightning_v3.1"}) + assert "Smallest" in type(svc).__name__ + + def test_smallest_forwards_voice_id_and_speed(self): + svc = create_tts_service( + "smallest", + params={"api_key": "k", "model": "lightning_v3.1", "voice_id": "sophia", "speed": 1.2}, + ) + assert svc._settings.voice == "sophia" + assert svc._settings.speed == 1.2 + + def test_smallest_defaults_voice_per_model_when_unset(self): + """Omitting voice_id must not override pipecat's per-model default voice.""" + svc = create_tts_service("smallest", params={"api_key": "k", "model": "lightning_v3.1_pro"}) + assert svc._settings.voice == "meher" + def test_openai_respects_voice_param(self): svc = create_tts_service("openai", params={"api_key": "k", "model": "tts-1", "voice": "nova"}) assert svc._settings.voice == "nova"