feat: add compaction_settings to agents (#6625)
* initial commit * Add database migration for compaction_settings field This migration adds the compaction_settings column to the agents table to support customized summarization configuration for each agent. 🐾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix * rename * update apis * fix tests * update web test --------- Co-authored-by: Letta <noreply@letta.com> Co-authored-by: Kian Jones <kian@letta.com>
This commit is contained in:
committed by
Caren Thomas
parent
4309ecf606
commit
7ea297231a
@@ -618,12 +618,12 @@ async def test_summarize_multiple_large_tool_calls(server: SyncServer, actor, ll
|
||||
#
|
||||
|
||||
# ======================================================================================================================
|
||||
# SummarizerConfig Mode Tests (with pytest.patch) - Using LettaAgentV3
|
||||
# CompactionSettings Mode Tests (with pytest.patch) - Using LettaAgentV3
|
||||
# ======================================================================================================================
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from letta.services.summarizer.summarizer_config import SummarizerConfig, get_default_summarizer_config
|
||||
from letta.services.summarizer.summarizer_config import CompactionSettings, get_default_compaction_settings
|
||||
|
||||
# Test both summarizer modes: "all" summarizes entire history, "sliding_window" keeps recent messages
|
||||
SUMMARIZER_CONFIG_MODES: list[Literal["all", "sliding_window"]] = ["all", "sliding_window"]
|
||||
@@ -634,7 +634,7 @@ SUMMARIZER_CONFIG_MODES: list[Literal["all", "sliding_window"]] = ["all", "slidi
|
||||
@pytest.mark.parametrize("llm_config", TESTED_LLM_CONFIGS, ids=[c.model for c in TESTED_LLM_CONFIGS])
|
||||
async def test_summarize_with_mode(server: SyncServer, actor, llm_config: LLMConfig, mode: Literal["all", "sliding_window"]):
|
||||
"""
|
||||
Test summarization with different SummarizerConfig modes using LettaAgentV3.
|
||||
Test summarization with different CompactionSettings modes using LettaAgentV3.
|
||||
|
||||
This test verifies that both summarization modes work correctly:
|
||||
- "all": Summarizes the entire conversation history into a single summary
|
||||
@@ -674,11 +674,11 @@ async def test_summarize_with_mode(server: SyncServer, actor, llm_config: LLMCon
|
||||
# Persist the new messages
|
||||
new_letta_messages = await server.message_manager.create_many_messages_async(new_letta_messages, actor=actor)
|
||||
|
||||
# Create a custom SummarizerConfig with the desired mode
|
||||
def mock_get_default_summarizer_config(model_settings):
|
||||
config = get_default_summarizer_config(model_settings)
|
||||
# Create a custom CompactionSettings with the desired mode
|
||||
def mock_get_default_compaction_settings(model_settings):
|
||||
config = get_default_compaction_settings(model_settings)
|
||||
# Override the mode
|
||||
return SummarizerConfig(
|
||||
return CompactionSettings(
|
||||
model_settings=config.model_settings,
|
||||
prompt=config.prompt,
|
||||
prompt_acknowledgement=config.prompt_acknowledgement,
|
||||
@@ -687,7 +687,7 @@ async def test_summarize_with_mode(server: SyncServer, actor, llm_config: LLMCon
|
||||
sliding_window_percentage=config.sliding_window_percentage,
|
||||
)
|
||||
|
||||
with patch("letta.agents.letta_agent_v3.get_default_summarizer_config", mock_get_default_summarizer_config):
|
||||
with patch("letta.agents.letta_agent_v3.get_default_compaction_settings", mock_get_default_compaction_settings):
|
||||
agent_loop = LettaAgentV3(agent_state=agent_state, actor=actor)
|
||||
|
||||
summary, result = await agent_loop.compact(messages=in_context_messages)
|
||||
@@ -848,13 +848,13 @@ async def test_sliding_window_cutoff_index_does_not_exceed_message_count(server:
|
||||
the sliding window logic works with actual token counting.
|
||||
"""
|
||||
from letta.schemas.model import ModelSettings
|
||||
from letta.services.summarizer.summarizer_config import get_default_summarizer_config
|
||||
from letta.services.summarizer.summarizer_config import get_default_compaction_settings
|
||||
from letta.services.summarizer.summarizer_sliding_window import summarize_via_sliding_window
|
||||
|
||||
# Create a real summarizer config using the default factory
|
||||
# Override sliding_window_percentage to 0.3 for this test
|
||||
model_settings = ModelSettings() # Use defaults
|
||||
summarizer_config = get_default_summarizer_config(model_settings)
|
||||
summarizer_config = get_default_compaction_settings(model_settings)
|
||||
summarizer_config.sliding_window_percentage = 0.3
|
||||
|
||||
# Create 65 messages (similar to the failing case in the bug report)
|
||||
@@ -1401,11 +1401,11 @@ async def test_summarize_all(server: SyncServer, actor, llm_config: LLMConfig):
|
||||
"""
|
||||
from letta.schemas.model import ModelSettings
|
||||
from letta.services.summarizer.summarizer_all import summarize_all
|
||||
from letta.services.summarizer.summarizer_config import get_default_summarizer_config
|
||||
from letta.services.summarizer.summarizer_config import get_default_compaction_settings
|
||||
|
||||
# Create a summarizer config with "all" mode
|
||||
model_settings = ModelSettings()
|
||||
summarizer_config = get_default_summarizer_config(model_settings)
|
||||
summarizer_config = get_default_compaction_settings(model_settings)
|
||||
summarizer_config.mode = "all"
|
||||
|
||||
# Create test messages - a simple conversation
|
||||
|
||||
@@ -81,6 +81,7 @@ from letta.schemas.letta_stop_reason import LettaStopReason, StopReasonType
|
||||
from letta.schemas.llm_batch_job import AgentStepState, LLMBatchItem
|
||||
from letta.schemas.llm_config import LLMConfig
|
||||
from letta.schemas.message import Message as PydanticMessage, MessageCreate, MessageUpdate
|
||||
from letta.schemas.model import ModelSettings
|
||||
from letta.schemas.openai.chat_completion_response import UsageStatistics
|
||||
from letta.schemas.organization import Organization, Organization as PydanticOrganization, OrganizationUpdate
|
||||
from letta.schemas.passage import Passage as PydanticPassage
|
||||
@@ -96,6 +97,7 @@ from letta.server.server import SyncServer
|
||||
from letta.services.block_manager import BlockManager
|
||||
from letta.services.helpers.agent_manager_helper import calculate_base_tools, calculate_multi_agent_tools, validate_agent_exists_async
|
||||
from letta.services.step_manager import FeedbackType
|
||||
from letta.services.summarizer.summarizer_config import CompactionSettings
|
||||
from letta.settings import settings, tool_settings
|
||||
from letta.utils import calculate_file_defaults_based_on_context_window
|
||||
from tests.helpers.utils import comprehensive_agent_checks, validate_context_window_overview
|
||||
@@ -526,6 +528,91 @@ async def test_update_agent(server: SyncServer, comprehensive_test_agent_fixture
|
||||
assert updated_agent.updated_at > last_updated_timestamp
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_agent_with_compaction_settings(server: SyncServer, default_user, default_block):
|
||||
"""Test that agents can be created with custom compaction_settings"""
|
||||
# Upsert base tools
|
||||
await server.tool_manager.upsert_base_tools_async(actor=default_user)
|
||||
|
||||
# Create custom compaction settings
|
||||
llm_config = LLMConfig.default_config("gpt-4o-mini")
|
||||
model_settings = llm_config._to_model_settings()
|
||||
|
||||
compaction_settings = CompactionSettings(
|
||||
model_settings=model_settings,
|
||||
prompt="Custom summarization prompt",
|
||||
prompt_acknowledgement="Acknowledged",
|
||||
clip_chars=1500,
|
||||
mode="all",
|
||||
sliding_window_percentage=0.5,
|
||||
)
|
||||
|
||||
# Create agent with compaction settings
|
||||
create_agent_request = CreateAgent(
|
||||
name="test_compaction_agent",
|
||||
agent_type="memgpt_v2_agent",
|
||||
system="test system",
|
||||
llm_config=llm_config,
|
||||
embedding_config=EmbeddingConfig.default_config(provider="openai"),
|
||||
block_ids=[default_block.id],
|
||||
include_base_tools=True,
|
||||
compaction_settings=compaction_settings,
|
||||
)
|
||||
|
||||
created_agent = await server.agent_manager.create_agent_async(
|
||||
create_agent_request,
|
||||
actor=default_user,
|
||||
)
|
||||
|
||||
# Verify compaction settings were stored correctly
|
||||
assert created_agent.compaction_settings is not None
|
||||
assert created_agent.compaction_settings.mode == "all"
|
||||
assert created_agent.compaction_settings.clip_chars == 1500
|
||||
assert created_agent.compaction_settings.sliding_window_percentage == 0.5
|
||||
assert created_agent.compaction_settings.prompt == "Custom summarization prompt"
|
||||
assert created_agent.compaction_settings.prompt_acknowledgement == "Acknowledged"
|
||||
|
||||
# Clean up
|
||||
await server.agent_manager.delete_agent_async(agent_id=created_agent.id, actor=default_user)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_agent_compaction_settings(server: SyncServer, comprehensive_test_agent_fixture, default_user):
|
||||
"""Test that an agent's compaction_settings can be updated"""
|
||||
agent, _ = comprehensive_test_agent_fixture
|
||||
|
||||
# Verify initial state (should be None or default)
|
||||
assert agent.compaction_settings is None
|
||||
|
||||
# Create new compaction settings
|
||||
llm_config = LLMConfig.default_config("gpt-4o-mini")
|
||||
model_settings = llm_config._to_model_settings()
|
||||
|
||||
new_compaction_settings = CompactionSettings(
|
||||
model_settings=model_settings,
|
||||
prompt="Updated summarization prompt",
|
||||
prompt_acknowledgement="Updated acknowledgement",
|
||||
clip_chars=3000,
|
||||
mode="sliding_window",
|
||||
sliding_window_percentage=0.4,
|
||||
)
|
||||
|
||||
# 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.mode == "sliding_window"
|
||||
assert updated_agent.compaction_settings.clip_chars == 3000
|
||||
assert updated_agent.compaction_settings.sliding_window_percentage == 0.4
|
||||
assert updated_agent.compaction_settings.prompt == "Updated summarization prompt"
|
||||
assert updated_agent.compaction_settings.prompt_acknowledgement == "Updated acknowledgement"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
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"""
|
||||
@@ -1282,6 +1369,7 @@ async def test_agent_state_schema_unchanged(server: SyncServer):
|
||||
from letta.schemas.source import Source
|
||||
from letta.schemas.tool import Tool
|
||||
from letta.schemas.tool_rule import ToolRule
|
||||
from letta.services.summarizer.summarizer_config import CompactionSettings
|
||||
|
||||
# Define the expected schema structure
|
||||
expected_schema = {
|
||||
@@ -1298,6 +1386,7 @@ async def test_agent_state_schema_unchanged(server: SyncServer):
|
||||
"agent_type": AgentType,
|
||||
# LLM information
|
||||
"llm_config": LLMConfig,
|
||||
"compaction_settings": CompactionSettings,
|
||||
"model": str,
|
||||
"embedding": str,
|
||||
"embedding_config": EmbeddingConfig,
|
||||
|
||||
Reference in New Issue
Block a user