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>
This commit is contained in:
amysguan
2026-03-02 10:02:57 -08:00
committed by Caren Thomas
parent 612a2ae98b
commit 7a4188dbda
3 changed files with 93 additions and 4 deletions

View File

@@ -24,8 +24,7 @@ from letta.constants import (
INCLUDE_MODEL_KEYWORDS_BASE_TOOL_RULES, INCLUDE_MODEL_KEYWORDS_BASE_TOOL_RULES,
RETRIEVAL_QUERY_DEFAULT_PAGE_SIZE, RETRIEVAL_QUERY_DEFAULT_PAGE_SIZE,
) )
from letta.errors import LettaError
from letta.errors import LettaAgentNotFoundError, LettaError, LettaInvalidArgumentError
from letta.helpers import ToolRulesSolver from letta.helpers import ToolRulesSolver
from letta.helpers.datetime_helpers import get_utc_time from letta.helpers.datetime_helpers import get_utc_time
from letta.log import get_logger from letta.log import get_logger
@@ -789,6 +788,21 @@ class AgentManager:
agent.agent_type, agent.agent_type,
) )
# Upsert compaction_settings: merge incoming partial update with existing settings
if agent_update.compaction_settings is not None:
# If mode changed, update the prompt to the default for the new mode
if agent.compaction_settings is not None and agent_update.compaction_settings.mode != agent.compaction_settings.mode:
from letta.services.summarizer.summarizer_config import get_default_prompt_for_mode
agent_update.compaction_settings.prompt = get_default_prompt_for_mode(agent_update.compaction_settings.mode)
# Fill in unchanged fields from existing settings
if agent.compaction_settings is not None:
changed_fields = agent_update.compaction_settings.model_fields_set
for field in agent.compaction_settings.model_fields:
if field not in changed_fields:
setattr(agent_update.compaction_settings, field, getattr(agent.compaction_settings, field))
scalar_updates = { scalar_updates = {
"name": agent_update.name, "name": agent_update.name,
"system": agent_update.system, "system": agent_update.system,

View File

@@ -11,7 +11,7 @@ from letta.settings import summarizer_settings
def get_default_summarizer_model(provider_type: ProviderType) -> str | None: def get_default_summarizer_model(provider_type: ProviderType) -> str | None:
"""Get default model for summarization for given provider type.""" """Get default model for summarization for given provider type."""
summarizer_defaults = { summarizer_defaults = {
ProviderType.anthropic: "anthropic/claude-haiku-4-5-20251001", ProviderType.anthropic: "anthropic/claude-haiku-4-5",
ProviderType.openai: "openai/gpt-5-mini", ProviderType.openai: "openai/gpt-5-mini",
ProviderType.google_ai: "google_ai/gemini-2.5-flash", ProviderType.google_ai: "google_ai/gemini-2.5-flash",
} }

View File

@@ -366,6 +366,8 @@ async def test_compaction_settings_model_uses_separate_llm_config_for_summarizat
async def test_create_agent_sets_default_compaction_model_anthropic(server: SyncServer, default_user): async def test_create_agent_sets_default_compaction_model_anthropic(server: SyncServer, default_user):
"""When no compaction_settings provided for Anthropic agent, default haiku model should be set.""" """When no compaction_settings provided for Anthropic agent, default haiku model should be set."""
from letta.schemas.agent import CreateAgent from letta.schemas.agent import CreateAgent
from letta.schemas.enums import ProviderType
from letta.services.summarizer.summarizer_config import get_default_summarizer_model
await server.init_async(init_with_default_org_and_user=True) await server.init_async(init_with_default_org_and_user=True)
@@ -384,7 +386,7 @@ async def test_create_agent_sets_default_compaction_model_anthropic(server: Sync
# Should have default haiku model set # Should have default haiku model set
assert agent.compaction_settings is not None assert agent.compaction_settings is not None
assert agent.compaction_settings.model == "anthropic/claude-haiku-4-5-20251001" assert agent.compaction_settings.model == get_default_summarizer_model(ProviderType.anthropic)
@pytest.mark.asyncio @pytest.mark.asyncio
@@ -808,6 +810,79 @@ async def test_update_agent_compaction_settings(server: SyncServer, comprehensiv
assert updated_agent.compaction_settings.prompt_acknowledgement == False assert updated_agent.compaction_settings.prompt_acknowledgement == False
@pytest.mark.asyncio
async def test_update_agent_partial_compaction_settings(server: SyncServer, comprehensive_test_agent_fixture, default_user):
"""Test that an agent's compaction_settings can be upserted."""
from letta.services.summarizer.summarizer_config import get_default_prompt_for_mode
agent, _ = comprehensive_test_agent_fixture
# Create new compaction settings
original_compaction_settings = agent.compaction_settings.model_copy()
new_compaction_settings = CompactionSettings(
mode="all",
prompt_acknowledgement=True,
clip_chars=3000,
)
# Update agent with compaction settings
update_agent_request = UpdateAgent(
compaction_settings=new_compaction_settings,
)
updated_agent = await server.agent_manager.update_agent_async(agent.id, update_agent_request, actor=default_user)
# Verify compaction settings were updated correctly
assert updated_agent.compaction_settings is not None
assert updated_agent.compaction_settings.model == original_compaction_settings.model
assert updated_agent.compaction_settings.model_settings == original_compaction_settings.model_settings
assert updated_agent.compaction_settings.sliding_window_percentage == original_compaction_settings.sliding_window_percentage
assert updated_agent.compaction_settings.mode == "all"
assert updated_agent.compaction_settings.clip_chars == 3000
assert updated_agent.compaction_settings.prompt == get_default_prompt_for_mode("all")
assert updated_agent.compaction_settings.prompt_acknowledgement == True
@pytest.mark.asyncio
async def test_update_agent_partial_compaction_settings_same_mode(server: SyncServer, comprehensive_test_agent_fixture, default_user):
"""Test that if the mode stays the same without a prompt passed in, the prompt is not updated."""
agent, _ = comprehensive_test_agent_fixture
update_agent_request = UpdateAgent(
compaction_settings=CompactionSettings(mode="sliding_window", prompt="This is a fake prompt."),
)
updated_agent = await server.agent_manager.update_agent_async(agent.id, update_agent_request, actor=default_user)
assert updated_agent.compaction_settings is not None
assert updated_agent.compaction_settings.prompt == "This is a fake prompt."
# Create new compaction settings
original_compaction_settings = updated_agent.compaction_settings.model_copy()
new_compaction_settings = CompactionSettings(
mode="sliding_window",
model="openai/gpt-4o-mini",
)
# Update agent with compaction settings
update_agent_request = UpdateAgent(
compaction_settings=new_compaction_settings,
)
final_agent = await server.agent_manager.update_agent_async(updated_agent.id, update_agent_request, actor=default_user)
# Verify compaction settings were updated correctly
assert final_agent.compaction_settings is not None
assert final_agent.compaction_settings.sliding_window_percentage == original_compaction_settings.sliding_window_percentage
assert final_agent.compaction_settings.prompt == original_compaction_settings.prompt
assert final_agent.compaction_settings.clip_chars == original_compaction_settings.clip_chars
assert final_agent.compaction_settings.prompt_acknowledgement == original_compaction_settings.prompt_acknowledgement
assert final_agent.compaction_settings.mode == "sliding_window"
assert final_agent.compaction_settings.model == "openai/gpt-4o-mini"
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_agent_file_defaults_based_on_context_window(server: SyncServer, default_user, default_block): async def test_agent_file_defaults_based_on_context_window(server: SyncServer, default_user, default_block):
"""Test that file-related defaults are set based on the model's context window size""" """Test that file-related defaults are set based on the model's context window size"""