From a101d5980d26d2eb33c239c451831fa2d3b2225b Mon Sep 17 00:00:00 2001 From: amysguan <64990783+amysguan@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:52:38 -0800 Subject: [PATCH] Fix: load config for summarizer model from defaults instead of agent's config (#9568) * load default settings instead of loading from agent for summarizer config * update tests to allow use of get_llm_config_from_handle * remove nit comment --------- Co-authored-by: Amy Guan --- letta/services/summarizer/compact.py | 53 +++++-------------- .../services/summarizer/summarizer_config.py | 4 +- tests/managers/test_agent_manager.py | 6 ++- 3 files changed, 19 insertions(+), 44 deletions(-) diff --git a/letta/services/summarizer/compact.py b/letta/services/summarizer/compact.py index f3431fca..faf4782e 100644 --- a/letta/services/summarizer/compact.py +++ b/letta/services/summarizer/compact.py @@ -73,48 +73,21 @@ async def build_summarizer_llm_config( return agent_llm_config try: - # Parse provider/model from the handle, falling back to the agent's - # provider type when only a model name is given. - if "/" in summarizer_config.model: - provider_name, model_name = summarizer_config.model.split("/", 1) - else: - provider_name = agent_llm_config.provider_name - model_name = summarizer_config.model + # Load default config for the summarizer model handle, using the agent's context window + from letta.services.provider_manager import ProviderManager - # Start from the agent's config and override model + provider_name + handle - # Check if the summarizer's provider matches the agent's provider - # If they match, we can safely use the agent's config as a base - # If they don't match, we need to load the default config for the new provider - - provider_matches = False + provider_manager = ProviderManager() try: - # Check if provider_name is a valid ProviderType that matches agent's endpoint type - provider_type = ProviderType(provider_name) - provider_matches = provider_type.value == agent_llm_config.model_endpoint_type - except ValueError: - # provider_name is a custom label - check if it matches agent's provider_name - provider_matches = provider_name == agent_llm_config.provider_name - - if provider_matches: - # Same provider - use agent's config as base and override model/handle - base = agent_llm_config.model_copy() - base.model = model_name - base.handle = summarizer_config.model - else: - # Different provider - load default config for this handle - from letta.services.provider_manager import ProviderManager - - provider_manager = ProviderManager() - try: - base = await provider_manager.get_llm_config_from_handle( - handle=summarizer_config.model, - actor=actor, - ) - except Exception as e: - logger.warning( - f"Failed to load LLM config for summarizer handle '{summarizer_config.model}': {e}. Falling back to agent's LLM config." - ) - return agent_llm_config + # automatically sets the context window to the max available for the summarizer model + base = await provider_manager.get_llm_config_from_handle( + handle=summarizer_config.model, + actor=actor, + ) + except Exception as e: + logger.warning( + f"Failed to load LLM config for summarizer handle '{summarizer_config.model}': {e}. Falling back to agent's LLM config." + ) + return agent_llm_config # If explicit model_settings are provided for the summarizer, apply # them just like server.create_agent_async does for agents. diff --git a/letta/services/summarizer/summarizer_config.py b/letta/services/summarizer/summarizer_config.py index 18e7203b..a0e40e6b 100644 --- a/letta/services/summarizer/summarizer_config.py +++ b/letta/services/summarizer/summarizer_config.py @@ -11,9 +11,9 @@ from letta.settings import summarizer_settings def get_default_summarizer_model(provider_type: ProviderType) -> str | None: """Get default model for summarization for given provider type.""" summarizer_defaults = { - ProviderType.anthropic: "anthropic/claude-haiku-4-5", + ProviderType.anthropic: "anthropic/claude-haiku-4-5-20251001", ProviderType.openai: "openai/gpt-5-mini", - ProviderType.google_ai: "google_ai/gemini-2.0-flash", + ProviderType.google_ai: "google_ai/gemini-2.5-flash", } return summarizer_defaults.get(provider_type) diff --git a/tests/managers/test_agent_manager.py b/tests/managers/test_agent_manager.py index 073a5d34..7a08c61b 100644 --- a/tests/managers/test_agent_manager.py +++ b/tests/managers/test_agent_manager.py @@ -242,7 +242,7 @@ async def test_create_agent_with_model_handle_uses_correct_llm_config(server: Sy @pytest.mark.asyncio -async def test_compaction_settings_model_uses_separate_llm_config_for_summarization(default_user): +async def test_compaction_settings_model_uses_separate_llm_config_for_summarization(server: SyncServer, default_user): """When compaction_settings.model differs from the agent model, use a separate llm_config. This test exercises the summarization helpers directly to avoid external @@ -257,6 +257,8 @@ async def test_compaction_settings_model_uses_separate_llm_config_for_summarizat from letta.schemas.model import OpenAIModelSettings, OpenAIReasoning from letta.services.summarizer.compact import build_summarizer_llm_config + await server.init_async(init_with_default_org_and_user=True) + # Base agent LLM config base_llm_config = LLMConfig.default_config("gpt-4o-mini") assert base_llm_config.model == "gpt-4o-mini" @@ -382,7 +384,7 @@ async def test_create_agent_sets_default_compaction_model_anthropic(server: Sync # Should have default haiku model set assert agent.compaction_settings is not None - assert agent.compaction_settings.model == "anthropic/claude-haiku-4-5" + assert agent.compaction_settings.model == "anthropic/claude-haiku-4-5-20251001" @pytest.mark.asyncio