Files
letta-server/letta/services/summarizer/summarizer_config.py
amysguan a101d5980d 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>
2026-02-24 10:55:12 -08:00

71 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import Literal
from pydantic import BaseModel, Field
from letta.prompts.summarizer_prompt import ALL_PROMPT, SLIDING_PROMPT
from letta.schemas.enums import ProviderType
from letta.schemas.model import ModelSettingsUnion
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-20251001",
ProviderType.openai: "openai/gpt-5-mini",
ProviderType.google_ai: "google_ai/gemini-2.5-flash",
}
return summarizer_defaults.get(provider_type)
def get_default_prompt_for_mode(mode: Literal["all", "sliding_window"]) -> str:
"""Get the default prompt for a given compaction mode.
Also used in /summarize endpoint if mode is changed and prompt is not explicitly set."""
if mode == "all":
return ALL_PROMPT
else: # sliding_window
return SLIDING_PROMPT
class CompactionSettings(BaseModel):
"""Configuration for conversation compaction / summarization.
``model`` is the only required user-facing field it specifies the summarizer
model handle (e.g. ``"openai/gpt-4o-mini"``). Per-model settings (temperature,
max tokens, etc.) are derived from the default configuration for that handle.
"""
# Summarizer model handle (provider/model-name).
# If None, uses lightweight provider-specific defaults (e.g., haiku for Anthropic, gpt-5-mini for OpenAI).
model: str | None = Field(
default=None,
description="Model handle to use for summarization (format: provider/model-name). If None, uses lightweight provider-specific defaults.",
)
# Optional provider-specific model settings for the summarizer model
model_settings: ModelSettingsUnion | None = Field(
default=None,
description="Optional model settings used to override defaults for the summarizer model.",
)
prompt: str | None = Field(default=None, description="The prompt to use for summarization. If None, uses mode-specific default.")
prompt_acknowledgement: bool = Field(
default=False, description="Whether to include an acknowledgement post-prompt (helps prevent non-summary outputs)."
)
clip_chars: int | None = Field(
default=50000, description="The maximum length of the summary in characters. If none, no clipping is performed."
)
mode: Literal["all", "sliding_window", "self"] = Field(default="sliding_window", description="The type of summarization technique use.")
sliding_window_percentage: float = Field(
default_factory=lambda: summarizer_settings.partial_evict_summarizer_percentage,
description="The percentage of the context window to keep post-summarization (only used in sliding window mode).",
)
# Called upon agent creation and if mode is changed in summarize endpoint request
def set_mode_specific_prompt(self):
"""Set mode-specific default prompt if none provided."""
if self.prompt is None:
self.prompt = get_default_prompt_for_mode(self.mode)
return self