letta-nightly 0.6.25.dev20250213023354__py3-none-any.whl → 0.6.26.dev20250214013434__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of letta-nightly might be problematic. Click here for more details.
- letta/__init__.py +1 -1
- letta/agent.py +24 -6
- letta/cli/cli_config.py +3 -3
- letta/constants.py +1 -0
- letta/functions/function_sets/base.py +1 -1
- letta/functions/function_sets/extras.py +1 -1
- letta/functions/helpers.py +41 -12
- letta/helpers/composio_helpers.py +21 -0
- letta/helpers/datetime_helpers.py +90 -0
- letta/helpers/json_helpers.py +15 -0
- letta/interface.py +2 -1
- letta/llm_api/anthropic.py +1 -1
- letta/llm_api/cohere.py +3 -1
- letta/llm_api/google_ai.py +3 -1
- letta/llm_api/google_constants.py +12 -0
- letta/llm_api/google_vertex.py +3 -1
- letta/llm_api/helpers.py +2 -1
- letta/local_llm/chat_completion_proxy.py +3 -1
- letta/local_llm/function_parser.py +1 -1
- letta/local_llm/grammars/gbnf_grammar_generator.py +1 -1
- letta/local_llm/json_parser.py +1 -1
- letta/local_llm/llm_chat_completion_wrappers/airoboros.py +1 -2
- letta/local_llm/llm_chat_completion_wrappers/chatml.py +1 -1
- letta/local_llm/llm_chat_completion_wrappers/configurable_wrapper.py +1 -2
- letta/local_llm/llm_chat_completion_wrappers/dolphin.py +1 -2
- letta/local_llm/llm_chat_completion_wrappers/llama3.py +1 -1
- letta/local_llm/llm_chat_completion_wrappers/simple_summary_wrapper.py +1 -2
- letta/local_llm/llm_chat_completion_wrappers/zephyr.py +1 -2
- letta/local_llm/utils.py +1 -4
- letta/openai_backcompat/openai_object.py +1 -1
- letta/schemas/letta_response.py +1 -1
- letta/schemas/message.py +2 -1
- letta/schemas/organization.py +2 -1
- letta/schemas/passage.py +1 -1
- letta/server/rest_api/interface.py +1 -1
- letta/server/rest_api/routers/v1/tools.py +38 -39
- letta/server/server.py +7 -3
- letta/server/ws_api/protocol.py +1 -1
- letta/services/agent_manager.py +2 -1
- letta/services/helpers/agent_manager_helper.py +1 -1
- letta/services/job_manager.py +2 -1
- letta/services/sandbox_config_manager.py +1 -1
- letta/services/tool_execution_sandbox.py +1 -1
- letta/system.py +2 -1
- letta/utils.py +2 -103
- {letta_nightly-0.6.25.dev20250213023354.dist-info → letta_nightly-0.6.26.dev20250214013434.dist-info}/METADATA +3 -3
- {letta_nightly-0.6.25.dev20250213023354.dist-info → letta_nightly-0.6.26.dev20250214013434.dist-info}/RECORD +50 -46
- {letta_nightly-0.6.25.dev20250213023354.dist-info → letta_nightly-0.6.26.dev20250214013434.dist-info}/LICENSE +0 -0
- {letta_nightly-0.6.25.dev20250213023354.dist-info → letta_nightly-0.6.26.dev20250214013434.dist-info}/WHEEL +0 -0
- {letta_nightly-0.6.25.dev20250213023354.dist-info → letta_nightly-0.6.26.dev20250214013434.dist-info}/entry_points.txt +0 -0
letta/__init__.py
CHANGED
letta/agent.py
CHANGED
|
@@ -3,12 +3,13 @@ import time
|
|
|
3
3
|
import traceback
|
|
4
4
|
import warnings
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
|
-
from typing import List, Optional, Tuple, Union
|
|
6
|
+
from typing import Any, List, Optional, Tuple, Union
|
|
7
7
|
|
|
8
8
|
from openai.types.beta.function_tool import FunctionTool as OpenAITool
|
|
9
9
|
|
|
10
10
|
from letta.constants import (
|
|
11
11
|
CLI_WARNING_PREFIX,
|
|
12
|
+
COMPOSIO_ENTITY_ENV_VAR_KEY,
|
|
12
13
|
ERROR_MESSAGE_PREFIX,
|
|
13
14
|
FIRST_MESSAGE_ATTEMPTS,
|
|
14
15
|
FUNC_FAILED_HEARTBEAT_MESSAGE,
|
|
@@ -20,7 +21,11 @@ from letta.constants import (
|
|
|
20
21
|
from letta.errors import ContextWindowExceededError
|
|
21
22
|
from letta.functions.ast_parsers import coerce_dict_args_by_annotations, get_function_annotations_from_source
|
|
22
23
|
from letta.functions.functions import get_function_from_module
|
|
24
|
+
from letta.functions.helpers import execute_composio_action, generate_composio_action_from_func_name
|
|
23
25
|
from letta.helpers import ToolRulesSolver
|
|
26
|
+
from letta.helpers.composio_helpers import get_composio_api_key
|
|
27
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
28
|
+
from letta.helpers.json_helpers import json_dumps, json_loads
|
|
24
29
|
from letta.interface import AgentInterface
|
|
25
30
|
from letta.llm_api.helpers import calculate_summarizer_cutoff, get_token_counts_for_messages, is_context_overflow_error
|
|
26
31
|
from letta.llm_api.llm_api_tools import create
|
|
@@ -51,6 +56,7 @@ from letta.services.passage_manager import PassageManager
|
|
|
51
56
|
from letta.services.provider_manager import ProviderManager
|
|
52
57
|
from letta.services.step_manager import StepManager
|
|
53
58
|
from letta.services.tool_execution_sandbox import ToolExecutionSandbox
|
|
59
|
+
from letta.services.tool_manager import ToolManager
|
|
54
60
|
from letta.settings import summarizer_settings
|
|
55
61
|
from letta.streaming_interface import StreamingRefreshCLIInterface
|
|
56
62
|
from letta.system import get_heartbeat, get_token_limit_warning, package_function_response, package_summarize_message, package_user_message
|
|
@@ -58,9 +64,6 @@ from letta.utils import (
|
|
|
58
64
|
count_tokens,
|
|
59
65
|
get_friendly_error_msg,
|
|
60
66
|
get_tool_call_id,
|
|
61
|
-
get_utc_time,
|
|
62
|
-
json_dumps,
|
|
63
|
-
json_loads,
|
|
64
67
|
log_telemetry,
|
|
65
68
|
parse_json,
|
|
66
69
|
printd,
|
|
@@ -202,7 +205,7 @@ class Agent(BaseAgent):
|
|
|
202
205
|
|
|
203
206
|
def execute_tool_and_persist_state(
|
|
204
207
|
self, function_name: str, function_args: dict, target_letta_tool: Tool
|
|
205
|
-
) -> tuple[
|
|
208
|
+
) -> tuple[Any, Optional[SandboxRunResult]]:
|
|
206
209
|
"""
|
|
207
210
|
Execute tool modifications and persist the state of the agent.
|
|
208
211
|
Note: only some agent state modifications will be persisted, such as data in the AgentState ORM and block data
|
|
@@ -228,6 +231,18 @@ class Agent(BaseAgent):
|
|
|
228
231
|
function_args["agent_state"] = agent_state_copy # need to attach self to arg since it's dynamically linked
|
|
229
232
|
function_response = callable_func(**function_args)
|
|
230
233
|
self.update_memory_if_changed(agent_state_copy.memory)
|
|
234
|
+
elif target_letta_tool.tool_type == ToolType.EXTERNAL_COMPOSIO:
|
|
235
|
+
action_name = generate_composio_action_from_func_name(target_letta_tool.name)
|
|
236
|
+
# Get entity ID from the agent_state
|
|
237
|
+
entity_id = None
|
|
238
|
+
for env_var in self.agent_state.tool_exec_environment_variables:
|
|
239
|
+
if env_var.key == COMPOSIO_ENTITY_ENV_VAR_KEY:
|
|
240
|
+
entity_id = env_var.value
|
|
241
|
+
# Get composio_api_key
|
|
242
|
+
composio_api_key = get_composio_api_key(actor=self.user, logger=self.logger)
|
|
243
|
+
function_response = execute_composio_action(
|
|
244
|
+
action_name=action_name, args=function_args, api_key=composio_api_key, entity_id=entity_id
|
|
245
|
+
)
|
|
231
246
|
else:
|
|
232
247
|
# Parse the source code to extract function annotations
|
|
233
248
|
annotations = get_function_annotations_from_source(target_letta_tool.source_code, function_name)
|
|
@@ -460,7 +475,10 @@ class Agent(BaseAgent):
|
|
|
460
475
|
target_letta_tool = None
|
|
461
476
|
for t in self.agent_state.tools:
|
|
462
477
|
if t.name == function_name:
|
|
463
|
-
target_letta_tool
|
|
478
|
+
# This force refreshes the target_letta_tool from the database
|
|
479
|
+
# We only do this on name match to confirm that the agent state contains a specific tool with the right name
|
|
480
|
+
target_letta_tool = ToolManager().get_tool_by_name(tool_name=function_name, actor=self.user)
|
|
481
|
+
break
|
|
464
482
|
|
|
465
483
|
if not target_letta_tool:
|
|
466
484
|
error_msg = f"No function named {function_name}"
|
letta/cli/cli_config.py
CHANGED
|
@@ -8,7 +8,7 @@ import typer
|
|
|
8
8
|
from prettytable.colortable import ColorTable, Themes
|
|
9
9
|
from tqdm import tqdm
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
import letta.helpers.datetime_helpers
|
|
12
12
|
|
|
13
13
|
app = typer.Typer()
|
|
14
14
|
|
|
@@ -51,7 +51,7 @@ def list(arg: Annotated[ListChoice, typer.Argument]):
|
|
|
51
51
|
agent.memory.get_block("persona").value[:100] + "...",
|
|
52
52
|
agent.memory.get_block("human").value[:100] + "...",
|
|
53
53
|
",".join(source_names),
|
|
54
|
-
|
|
54
|
+
letta.helpers.datetime_helpers.format_datetime(agent.created_at),
|
|
55
55
|
]
|
|
56
56
|
)
|
|
57
57
|
print(table)
|
|
@@ -84,7 +84,7 @@ def list(arg: Annotated[ListChoice, typer.Argument]):
|
|
|
84
84
|
source.description,
|
|
85
85
|
source.embedding_config.embedding_model,
|
|
86
86
|
source.embedding_config.embedding_dim,
|
|
87
|
-
|
|
87
|
+
letta.helpers.datetime_helpers.format_datetime(source.created_at),
|
|
88
88
|
]
|
|
89
89
|
)
|
|
90
90
|
|
letta/constants.py
CHANGED
|
@@ -33,7 +33,7 @@ def conversation_search(self: "Agent", query: str, page: Optional[int] = 0) -> O
|
|
|
33
33
|
import math
|
|
34
34
|
|
|
35
35
|
from letta.constants import RETRIEVAL_QUERY_DEFAULT_PAGE_SIZE
|
|
36
|
-
from letta.
|
|
36
|
+
from letta.helpers.json_helpers import json_dumps
|
|
37
37
|
|
|
38
38
|
if page is None or (isinstance(page, str) and page.lower().strip() == "none"):
|
|
39
39
|
page = 0
|
|
@@ -5,9 +5,9 @@ from typing import Optional
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
7
|
from letta.constants import MESSAGE_CHATGPT_FUNCTION_MODEL, MESSAGE_CHATGPT_FUNCTION_SYSTEM_MESSAGE
|
|
8
|
+
from letta.helpers.json_helpers import json_dumps, json_loads
|
|
8
9
|
from letta.llm_api.llm_api_tools import create
|
|
9
10
|
from letta.schemas.message import Message, TextContent
|
|
10
|
-
from letta.utils import json_dumps, json_loads
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def message_chatgpt(self, message: str):
|
letta/functions/helpers.py
CHANGED
|
@@ -52,24 +52,53 @@ def generate_composio_tool_wrapper(action_name: str) -> tuple[str, str]:
|
|
|
52
52
|
# Generate func name
|
|
53
53
|
func_name = generate_func_name_from_composio_action(action_name)
|
|
54
54
|
|
|
55
|
-
wrapper_function_str = f"""
|
|
55
|
+
wrapper_function_str = f"""\
|
|
56
56
|
def {func_name}(**kwargs):
|
|
57
|
-
|
|
57
|
+
raise RuntimeError("Something went wrong - we should never be using the persisted source code for Composio. Please reach out to Letta team")
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
# Compile safety check
|
|
61
|
+
assert_code_gen_compilable(wrapper_function_str.strip())
|
|
62
|
+
|
|
63
|
+
return func_name, wrapper_function_str.strip()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def execute_composio_action(
|
|
67
|
+
action_name: str, args: dict, api_key: Optional[str] = None, entity_id: Optional[str] = None
|
|
68
|
+
) -> tuple[str, str]:
|
|
58
69
|
import os
|
|
59
70
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
from composio.exceptions import (
|
|
72
|
+
ApiKeyNotProvidedError,
|
|
73
|
+
ComposioSDKError,
|
|
74
|
+
ConnectedAccountNotFoundError,
|
|
75
|
+
EnumMetadataNotFound,
|
|
76
|
+
EnumStringNotFound,
|
|
77
|
+
)
|
|
78
|
+
from composio_langchain import ComposioToolSet
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
entity_id = entity_id or os.getenv(COMPOSIO_ENTITY_ENV_VAR_KEY, DEFAULT_ENTITY_ID)
|
|
81
|
+
try:
|
|
82
|
+
composio_toolset = ComposioToolSet(api_key=api_key, entity_id=entity_id)
|
|
83
|
+
response = composio_toolset.execute_action(action=action_name, params=args)
|
|
84
|
+
except ApiKeyNotProvidedError:
|
|
85
|
+
raise RuntimeError(
|
|
86
|
+
f"Composio API key is missing for action '{action_name}'. "
|
|
87
|
+
"Please set the sandbox environment variables either through the ADE or the API."
|
|
88
|
+
)
|
|
89
|
+
except ConnectedAccountNotFoundError:
|
|
90
|
+
raise RuntimeError(f"No connected account was found for action '{action_name}'. " "Please link an account and try again.")
|
|
91
|
+
except EnumStringNotFound as e:
|
|
92
|
+
raise RuntimeError(f"Invalid value provided for action '{action_name}': " + str(e) + ". Please check the action parameters.")
|
|
93
|
+
except EnumMetadataNotFound as e:
|
|
94
|
+
raise RuntimeError(f"Invalid value provided for action '{action_name}': " + str(e) + ". Please check the action parameters.")
|
|
95
|
+
except ComposioSDKError as e:
|
|
96
|
+
raise RuntimeError(f"An unexpected error occurred in Composio SDK while executing action '{action_name}': " + str(e))
|
|
68
97
|
|
|
69
|
-
|
|
70
|
-
|
|
98
|
+
if response["error"]:
|
|
99
|
+
raise RuntimeError(f"Error while executing action '{action_name}': " + str(response["error"]))
|
|
71
100
|
|
|
72
|
-
return
|
|
101
|
+
return response["data"]
|
|
73
102
|
|
|
74
103
|
|
|
75
104
|
def generate_langchain_tool_wrapper(
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from logging import Logger
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from letta.schemas.user import User
|
|
5
|
+
from letta.services.sandbox_config_manager import SandboxConfigManager
|
|
6
|
+
from letta.settings import tool_settings
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_composio_api_key(actor: User, logger: Logger) -> Optional[str]:
|
|
10
|
+
api_keys = SandboxConfigManager().list_sandbox_env_vars_by_key(key="COMPOSIO_API_KEY", actor=actor)
|
|
11
|
+
if not api_keys:
|
|
12
|
+
logger.warning(f"No API keys found for Composio. Defaulting to the environment variable...")
|
|
13
|
+
if tool_settings.composio_api_key:
|
|
14
|
+
return tool_settings.composio_api_key
|
|
15
|
+
else:
|
|
16
|
+
return None
|
|
17
|
+
else:
|
|
18
|
+
# TODO: Add more protections around this
|
|
19
|
+
# Ideally, not tied to a specific sandbox, but for now we just get the first one
|
|
20
|
+
# Theoretically possible for someone to have different composio api keys per sandbox
|
|
21
|
+
return api_keys[0].value
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from datetime import datetime, timedelta, timezone
|
|
3
|
+
|
|
4
|
+
import pytz
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def parse_formatted_time(formatted_time):
|
|
8
|
+
# parse times returned by letta.utils.get_formatted_time()
|
|
9
|
+
return datetime.strptime(formatted_time, "%Y-%m-%d %I:%M:%S %p %Z%z")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def datetime_to_timestamp(dt):
|
|
13
|
+
# convert datetime object to integer timestamp
|
|
14
|
+
return int(dt.timestamp())
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def timestamp_to_datetime(ts):
|
|
18
|
+
# convert integer timestamp to datetime object
|
|
19
|
+
return datetime.fromtimestamp(ts)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_local_time_military():
|
|
23
|
+
# Get the current time in UTC
|
|
24
|
+
current_time_utc = datetime.now(pytz.utc)
|
|
25
|
+
|
|
26
|
+
# Convert to San Francisco's time zone (PST/PDT)
|
|
27
|
+
sf_time_zone = pytz.timezone("America/Los_Angeles")
|
|
28
|
+
local_time = current_time_utc.astimezone(sf_time_zone)
|
|
29
|
+
|
|
30
|
+
# You may format it as you desire
|
|
31
|
+
formatted_time = local_time.strftime("%Y-%m-%d %H:%M:%S %Z%z")
|
|
32
|
+
|
|
33
|
+
return formatted_time
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_local_time_timezone(timezone="America/Los_Angeles"):
|
|
37
|
+
# Get the current time in UTC
|
|
38
|
+
current_time_utc = datetime.now(pytz.utc)
|
|
39
|
+
|
|
40
|
+
# Convert to San Francisco's time zone (PST/PDT)
|
|
41
|
+
sf_time_zone = pytz.timezone(timezone)
|
|
42
|
+
local_time = current_time_utc.astimezone(sf_time_zone)
|
|
43
|
+
|
|
44
|
+
# You may format it as you desire, including AM/PM
|
|
45
|
+
formatted_time = local_time.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
|
46
|
+
|
|
47
|
+
return formatted_time
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_local_time(timezone=None):
|
|
51
|
+
if timezone is not None:
|
|
52
|
+
time_str = get_local_time_timezone(timezone)
|
|
53
|
+
else:
|
|
54
|
+
# Get the current time, which will be in the local timezone of the computer
|
|
55
|
+
local_time = datetime.now().astimezone()
|
|
56
|
+
|
|
57
|
+
# You may format it as you desire, including AM/PM
|
|
58
|
+
time_str = local_time.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
|
59
|
+
|
|
60
|
+
return time_str.strip()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_utc_time() -> datetime:
|
|
64
|
+
"""Get the current UTC time"""
|
|
65
|
+
# return datetime.now(pytz.utc)
|
|
66
|
+
return datetime.now(timezone.utc)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def format_datetime(dt):
|
|
70
|
+
return dt.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def validate_date_format(date_str):
|
|
74
|
+
"""Validate the given date string in the format 'YYYY-MM-DD'."""
|
|
75
|
+
try:
|
|
76
|
+
datetime.strptime(date_str, "%Y-%m-%d")
|
|
77
|
+
return True
|
|
78
|
+
except (ValueError, TypeError):
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def extract_date_from_timestamp(timestamp):
|
|
83
|
+
"""Extracts and returns the date from the given timestamp."""
|
|
84
|
+
# Extracts the date (ignoring the time and timezone)
|
|
85
|
+
match = re.match(r"(\d{4}-\d{2}-\d{2})", timestamp)
|
|
86
|
+
return match.group(1) if match else None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def is_utc_datetime(dt: datetime) -> bool:
|
|
90
|
+
return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) == timedelta(0)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def json_loads(data):
|
|
6
|
+
return json.loads(data, strict=False)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def json_dumps(data, indent=2):
|
|
10
|
+
def safe_serializer(obj):
|
|
11
|
+
if isinstance(obj, datetime):
|
|
12
|
+
return obj.isoformat()
|
|
13
|
+
raise TypeError(f"Type {type(obj)} not serializable")
|
|
14
|
+
|
|
15
|
+
return json.dumps(data, indent=indent, default=safe_serializer, ensure_ascii=False)
|
letta/interface.py
CHANGED
|
@@ -5,9 +5,10 @@ from typing import List, Optional
|
|
|
5
5
|
from colorama import Fore, Style, init
|
|
6
6
|
|
|
7
7
|
from letta.constants import CLI_WARNING_PREFIX
|
|
8
|
+
from letta.helpers.json_helpers import json_loads
|
|
8
9
|
from letta.local_llm.constants import ASSISTANT_MESSAGE_CLI_SYMBOL, INNER_THOUGHTS_CLI_SYMBOL
|
|
9
10
|
from letta.schemas.message import Message
|
|
10
|
-
from letta.utils import
|
|
11
|
+
from letta.utils import printd
|
|
11
12
|
|
|
12
13
|
init(autoreset=True)
|
|
13
14
|
|
letta/llm_api/anthropic.py
CHANGED
|
@@ -18,6 +18,7 @@ from anthropic.types.beta import (
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
from letta.errors import BedrockError, BedrockPermissionError
|
|
21
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
21
22
|
from letta.llm_api.aws_bedrock import get_bedrock_client
|
|
22
23
|
from letta.llm_api.helpers import add_inner_thoughts_to_functions
|
|
23
24
|
from letta.local_llm.constants import INNER_THOUGHTS_KWARG, INNER_THOUGHTS_KWARG_DESCRIPTION
|
|
@@ -39,7 +40,6 @@ from letta.schemas.openai.chat_completion_response import MessageDelta, ToolCall
|
|
|
39
40
|
from letta.services.provider_manager import ProviderManager
|
|
40
41
|
from letta.settings import model_settings
|
|
41
42
|
from letta.streaming_interface import AgentChunkStreamingInterface, AgentRefreshStreamingInterface
|
|
42
|
-
from letta.utils import get_utc_time
|
|
43
43
|
|
|
44
44
|
BASE_URL = "https://api.anthropic.com/v1"
|
|
45
45
|
|
letta/llm_api/cohere.py
CHANGED
|
@@ -4,6 +4,8 @@ from typing import List, Optional, Union
|
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
8
|
+
from letta.helpers.json_helpers import json_dumps
|
|
7
9
|
from letta.local_llm.utils import count_tokens
|
|
8
10
|
from letta.schemas.message import Message
|
|
9
11
|
from letta.schemas.openai.chat_completion_request import ChatCompletionRequest, Tool
|
|
@@ -12,7 +14,7 @@ from letta.schemas.openai.chat_completion_response import (
|
|
|
12
14
|
Message as ChoiceMessage, # NOTE: avoid conflict with our own Letta Message datatype
|
|
13
15
|
)
|
|
14
16
|
from letta.schemas.openai.chat_completion_response import ToolCall, UsageStatistics
|
|
15
|
-
from letta.utils import get_tool_call_id,
|
|
17
|
+
from letta.utils import get_tool_call_id, smart_urljoin
|
|
16
18
|
|
|
17
19
|
BASE_URL = "https://api.cohere.ai/v1"
|
|
18
20
|
|
letta/llm_api/google_ai.py
CHANGED
|
@@ -4,12 +4,14 @@ from typing import List, Optional, Tuple
|
|
|
4
4
|
import requests
|
|
5
5
|
|
|
6
6
|
from letta.constants import NON_USER_MSG_PREFIX
|
|
7
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
8
|
+
from letta.helpers.json_helpers import json_dumps
|
|
7
9
|
from letta.llm_api.helpers import make_post_request
|
|
8
10
|
from letta.local_llm.json_parser import clean_json_string_extra_backslash
|
|
9
11
|
from letta.local_llm.utils import count_tokens
|
|
10
12
|
from letta.schemas.openai.chat_completion_request import Tool
|
|
11
13
|
from letta.schemas.openai.chat_completion_response import ChatCompletionResponse, Choice, FunctionCall, Message, ToolCall, UsageStatistics
|
|
12
|
-
from letta.utils import get_tool_call_id
|
|
14
|
+
from letta.utils import get_tool_call_id
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def get_gemini_endpoint_and_headers(
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
GOOGLE_MODEL_TO_CONTEXT_LENGTH = {
|
|
2
|
+
"gemini-2.0-flash-001": 1048576,
|
|
3
|
+
"gemini-2.0-pro-exp-02-05": 2097152,
|
|
4
|
+
"gemini-2.0-flash-lite-preview-02-05": 1048576,
|
|
5
|
+
"gemini-2.0-flash-thinking-exp-01-21": 1048576,
|
|
6
|
+
"gemini-1.5-flash": 1048576,
|
|
7
|
+
"gemini-1.5-pro": 2097152,
|
|
8
|
+
"gemini-1.0-pro": 32760,
|
|
9
|
+
"gemini-1.0-pro-vision": 16384,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
GOOGLE_EMBEDING_MODEL_TO_DIM = {"text-embedding-005": 768, "text-multilingual-embedding-002": 768}
|
letta/llm_api/google_vertex.py
CHANGED
|
@@ -2,11 +2,13 @@ import uuid
|
|
|
2
2
|
from typing import List, Optional
|
|
3
3
|
|
|
4
4
|
from letta.constants import NON_USER_MSG_PREFIX
|
|
5
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
6
|
+
from letta.helpers.json_helpers import json_dumps
|
|
5
7
|
from letta.local_llm.json_parser import clean_json_string_extra_backslash
|
|
6
8
|
from letta.local_llm.utils import count_tokens
|
|
7
9
|
from letta.schemas.openai.chat_completion_request import Tool
|
|
8
10
|
from letta.schemas.openai.chat_completion_response import ChatCompletionResponse, Choice, FunctionCall, Message, ToolCall, UsageStatistics
|
|
9
|
-
from letta.utils import get_tool_call_id
|
|
11
|
+
from letta.utils import get_tool_call_id
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
def add_dummy_model_messages(messages: List[dict]) -> List[dict]:
|
letta/llm_api/helpers.py
CHANGED
|
@@ -7,10 +7,11 @@ from typing import Any, List, Union
|
|
|
7
7
|
import requests
|
|
8
8
|
|
|
9
9
|
from letta.constants import OPENAI_CONTEXT_WINDOW_ERROR_SUBSTRING
|
|
10
|
+
from letta.helpers.json_helpers import json_dumps
|
|
10
11
|
from letta.schemas.message import Message
|
|
11
12
|
from letta.schemas.openai.chat_completion_response import ChatCompletionResponse, Choice
|
|
12
13
|
from letta.settings import summarizer_settings
|
|
13
|
-
from letta.utils import count_tokens,
|
|
14
|
+
from letta.utils import count_tokens, printd
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def _convert_to_structured_output_helper(property: dict) -> dict:
|
|
@@ -6,6 +6,8 @@ import requests
|
|
|
6
6
|
|
|
7
7
|
from letta.constants import CLI_WARNING_PREFIX
|
|
8
8
|
from letta.errors import LocalLLMConnectionError, LocalLLMError
|
|
9
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
10
|
+
from letta.helpers.json_helpers import json_dumps
|
|
9
11
|
from letta.local_llm.constants import DEFAULT_WRAPPER
|
|
10
12
|
from letta.local_llm.function_parser import patch_function
|
|
11
13
|
from letta.local_llm.grammars.gbnf_grammar_generator import create_dynamic_model_from_function, generate_gbnf_grammar_and_documentation
|
|
@@ -20,7 +22,7 @@ from letta.local_llm.webui.api import get_webui_completion
|
|
|
20
22
|
from letta.local_llm.webui.legacy_api import get_webui_completion as get_webui_completion_legacy
|
|
21
23
|
from letta.prompts.gpt_summarize import SYSTEM as SUMMARIZE_SYSTEM_MESSAGE
|
|
22
24
|
from letta.schemas.openai.chat_completion_response import ChatCompletionResponse, Choice, Message, ToolCall, UsageStatistics
|
|
23
|
-
from letta.utils import get_tool_call_id
|
|
25
|
+
from letta.utils import get_tool_call_id
|
|
24
26
|
|
|
25
27
|
has_shown_warning = False
|
|
26
28
|
grammar_supported_backends = ["koboldcpp", "llamacpp", "webui", "webui-legacy"]
|
|
@@ -10,7 +10,7 @@ from typing import Any, Callable, List, Optional, Tuple, Type, Union, _GenericAl
|
|
|
10
10
|
from docstring_parser import parse
|
|
11
11
|
from pydantic import BaseModel, create_model
|
|
12
12
|
|
|
13
|
-
from letta.
|
|
13
|
+
from letta.helpers.json_helpers import json_dumps
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class PydanticDataType(Enum):
|
letta/local_llm/json_parser.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from letta.errors import LLMJSONParsingError
|
|
2
|
+
from letta.helpers.json_helpers import json_dumps, json_loads
|
|
2
3
|
from letta.local_llm.json_parser import clean_json
|
|
3
4
|
from letta.local_llm.llm_chat_completion_wrappers.wrapper_base import LLMChatCompletionWrapper
|
|
4
5
|
from letta.schemas.enums import MessageRole
|
|
5
|
-
from letta.utils import json_dumps, json_loads
|
|
6
6
|
|
|
7
7
|
PREFIX_HINT = """# Reminders:
|
|
8
8
|
# Important information about yourself and the user is stored in (limited) core memory
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from letta.errors import LLMJSONParsingError
|
|
2
|
+
from letta.helpers.json_helpers import json_dumps, json_loads
|
|
2
3
|
from letta.local_llm.json_parser import clean_json
|
|
3
4
|
from letta.local_llm.llm_chat_completion_wrappers.wrapper_base import LLMChatCompletionWrapper
|
|
4
|
-
from letta.utils import json_dumps, json_loads
|
|
5
5
|
|
|
6
6
|
PREFIX_HINT = """# Reminders:
|
|
7
7
|
# Important information about yourself and the user is stored in (limited) core memory
|
letta/local_llm/utils.py
CHANGED
|
@@ -249,10 +249,7 @@ def num_tokens_from_messages(messages: List[dict], model: str = "gpt-4") -> int:
|
|
|
249
249
|
# num_tokens += len(encoding.encode(value["arguments"]))
|
|
250
250
|
|
|
251
251
|
else:
|
|
252
|
-
if value is None:
|
|
253
|
-
# raise ValueError(f"Message has null value: {key} with value: {value} - message={message}")
|
|
254
|
-
warnings.warn(f"Message has null value: {key} with value: {value} - message={message}")
|
|
255
|
-
else:
|
|
252
|
+
if value is not None:
|
|
256
253
|
if not isinstance(value, str):
|
|
257
254
|
raise ValueError(f"Message has non-string value: {key} with value: {value} - message={message}")
|
|
258
255
|
num_tokens += len(encoding.encode(value))
|
letta/schemas/letta_response.py
CHANGED
|
@@ -5,10 +5,10 @@ from typing import List, Union
|
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
|
+
from letta.helpers.json_helpers import json_dumps
|
|
8
9
|
from letta.schemas.enums import MessageStreamStatus
|
|
9
10
|
from letta.schemas.letta_message import LettaMessage, LettaMessageUnion
|
|
10
11
|
from letta.schemas.usage import LettaUsageStatistics
|
|
11
|
-
from letta.utils import json_dumps
|
|
12
12
|
|
|
13
13
|
# TODO: consider moving into own file
|
|
14
14
|
|
letta/schemas/message.py
CHANGED
|
@@ -12,6 +12,8 @@ from openai.types.chat.chat_completion_message_tool_call import Function as Open
|
|
|
12
12
|
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
13
13
|
|
|
14
14
|
from letta.constants import DEFAULT_MESSAGE_TOOL, DEFAULT_MESSAGE_TOOL_KWARG, TOOL_CALL_ID_MAX_LEN
|
|
15
|
+
from letta.helpers.datetime_helpers import get_utc_time, is_utc_datetime
|
|
16
|
+
from letta.helpers.json_helpers import json_dumps
|
|
15
17
|
from letta.local_llm.constants import INNER_THOUGHTS_KWARG
|
|
16
18
|
from letta.schemas.enums import MessageContentType, MessageRole
|
|
17
19
|
from letta.schemas.letta_base import OrmMetadataBase
|
|
@@ -28,7 +30,6 @@ from letta.schemas.letta_message import (
|
|
|
28
30
|
UserMessage,
|
|
29
31
|
)
|
|
30
32
|
from letta.system import unpack_message
|
|
31
|
-
from letta.utils import get_utc_time, is_utc_datetime, json_dumps
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
def add_inner_thoughts_to_tool_call(
|
letta/schemas/organization.py
CHANGED
|
@@ -3,8 +3,9 @@ from typing import Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import Field
|
|
5
5
|
|
|
6
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
6
7
|
from letta.schemas.letta_base import LettaBase
|
|
7
|
-
from letta.utils import create_random_username
|
|
8
|
+
from letta.utils import create_random_username
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class OrganizationBase(LettaBase):
|
letta/schemas/passage.py
CHANGED
|
@@ -4,9 +4,9 @@ from typing import Dict, List, Optional
|
|
|
4
4
|
from pydantic import Field, field_validator
|
|
5
5
|
|
|
6
6
|
from letta.constants import MAX_EMBEDDING_DIM
|
|
7
|
+
from letta.helpers.datetime_helpers import get_utc_time
|
|
7
8
|
from letta.schemas.embedding_config import EmbeddingConfig
|
|
8
9
|
from letta.schemas.letta_base import OrmMetadataBase
|
|
9
|
-
from letta.utils import get_utc_time
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class PassageBase(OrmMetadataBase):
|