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 <amy@letta.com>
This commit is contained in:
amysguan
2026-02-19 17:52:38 -08:00
committed by Caren Thomas
parent b29d063ba7
commit a101d5980d
3 changed files with 19 additions and 44 deletions

View File

@@ -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.

View File

@@ -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)

View File

@@ -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