fix: add more timezone fixes (#3025)
This commit is contained in:
@@ -1246,6 +1246,7 @@ class Agent(BaseAgent):
|
||||
message_manager_size = self.message_manager.size(actor=self.user, agent_id=self.agent_state.id)
|
||||
external_memory_summary = compile_memory_metadata_block(
|
||||
memory_edit_timestamp=get_utc_time(),
|
||||
timezone=self.agent_state.timezone,
|
||||
previous_message_count=self.message_manager.size(actor=self.user, agent_id=self.agent_state.id),
|
||||
archival_memory_size=self.agent_manager.passage_size(actor=self.user, agent_id=self.agent_state.id),
|
||||
)
|
||||
|
||||
@@ -120,6 +120,7 @@ class BaseAgent(ABC):
|
||||
system_prompt=agent_state.system,
|
||||
in_context_memory=agent_state.memory,
|
||||
in_context_memory_last_edit=memory_edit_timestamp,
|
||||
timezone=agent_state.timezone,
|
||||
previous_message_count=num_messages - len(in_context_messages),
|
||||
archival_memory_size=num_archival_memories,
|
||||
tool_rules_solver=tool_rules_solver,
|
||||
|
||||
@@ -150,6 +150,7 @@ class VoiceAgent(BaseAgent):
|
||||
system_prompt=agent_state.system,
|
||||
in_context_memory=agent_state.memory,
|
||||
in_context_memory_last_edit=memory_edit_timestamp,
|
||||
timezone=agent_state.timezone,
|
||||
previous_message_count=self.num_messages,
|
||||
archival_memory_size=self.num_archival_memories,
|
||||
)
|
||||
|
||||
@@ -6,6 +6,7 @@ LETTA_DIR = os.path.join(os.path.expanduser("~"), ".letta")
|
||||
LETTA_TOOL_EXECUTION_DIR = os.path.join(LETTA_DIR, "tool_execution_dir")
|
||||
|
||||
LETTA_MODEL_ENDPOINT = "https://inference.letta.com"
|
||||
DEFAULT_TIMEZONE = "UTC"
|
||||
|
||||
ADMIN_PREFIX = "/v1/admin"
|
||||
API_PREFIX = "/v1"
|
||||
|
||||
@@ -2,11 +2,12 @@ import re
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timezone as dt_timezone
|
||||
from time import strftime
|
||||
from typing import Callable
|
||||
|
||||
import pytz
|
||||
|
||||
from letta.constants import DEFAULT_TIMEZONE
|
||||
|
||||
|
||||
def parse_formatted_time(formatted_time):
|
||||
# parse times returned by letta.utils.get_formatted_time()
|
||||
@@ -18,33 +19,22 @@ def datetime_to_timestamp(dt):
|
||||
return int(dt.timestamp())
|
||||
|
||||
|
||||
def get_local_time_military():
|
||||
# Get the current time in UTC
|
||||
def get_local_time_fast(timezone):
|
||||
# Get current UTC time and convert to the specified timezone
|
||||
if not timezone:
|
||||
return datetime.now().strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
current_time_utc = datetime.now(pytz.utc)
|
||||
|
||||
# Convert to San Francisco's time zone (PST/PDT)
|
||||
sf_time_zone = pytz.timezone("America/Los_Angeles")
|
||||
local_time = current_time_utc.astimezone(sf_time_zone)
|
||||
|
||||
# You may format it as you desire
|
||||
formatted_time = local_time.strftime("%Y-%m-%d %H:%M:%S %Z%z")
|
||||
local_time = current_time_utc.astimezone(pytz.timezone(timezone))
|
||||
formatted_time = local_time.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
|
||||
return formatted_time
|
||||
|
||||
|
||||
def get_local_time_fast():
|
||||
formatted_time = strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
|
||||
return formatted_time
|
||||
|
||||
|
||||
def get_local_time_timezone(timezone="America/Los_Angeles"):
|
||||
def get_local_time_timezone(timezone=DEFAULT_TIMEZONE):
|
||||
# Get the current time in UTC
|
||||
current_time_utc = datetime.now(pytz.utc)
|
||||
|
||||
# Convert to San Francisco's time zone (PST/PDT)
|
||||
sf_time_zone = pytz.timezone(timezone)
|
||||
local_time = current_time_utc.astimezone(sf_time_zone)
|
||||
local_time = current_time_utc.astimezone(pytz.timezone(timezone))
|
||||
|
||||
# You may format it as you desire, including AM/PM
|
||||
formatted_time = local_time.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
@@ -52,7 +42,7 @@ def get_local_time_timezone(timezone="America/Los_Angeles"):
|
||||
return formatted_time
|
||||
|
||||
|
||||
def get_local_time(timezone=None):
|
||||
def get_local_time(timezone=DEFAULT_TIMEZONE):
|
||||
if timezone is not None:
|
||||
time_str = get_local_time_timezone(timezone)
|
||||
else:
|
||||
@@ -89,8 +79,11 @@ def timestamp_to_datetime(timestamp_seconds: int) -> datetime:
|
||||
return datetime.fromtimestamp(timestamp_seconds, tz=dt_timezone.utc)
|
||||
|
||||
|
||||
def format_datetime(dt):
|
||||
return dt.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
def format_datetime(dt, timezone):
|
||||
if not timezone:
|
||||
# use local timezone
|
||||
return dt.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
return dt.astimezone(pytz.timezone(timezone)).strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
||||
|
||||
|
||||
def validate_date_format(date_str):
|
||||
|
||||
@@ -190,7 +190,6 @@ class Agent(SqlalchemyBase, OrganizationMixin, AsyncAttrs):
|
||||
"response_format": self.response_format,
|
||||
"last_run_completion": self.last_run_completion,
|
||||
"last_run_duration_ms": self.last_run_duration_ms,
|
||||
"timezone": self.timezone,
|
||||
# optional field defaults
|
||||
"tags": [],
|
||||
"tools": [],
|
||||
@@ -269,7 +268,6 @@ class Agent(SqlalchemyBase, OrganizationMixin, AsyncAttrs):
|
||||
"response_format": self.response_format,
|
||||
"last_run_completion": self.last_run_completion,
|
||||
"last_run_duration_ms": self.last_run_duration_ms,
|
||||
"timezone": self.timezone,
|
||||
}
|
||||
optional_fields = {
|
||||
"tags": [],
|
||||
|
||||
@@ -15,6 +15,7 @@ from letta.constants import (
|
||||
BASE_TOOLS,
|
||||
BASE_VOICE_SLEEPTIME_CHAT_TOOLS,
|
||||
BASE_VOICE_SLEEPTIME_TOOLS,
|
||||
DEFAULT_TIMEZONE,
|
||||
FILES_TOOLS,
|
||||
MULTI_AGENT_TOOLS,
|
||||
)
|
||||
@@ -481,7 +482,7 @@ class AgentManager:
|
||||
response_format=agent_create.response_format,
|
||||
created_by_id=actor.id,
|
||||
last_updated_by_id=actor.id,
|
||||
timezone=agent_create.timezone,
|
||||
timezone=agent_create.timezone if agent_create.timezone else DEFAULT_TIMEZONE,
|
||||
)
|
||||
|
||||
if _test_only_force_id:
|
||||
@@ -1429,6 +1430,7 @@ class AgentManager:
|
||||
system_prompt=agent_state.system,
|
||||
in_context_memory=agent_state.memory,
|
||||
in_context_memory_last_edit=memory_edit_timestamp,
|
||||
timezone=agent_state.timezone,
|
||||
previous_message_count=num_messages - len(agent_state.message_ids),
|
||||
archival_memory_size=num_archival_memories,
|
||||
)
|
||||
@@ -1503,6 +1505,7 @@ class AgentManager:
|
||||
system_prompt=agent_state.system,
|
||||
in_context_memory=agent_state.memory,
|
||||
in_context_memory_last_edit=memory_edit_timestamp,
|
||||
timezone=agent_state.timezone,
|
||||
previous_message_count=num_messages - len(agent_state.message_ids),
|
||||
archival_memory_size=num_archival_memories,
|
||||
tool_rules_solver=tool_rules_solver,
|
||||
|
||||
@@ -9,7 +9,7 @@ from letta import system
|
||||
from letta.constants import IN_CONTEXT_MEMORY_KEYWORD, MAX_EMBEDDING_DIM, STRUCTURED_OUTPUT_MODELS
|
||||
from letta.embeddings import embedding_model
|
||||
from letta.helpers import ToolRulesSolver
|
||||
from letta.helpers.datetime_helpers import get_local_time, get_local_time_fast
|
||||
from letta.helpers.datetime_helpers import format_datetime, get_local_time, get_local_time_fast
|
||||
from letta.orm import AgentPassage, SourcePassage, SourcesAgents
|
||||
from letta.orm.agent import Agent as AgentModel
|
||||
from letta.orm.agents_tags import AgentsTags
|
||||
@@ -179,17 +179,18 @@ def derive_system_message(agent_type: AgentType, enable_sleeptime: Optional[bool
|
||||
# TODO: This code is kind of wonky and deserves a rewrite
|
||||
def compile_memory_metadata_block(
|
||||
memory_edit_timestamp: datetime,
|
||||
timezone: str,
|
||||
previous_message_count: int = 0,
|
||||
archival_memory_size: int = 0,
|
||||
) -> str:
|
||||
# Put the timestamp in the local timezone (mimicking get_local_time())
|
||||
timestamp_str = memory_edit_timestamp.astimezone().strftime("%Y-%m-%d %I:%M:%S %p %Z%z").strip()
|
||||
timestamp_str = format_datetime(memory_edit_timestamp, timezone)
|
||||
|
||||
# Create a metadata block of info so the agent knows about the metadata of out-of-context memories
|
||||
memory_metadata_block = "\n".join(
|
||||
[
|
||||
"<memory_metadata>",
|
||||
f"- The current time is: {get_local_time_fast()}",
|
||||
f"- The current time is: {get_local_time_fast(timezone)}",
|
||||
f"- Memory blocks were last modified: {timestamp_str}",
|
||||
f"- {previous_message_count} previous messages between you and the user are stored in recall memory (use tools to access them)",
|
||||
f"- {archival_memory_size} total memories you created are stored in archival memory (use tools to access them)",
|
||||
@@ -224,6 +225,7 @@ def compile_system_message(
|
||||
system_prompt: str,
|
||||
in_context_memory: Memory,
|
||||
in_context_memory_last_edit: datetime, # TODO move this inside of BaseMemory?
|
||||
timezone: str,
|
||||
user_defined_variables: Optional[dict] = None,
|
||||
append_icm_if_missing: bool = True,
|
||||
template_format: Literal["f-string", "mustache", "jinja2"] = "f-string",
|
||||
@@ -258,6 +260,7 @@ def compile_system_message(
|
||||
memory_edit_timestamp=in_context_memory_last_edit,
|
||||
previous_message_count=previous_message_count,
|
||||
archival_memory_size=archival_memory_size,
|
||||
timezone=timezone,
|
||||
)
|
||||
full_memory_string = in_context_memory.compile(tool_usage_rules=tool_constraint_block) + "\n\n" + memory_metadata_string
|
||||
|
||||
@@ -303,6 +306,7 @@ def initialize_message_sequence(
|
||||
system_prompt=agent_state.system,
|
||||
in_context_memory=agent_state.memory,
|
||||
in_context_memory_last_edit=memory_edit_timestamp,
|
||||
timezone=agent_state.timezone,
|
||||
user_defined_variables=None,
|
||||
append_icm_if_missing=True,
|
||||
previous_message_count=previous_message_count,
|
||||
|
||||
Reference in New Issue
Block a user