"""Deep coverage tests for llm_config.py targeting uncovered branches. Focuses on: - get_llm() with registered custom LLMs (callable factory and BaseChatModel instance) - get_llm() with invalid provider - ProcessingLLMWrapper.close() - _get_context_window_for_provider() with None window_size from settings """ from unittest.mock import MagicMock, patch import pytest from langchain_core.language_models import BaseChatModel MODULE = "local_deep_research.config.llm_config" # Context-window resolution delegates to the _helpers twin, which reads # settings via thread_settings.get_setting_from_snapshot. Patch this module # (not MODULE) for context-window tests. THREAD_SETTINGS = "local_deep_research.config.thread_settings" def _make_settings_snapshot(provider="openai", model="gpt-4", **extra): snap = { "llm.provider": provider, "llm.model": model, "llm.temperature": 0.7, "llm.max_tokens": 4096, "llm.supports_max_tokens": True, "llm.context_window_unrestricted": True, "rate_limiting.llm_enabled": False, } snap.update(extra) return snap # --------------------------------------------------------------------------- # get_llm with registered custom LLM – callable factory # --------------------------------------------------------------------------- class TestGetLlmRegisteredFactory: def test_callable_factory_invoked(self): mock_instance = MagicMock(spec=BaseChatModel) mock_factory = MagicMock(return_value=mock_instance) # Make isinstance(mock_factory, BaseChatModel) return False # mock_factory is already a MagicMock (not BaseChatModel) with ( patch(f"{MODULE}.is_llm_registered", return_value=True), patch(f"{MODULE}.get_llm_from_registry", return_value=mock_factory), patch(f"{MODULE}.get_setting_from_snapshot") as mock_setting, patch(f"{MODULE}.wrap_llm_without_think_tags") as mock_wrap, ): mock_setting.side_effect = ( lambda key, default=None, settings_snapshot=None: { "llm.model": "gpt-4", "llm.temperature": 0.7, "llm.provider": "my_custom", "rate_limiting.llm_enabled": False, }.get(key, default) ) from local_deep_research.config.llm_config import get_llm get_llm( provider="my_custom", settings_snapshot={"search.tool": "searxng"}, ) mock_factory.assert_called_once() mock_wrap.assert_called_once() def test_factory_returning_non_basechatmodel_raises(self): mock_factory = MagicMock(return_value="not_a_model") with ( patch(f"{MODULE}.is_llm_registered", return_value=True), patch(f"{MODULE}.get_llm_from_registry", return_value=mock_factory), patch(f"{MODULE}.get_setting_from_snapshot") as mock_setting, ): mock_setting.side_effect = ( lambda key, default=None, settings_snapshot=None: { "llm.model": "gpt-4", "llm.temperature": 0.7, "llm.provider": "my_custom", }.get(key, default) ) from local_deep_research.config.llm_config import get_llm with pytest.raises(ValueError, match="must return a BaseChatModel"): get_llm( provider="my_custom", settings_snapshot={"search.tool": "searxng"}, ) def test_factory_with_bad_signature_raises_type_error(self): def bad_factory(): return MagicMock(spec=BaseChatModel) with ( patch(f"{MODULE}.is_llm_registered", return_value=True), patch(f"{MODULE}.get_llm_from_registry", return_value=bad_factory), patch(f"{MODULE}.get_setting_from_snapshot") as mock_setting, ): mock_setting.side_effect = ( lambda key, default=None, settings_snapshot=None: { "llm.model": "gpt-4", "llm.temperature": 0.7, "llm.provider": "bad_factory", }.get(key, default) ) from local_deep_research.config.llm_config import get_llm with pytest.raises(TypeError, match="invalid signature"): get_llm( provider="bad_factory", settings_snapshot={"search.tool": "searxng"}, ) def test_registered_basechatmodel_instance_used_directly(self): mock_instance = MagicMock(spec=BaseChatModel) with ( patch(f"{MODULE}.is_llm_registered", return_value=True), patch( f"{MODULE}.get_llm_from_registry", return_value=mock_instance ), patch(f"{MODULE}.get_setting_from_snapshot") as mock_setting, patch(f"{MODULE}.wrap_llm_without_think_tags") as mock_wrap, ): mock_setting.side_effect = ( lambda key, default=None, settings_snapshot=None: { "llm.model": "gpt-4", "llm.temperature": 0.7, "llm.provider": "my_instance", }.get(key, default) ) from local_deep_research.config.llm_config import get_llm get_llm( provider="my_instance", settings_snapshot={"search.tool": "searxng"}, ) # The factory path is skipped for BaseChatModel instances mock_wrap.assert_called_once() def test_registered_invalid_type_raises_value_error(self): """Registered object that is not BaseChatModel and not callable raises ValueError.""" class WeirdThing: pass with ( patch(f"{MODULE}.is_llm_registered", return_value=True), patch(f"{MODULE}.get_llm_from_registry", return_value=WeirdThing()), patch(f"{MODULE}.get_setting_from_snapshot") as mock_setting, ): mock_setting.side_effect = ( lambda key, default=None, settings_snapshot=None: { "llm.model": "gpt-4", "llm.temperature": 0.7, "llm.provider": "weird", }.get(key, default) ) from local_deep_research.config.llm_config import get_llm with pytest.raises( ValueError, match="must be either a BaseChatModel" ): get_llm( provider="weird", settings_snapshot={"search.tool": "searxng"}, ) # --------------------------------------------------------------------------- # get_llm with invalid provider # --------------------------------------------------------------------------- class TestGetLlmInvalidProvider: def test_invalid_provider_raises_value_error(self): with ( patch(f"{MODULE}.is_llm_registered", return_value=False), patch(f"{MODULE}.get_setting_from_snapshot") as mock_setting, ): mock_setting.side_effect = ( lambda key, default=None, settings_snapshot=None: { "llm.model": "gpt-4", "llm.temperature": 0.7, "llm.provider": "bogus_provider", "llm.supports_max_tokens": False, "llm.context_window_unrestricted": True, "rate_limiting.llm_enabled": False, }.get(key, default) ) from local_deep_research.config.llm_config import get_llm with pytest.raises(ValueError, match="Invalid provider"): get_llm( provider="bogus_provider", settings_snapshot={"search.tool": "searxng"}, ) # --------------------------------------------------------------------------- # _get_context_window_for_provider edge cases # --------------------------------------------------------------------------- class TestContextWindowEdgeCases: def test_none_window_size_for_local_provider_defaults_to_8192(self): """If local_context_window_size returns None, defaults to 8192.""" with patch( f"{THREAD_SETTINGS}.get_setting_from_snapshot", return_value=None, ): from local_deep_research.config.llm_config import ( _get_context_window_for_provider, ) result = _get_context_window_for_provider("ollama") assert result == 8192 def test_none_window_size_for_cloud_restricted_defaults_to_128000(self): """Restricted cloud: if context_window_size returns None, defaults to 128000.""" call_num = [0] def fake_setting(key, default=None, settings_snapshot=None): call_num[0] += 1 if key == "llm.context_window_unrestricted": return False if key == "llm.context_window_size": return None return default with patch( f"{THREAD_SETTINGS}.get_setting_from_snapshot", side_effect=fake_setting, ): from local_deep_research.config.llm_config import ( _get_context_window_for_provider, ) result = _get_context_window_for_provider("openai") assert result == 128000 def test_llamacpp_is_local_provider(self): """llamacpp is in the local provider list.""" with patch( f"{THREAD_SETTINGS}.get_setting_from_snapshot", return_value=8192, ): from local_deep_research.config.llm_config import ( _get_context_window_for_provider, ) result = _get_context_window_for_provider("llamacpp") assert result == 8192 # --------------------------------------------------------------------------- # ProcessingLLMWrapper.close() # --------------------------------------------------------------------------- class TestProcessingLLMWrapperClose: def _make_wrapper(self, mock_llm): with patch(f"{MODULE}.get_setting_from_snapshot", return_value=False): from local_deep_research.config.llm_config import ( wrap_llm_without_think_tags, ) return wrap_llm_without_think_tags(mock_llm) def test_close_called_without_error(self): mock_llm = MagicMock() wrapper = self._make_wrapper(mock_llm) with patch( "local_deep_research.utilities.llm_utils._close_base_llm" ) as mock_close: wrapper.close() mock_close.assert_called_once_with(mock_llm) def test_close_swallows_exceptions(self): mock_llm = MagicMock() wrapper = self._make_wrapper(mock_llm) with patch( "local_deep_research.utilities.llm_utils._close_base_llm", side_effect=RuntimeError("close failed"), ): # Should not raise wrapper.close() # --------------------------------------------------------------------------- # get_llm model/provider name cleaning # --------------------------------------------------------------------------- class TestGetLlmNameCleaning: def test_model_name_stripped_and_unquoted(self): """Model name with surrounding quotes/whitespace is cleaned.""" captured = {} def fake_setting(key, default=None, settings_snapshot=None): return { "llm.model": ' "gpt-4" ', "llm.temperature": 0.7, "llm.provider": "openai", "llm.openai.api_key": "sk-test", "llm.supports_max_tokens": False, "llm.context_window_unrestricted": True, "rate_limiting.llm_enabled": False, }.get(key, default) with ( patch(f"{MODULE}.is_llm_registered", return_value=False), patch( f"{MODULE}.get_setting_from_snapshot", side_effect=fake_setting ), patch( "langchain_openai.ChatOpenAI.__init__", return_value=None ) as mock_init, patch( f"{MODULE}.wrap_llm_without_think_tags", return_value=MagicMock(), ), ): try: from local_deep_research.config.llm_config import get_llm get_llm(settings_snapshot={"search.tool": "searxng"}) if mock_init.call_args: captured["model"] = mock_init.call_args.kwargs.get( "model", mock_init.call_args.args[0] if mock_init.call_args.args else None, ) except Exception: pass # ChatOpenAI init may fail, we just care about name cleaning