feat: background multi-agent group for sleeptime agent (#1508)
This commit is contained in:
@@ -1,12 +1,28 @@
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete
|
||||
|
||||
from letta.config import LettaConfig
|
||||
from letta.constants import BASE_MEMORY_TOOLS, BASE_TOOLS
|
||||
from letta.functions.functions import parse_source_code
|
||||
from letta.functions.schema_generator import generate_schema
|
||||
from letta.orm import Provider, Step
|
||||
from letta.schemas.agent import CreateAgent
|
||||
from letta.schemas.block import CreateBlock
|
||||
from letta.schemas.group import DynamicManager, GroupCreate, GroupUpdate, ManagerType, RoundRobinManager, SupervisorManager
|
||||
from letta.schemas.block import Block, CreateBlock
|
||||
from letta.schemas.enums import JobStatus
|
||||
from letta.schemas.group import (
|
||||
BackgroundManager,
|
||||
DynamicManager,
|
||||
GroupCreate,
|
||||
GroupUpdate,
|
||||
ManagerType,
|
||||
RoundRobinManager,
|
||||
SupervisorManager,
|
||||
)
|
||||
from letta.schemas.message import MessageCreate
|
||||
from letta.schemas.tool import Tool
|
||||
from letta.schemas.tool_rule import TerminalToolRule
|
||||
from letta.server.server import SyncServer
|
||||
|
||||
|
||||
@@ -426,3 +442,129 @@ async def test_dynamic_group_chat(server, actor, manager_agent, participant_agen
|
||||
|
||||
finally:
|
||||
server.group_manager.delete_group(group_id=group.id, actor=actor)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_background_group_chat(server, actor):
|
||||
# 1. create shared block
|
||||
shared_memory_block = server.block_manager.create_or_update_block(
|
||||
Block(
|
||||
label="human",
|
||||
value="",
|
||||
limit=1000,
|
||||
),
|
||||
actor=actor,
|
||||
)
|
||||
|
||||
# 2. create main agent
|
||||
main_agent = server.create_agent(
|
||||
request=CreateAgent(
|
||||
name="main_agent",
|
||||
memory_blocks=[
|
||||
CreateBlock(
|
||||
label="persona",
|
||||
value="You are a personal assistant that helps users with requests.",
|
||||
),
|
||||
],
|
||||
model="openai/gpt-4o-mini",
|
||||
embedding="openai/text-embedding-ada-002",
|
||||
include_base_tools=False,
|
||||
tools=BASE_TOOLS,
|
||||
),
|
||||
actor=actor,
|
||||
)
|
||||
|
||||
# 3. create background memory agent
|
||||
def skip_memory_update():
|
||||
"""
|
||||
Perform no memory updates. This function is used when the transcript
|
||||
does not require any changes to the memory.
|
||||
"""
|
||||
|
||||
skip_memory_update = Tool(
|
||||
name=skip_memory_update.__name__,
|
||||
description="",
|
||||
source_type="python",
|
||||
tags=[],
|
||||
source_code=parse_source_code(skip_memory_update),
|
||||
json_schema=generate_schema(skip_memory_update, None),
|
||||
)
|
||||
skip_memory_update = server.tool_manager.create_or_update_tool(
|
||||
pydantic_tool=skip_memory_update,
|
||||
actor=actor,
|
||||
)
|
||||
|
||||
background_memory_agent = server.create_agent(
|
||||
request=CreateAgent(
|
||||
name="memory_agent",
|
||||
memory_blocks=[
|
||||
CreateBlock(
|
||||
label="persona",
|
||||
value="You manage memory for the main agent. You are a background agent and you are not expected to respond to messages. When you receive a conversation snippet from the main thread, perform memory updates only if there are meaningful changes, and otherwise call the skip_memory_update tool.",
|
||||
),
|
||||
],
|
||||
model="openai/gpt-4o-mini",
|
||||
embedding="openai/text-embedding-ada-002",
|
||||
include_base_tools=False,
|
||||
include_base_tool_rules=False,
|
||||
tools=BASE_MEMORY_TOOLS + [skip_memory_update.name],
|
||||
tool_rules=[
|
||||
TerminalToolRule(tool_name="core_memory_append"),
|
||||
TerminalToolRule(tool_name="core_memory_replace"),
|
||||
TerminalToolRule(tool_name="skip_memory_update"),
|
||||
],
|
||||
),
|
||||
actor=actor,
|
||||
)
|
||||
|
||||
# 4. create group
|
||||
group = server.group_manager.create_group(
|
||||
group=GroupCreate(
|
||||
description="",
|
||||
agent_ids=[background_memory_agent.id],
|
||||
manager_config=BackgroundManager(
|
||||
manager_agent_id=main_agent.id,
|
||||
background_agents_interval=2,
|
||||
),
|
||||
shared_block_ids=[shared_memory_block.id],
|
||||
),
|
||||
actor=actor,
|
||||
)
|
||||
|
||||
agents = server.block_manager.get_agents_for_block(block_id=shared_memory_block.id, actor=actor)
|
||||
assert len(agents) == 2
|
||||
|
||||
message_text = [
|
||||
"my favorite color is orange",
|
||||
"not particularly. today is a good day",
|
||||
"actually my favorite color is coral",
|
||||
"sorry gotta run",
|
||||
]
|
||||
run_ids = []
|
||||
for i, text in enumerate(message_text):
|
||||
response = await server.send_message_to_agent(
|
||||
agent_id=main_agent.id,
|
||||
actor=actor,
|
||||
messages=[
|
||||
MessageCreate(
|
||||
role="user",
|
||||
content=text,
|
||||
),
|
||||
],
|
||||
stream_steps=False,
|
||||
stream_tokens=False,
|
||||
)
|
||||
|
||||
assert len(response.messages) > 0
|
||||
assert len(response.usage.run_ids) == i % 2
|
||||
run_ids.extend(response.usage.run_ids)
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
for run_id in run_ids:
|
||||
job = server.job_manager.get_job_by_id(job_id=run_id, actor=actor)
|
||||
assert job.status == JobStatus.completed
|
||||
|
||||
server.group_manager.delete_group(group_id=group.id, actor=actor)
|
||||
server.agent_manager.delete_agent(agent_id=background_memory_agent.id, actor=actor)
|
||||
server.agent_manager.delete_agent(agent_id=main_agent.id, actor=actor)
|
||||
|
||||
Reference in New Issue
Block a user