Files
letta-server/letta/services/summarizer/summarizer_config.py
amysguan 7a4188dbda Add compaction settings to ADE (#9667)
* add compaction settings to ADE, add get default prompt for updated mode route

* update patch to auto set prompt on mode change, related ade changes

* reset api and update test

* feat: add compaction configuration translation keys for fr and cn

Add ADE/CompactionConfiguration translation keys to fr.json and cn.json
to match the new keys added in en.json.

Co-authored-by: Christina Tong <christinatong01@users.noreply.github.com>

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* type/translation/etc fixes

* fix typing

* update model selector path w/ change from main

* import mode from sdk

---------

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Letta <noreply@letta.com>
2026-03-03 18:34:02 -08:00

76 lines
3.3 KiB
Python

from typing import Literal
from pydantic import BaseModel, Field
from letta.prompts.summarizer_prompt import ALL_PROMPT, SELF_ALL_PROMPT, SELF_SLIDING_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",
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", "self_compact_all", "self_compact_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 == "self_compact_sliding_window":
return SELF_SLIDING_PROMPT
elif mode == "self_compact_all":
return SELF_ALL_PROMPT
elif mode == "sliding_window":
return SLIDING_PROMPT
else: # all
return ALL_PROMPT
class CompactionSettings(BaseModel):
"""Configuration for conversation compaction / summarization.
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 sliding_window/all 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_compact_all", "self_compact_sliding_window"] = 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 modes).",
)
# 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