diff --git a/changelog/4393.fixed.md b/changelog/4393.fixed.md new file mode 100644 index 000000000..340158e42 --- /dev/null +++ b/changelog/4393.fixed.md @@ -0,0 +1 @@ +- Fixed an issue where `LocalSmartTurnAnalyzerV3` was imported unconditionally for user turn stop strategies. It is now only imported when `default_user_turn_stop_strategies()` is called. This improves startup time and removes the `transformers` "PyTorch/TensorFlow/Flax not found" warning when the default stop strategies are not used. diff --git a/src/pipecat/turns/user_turn_strategies.py b/src/pipecat/turns/user_turn_strategies.py index 8a663d3da..8bbe87a7a 100644 --- a/src/pipecat/turns/user_turn_strategies.py +++ b/src/pipecat/turns/user_turn_strategies.py @@ -8,7 +8,6 @@ from dataclasses import dataclass -from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 from pipecat.turns.user_start import ( BaseUserTurnStartStrategy, ExternalUserTurnStartStrategy, @@ -44,6 +43,8 @@ def default_user_turn_stop_strategies() -> list[BaseUserTurnStopStrategy]: Returns ``[TurnAnalyzerUserTurnStopStrategy(LocalSmartTurnAnalyzerV3)]``. Useful when building a custom strategy list that extends the defaults. """ + from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 + return [TurnAnalyzerUserTurnStopStrategy(turn_analyzer=LocalSmartTurnAnalyzerV3())] diff --git a/tests/test_krisp_ip_user_turn_start_strategy.py b/tests/test_krisp_ip_user_turn_start_strategy.py index 5e5dd00cc..576c4be60 100644 --- a/tests/test_krisp_ip_user_turn_start_strategy.py +++ b/tests/test_krisp_ip_user_turn_start_strategy.py @@ -12,10 +12,6 @@ from unittest.mock import MagicMock, patch import numpy as np -# Mock package version check before importing pipecat (development mode) -_version_patcher = patch("importlib.metadata.version", return_value="0.0.0-dev") -_version_patcher.start() - # Mock krisp_audio before any pipecat import that loads krisp_instance / VIVA IP strategy mock_krisp_audio = MagicMock() mock_krisp_audio.SamplingRate.Sr8000Hz = 8000 @@ -37,18 +33,22 @@ sys.modules["pipecat_ai_krisp"] = mock_pipecat_krisp sys.modules["pipecat_ai_krisp.audio"] = MagicMock() sys.modules["pipecat_ai_krisp.audio.krisp_processor"] = MagicMock() -from pipecat.frames.frames import ( - BotStartedSpeakingFrame, - BotStoppedSpeakingFrame, - InputAudioRawFrame, - TranscriptionFrame, - VADUserStartedSpeakingFrame, - VADUserStoppedSpeakingFrame, -) -from pipecat.turns.types import ProcessFrameResult -from pipecat.turns.user_start.krisp_viva_ip_user_turn_start_strategy import ( - KrispVivaIPUserTurnStartStrategy, -) +# The version patch is scoped to just the import so it doesn't leak across the +# test session and corrupt importlib.metadata.version for other tests +# (e.g. transformers' import-time dependency checks). +with patch("importlib.metadata.version", return_value="0.0.0-dev"): + from pipecat.frames.frames import ( + BotStartedSpeakingFrame, + BotStoppedSpeakingFrame, + InputAudioRawFrame, + TranscriptionFrame, + VADUserStartedSpeakingFrame, + VADUserStoppedSpeakingFrame, + ) + from pipecat.turns.types import ProcessFrameResult + from pipecat.turns.user_start.krisp_viva_ip_user_turn_start_strategy import ( + KrispVivaIPUserTurnStartStrategy, + ) STRATEGY_MODULE = "pipecat.turns.user_start.krisp_viva_ip_user_turn_start_strategy" diff --git a/tests/test_krisp_sdk_manager.py b/tests/test_krisp_sdk_manager.py index 2edbf4598..c809527ef 100644 --- a/tests/test_krisp_sdk_manager.py +++ b/tests/test_krisp_sdk_manager.py @@ -11,11 +11,6 @@ from unittest.mock import MagicMock, patch import pytest -# Mock package version check before importing pipecat -# This allows tests to run in development mode without installed package -_version_patcher = patch("importlib.metadata.version", return_value="0.0.0-dev") -_version_patcher.start() - # Mock krisp_audio module BEFORE any pipecat imports # This allows tests to run without krisp_audio installed mock_krisp_audio = MagicMock() @@ -48,12 +43,15 @@ sys.modules["pipecat_ai_krisp"] = mock_pipecat_krisp sys.modules["pipecat_ai_krisp.audio"] = MagicMock() sys.modules["pipecat_ai_krisp.audio.krisp_processor"] = MagicMock() -# Now we can safely import -from pipecat.audio.krisp_instance import ( - KRISP_SAMPLE_RATES, - KrispVivaSDKManager, - int_to_krisp_sample_rate, -) +# Now we can safely import. The version patch is scoped to just the import so +# it doesn't leak across the test session and corrupt importlib.metadata.version +# for other tests (e.g. transformers' import-time dependency checks). +with patch("importlib.metadata.version", return_value="0.0.0-dev"): + from pipecat.audio.krisp_instance import ( + KRISP_SAMPLE_RATES, + KrispVivaSDKManager, + int_to_krisp_sample_rate, + ) class TestKrispVivaSDKManager: diff --git a/tests/test_krisp_viva_filter.py b/tests/test_krisp_viva_filter.py index a788ab131..61a6d0493 100644 --- a/tests/test_krisp_viva_filter.py +++ b/tests/test_krisp_viva_filter.py @@ -13,11 +13,6 @@ from unittest.mock import MagicMock, patch import numpy as np -# Mock package version check before importing pipecat -# This allows tests to run in development mode without installed package -_version_patcher = patch("importlib.metadata.version", return_value="0.0.0-dev") -_version_patcher.start() - # Mock krisp_audio module BEFORE any pipecat imports # This allows tests to run without krisp_audio installed mock_krisp_audio = MagicMock() @@ -42,9 +37,12 @@ sys.modules["pipecat_ai_krisp"] = mock_pipecat_krisp sys.modules["pipecat_ai_krisp.audio"] = MagicMock() sys.modules["pipecat_ai_krisp.audio.krisp_processor"] = MagicMock() -# Now we can safely import -from pipecat.audio.filters.krisp_viva_filter import KrispVivaFilter -from pipecat.frames.frames import FilterEnableFrame +# Now we can safely import. The version patch is scoped to just the import so +# it doesn't leak across the test session and corrupt importlib.metadata.version +# for other tests (e.g. transformers' import-time dependency checks). +with patch("importlib.metadata.version", return_value="0.0.0-dev"): + from pipecat.audio.filters.krisp_viva_filter import KrispVivaFilter + from pipecat.frames.frames import FilterEnableFrame class TestKrispVivaFilter(unittest.IsolatedAsyncioTestCase): diff --git a/tests/test_krisp_viva_vad.py b/tests/test_krisp_viva_vad.py index 12b06bc70..9124eaad8 100644 --- a/tests/test_krisp_viva_vad.py +++ b/tests/test_krisp_viva_vad.py @@ -15,11 +15,6 @@ from unittest.mock import MagicMock, patch import numpy as np -# Mock package version check before importing pipecat -# This allows tests to run in development mode without installed package -_version_patcher = patch("importlib.metadata.version", return_value="0.0.0-dev") -_version_patcher.start() - # Mock krisp_audio module BEFORE any pipecat imports # This allows tests to run without krisp_audio installed mock_krisp_audio = MagicMock() @@ -44,9 +39,12 @@ sys.modules["pipecat_ai_krisp"] = mock_pipecat_krisp sys.modules["pipecat_ai_krisp.audio"] = MagicMock() sys.modules["pipecat_ai_krisp.audio.krisp_processor"] = MagicMock() -# Now we can safely import -from pipecat.audio.vad.krisp_viva_vad import KrispVivaVadAnalyzer -from pipecat.audio.vad.vad_analyzer import VADParams +# Now we can safely import. The version patch is scoped to just the import so +# it doesn't leak across the test session and corrupt importlib.metadata.version +# for other tests (e.g. transformers' import-time dependency checks). +with patch("importlib.metadata.version", return_value="0.0.0-dev"): + from pipecat.audio.vad.krisp_viva_vad import KrispVivaVadAnalyzer + from pipecat.audio.vad.vad_analyzer import VADParams class TestKrispVivaVadAnalyzer(unittest.TestCase):