letta-nightly 0.4.1.dev20241007104134__py3-none-any.whl → 0.4.1.dev20241009104130__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/agent.py +36 -10
- letta/client/client.py +8 -1
- letta/credentials.py +3 -3
- letta/errors.py +1 -1
- letta/functions/schema_generator.py +1 -1
- letta/llm_api/anthropic.py +3 -24
- letta/llm_api/azure_openai.py +53 -108
- letta/llm_api/azure_openai_constants.py +10 -0
- letta/llm_api/google_ai.py +39 -64
- letta/llm_api/helpers.py +208 -0
- letta/llm_api/llm_api_tools.py +43 -218
- letta/llm_api/openai.py +74 -50
- letta/main.py +1 -1
- letta/metadata.py +2 -0
- letta/providers.py +144 -31
- letta/schemas/agent.py +14 -0
- letta/schemas/llm_config.py +2 -2
- letta/schemas/openai/chat_completion_response.py +3 -0
- letta/schemas/tool.py +3 -3
- letta/server/rest_api/admin/tools.py +0 -1
- letta/server/rest_api/app.py +1 -17
- letta/server/rest_api/routers/openai/assistants/threads.py +10 -7
- letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +5 -3
- letta/server/rest_api/routers/v1/agents.py +23 -13
- letta/server/rest_api/routers/v1/blocks.py +5 -3
- letta/server/rest_api/routers/v1/jobs.py +5 -3
- letta/server/rest_api/routers/v1/sources.py +25 -13
- letta/server/rest_api/routers/v1/tools.py +12 -7
- letta/server/server.py +33 -37
- letta/settings.py +5 -113
- {letta_nightly-0.4.1.dev20241007104134.dist-info → letta_nightly-0.4.1.dev20241009104130.dist-info}/METADATA +1 -1
- {letta_nightly-0.4.1.dev20241007104134.dist-info → letta_nightly-0.4.1.dev20241009104130.dist-info}/RECORD +35 -33
- {letta_nightly-0.4.1.dev20241007104134.dist-info → letta_nightly-0.4.1.dev20241009104130.dist-info}/LICENSE +0 -0
- {letta_nightly-0.4.1.dev20241007104134.dist-info → letta_nightly-0.4.1.dev20241009104130.dist-info}/WHEEL +0 -0
- {letta_nightly-0.4.1.dev20241007104134.dist-info → letta_nightly-0.4.1.dev20241009104130.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import List, Optional
|
|
2
2
|
|
|
3
|
-
from fastapi import APIRouter, Depends, Query
|
|
3
|
+
from fastapi import APIRouter, Depends, Header, Query
|
|
4
4
|
|
|
5
5
|
from letta.schemas.job import Job
|
|
6
6
|
from letta.server.rest_api.utils import get_letta_server
|
|
@@ -13,11 +13,12 @@ router = APIRouter(prefix="/jobs", tags=["jobs"])
|
|
|
13
13
|
def list_jobs(
|
|
14
14
|
server: "SyncServer" = Depends(get_letta_server),
|
|
15
15
|
source_id: Optional[str] = Query(None, description="Only list jobs associated with the source."),
|
|
16
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
16
17
|
):
|
|
17
18
|
"""
|
|
18
19
|
List all jobs.
|
|
19
20
|
"""
|
|
20
|
-
actor = server.
|
|
21
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
21
22
|
|
|
22
23
|
# TODO: add filtering by status
|
|
23
24
|
jobs = server.list_jobs(user_id=actor.id)
|
|
@@ -33,11 +34,12 @@ def list_jobs(
|
|
|
33
34
|
@router.get("/active", response_model=List[Job], operation_id="list_active_jobs")
|
|
34
35
|
def list_active_jobs(
|
|
35
36
|
server: "SyncServer" = Depends(get_letta_server),
|
|
37
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
36
38
|
):
|
|
37
39
|
"""
|
|
38
40
|
List all active jobs.
|
|
39
41
|
"""
|
|
40
|
-
actor = server.
|
|
42
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
41
43
|
|
|
42
44
|
return server.list_active_jobs(user_id=actor.id)
|
|
43
45
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import tempfile
|
|
3
|
-
from typing import List
|
|
3
|
+
from typing import List, Optional
|
|
4
4
|
|
|
5
|
-
from fastapi import APIRouter, BackgroundTasks, Depends, Query, UploadFile
|
|
5
|
+
from fastapi import APIRouter, BackgroundTasks, Depends, Header, Query, UploadFile
|
|
6
6
|
|
|
7
7
|
from letta.schemas.document import Document
|
|
8
8
|
from letta.schemas.job import Job
|
|
@@ -21,11 +21,12 @@ router = APIRouter(prefix="/sources", tags=["sources"])
|
|
|
21
21
|
def get_source(
|
|
22
22
|
source_id: str,
|
|
23
23
|
server: "SyncServer" = Depends(get_letta_server),
|
|
24
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
24
25
|
):
|
|
25
26
|
"""
|
|
26
27
|
Get all sources
|
|
27
28
|
"""
|
|
28
|
-
actor = server.
|
|
29
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
29
30
|
|
|
30
31
|
return server.get_source(source_id=source_id, user_id=actor.id)
|
|
31
32
|
|
|
@@ -34,11 +35,12 @@ def get_source(
|
|
|
34
35
|
def get_source_id_by_name(
|
|
35
36
|
source_name: str,
|
|
36
37
|
server: "SyncServer" = Depends(get_letta_server),
|
|
38
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
37
39
|
):
|
|
38
40
|
"""
|
|
39
41
|
Get a source by name
|
|
40
42
|
"""
|
|
41
|
-
actor = server.
|
|
43
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
42
44
|
|
|
43
45
|
source_id = server.get_source_id(source_name=source_name, user_id=actor.id)
|
|
44
46
|
return source_id
|
|
@@ -47,11 +49,12 @@ def get_source_id_by_name(
|
|
|
47
49
|
@router.get("/", response_model=List[Source], operation_id="list_sources")
|
|
48
50
|
def list_sources(
|
|
49
51
|
server: "SyncServer" = Depends(get_letta_server),
|
|
52
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
50
53
|
):
|
|
51
54
|
"""
|
|
52
55
|
List all data sources created by a user.
|
|
53
56
|
"""
|
|
54
|
-
actor = server.
|
|
57
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
55
58
|
|
|
56
59
|
return server.list_all_sources(user_id=actor.id)
|
|
57
60
|
|
|
@@ -60,11 +63,12 @@ def list_sources(
|
|
|
60
63
|
def create_source(
|
|
61
64
|
source: SourceCreate,
|
|
62
65
|
server: "SyncServer" = Depends(get_letta_server),
|
|
66
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
63
67
|
):
|
|
64
68
|
"""
|
|
65
69
|
Create a new data source.
|
|
66
70
|
"""
|
|
67
|
-
actor = server.
|
|
71
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
68
72
|
|
|
69
73
|
return server.create_source(request=source, user_id=actor.id)
|
|
70
74
|
|
|
@@ -74,11 +78,13 @@ def update_source(
|
|
|
74
78
|
source_id: str,
|
|
75
79
|
source: SourceUpdate,
|
|
76
80
|
server: "SyncServer" = Depends(get_letta_server),
|
|
81
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
77
82
|
):
|
|
78
83
|
"""
|
|
79
84
|
Update the name or documentation of an existing data source.
|
|
80
85
|
"""
|
|
81
|
-
actor = server.
|
|
86
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
87
|
+
|
|
82
88
|
assert source.id == source_id, "Source ID in path must match ID in request body"
|
|
83
89
|
|
|
84
90
|
return server.update_source(request=source, user_id=actor.id)
|
|
@@ -88,11 +94,12 @@ def update_source(
|
|
|
88
94
|
def delete_source(
|
|
89
95
|
source_id: str,
|
|
90
96
|
server: "SyncServer" = Depends(get_letta_server),
|
|
97
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
91
98
|
):
|
|
92
99
|
"""
|
|
93
100
|
Delete a data source.
|
|
94
101
|
"""
|
|
95
|
-
actor = server.
|
|
102
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
96
103
|
|
|
97
104
|
server.delete_source(source_id=source_id, user_id=actor.id)
|
|
98
105
|
|
|
@@ -102,11 +109,12 @@ def attach_source_to_agent(
|
|
|
102
109
|
source_id: str,
|
|
103
110
|
agent_id: str = Query(..., description="The unique identifier of the agent to attach the source to."),
|
|
104
111
|
server: "SyncServer" = Depends(get_letta_server),
|
|
112
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
105
113
|
):
|
|
106
114
|
"""
|
|
107
115
|
Attach a data source to an existing agent.
|
|
108
116
|
"""
|
|
109
|
-
actor = server.
|
|
117
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
110
118
|
|
|
111
119
|
source = server.ms.get_source(source_id=source_id, user_id=actor.id)
|
|
112
120
|
assert source is not None, f"Source with id={source_id} not found."
|
|
@@ -119,11 +127,12 @@ def detach_source_from_agent(
|
|
|
119
127
|
source_id: str,
|
|
120
128
|
agent_id: str = Query(..., description="The unique identifier of the agent to detach the source from."),
|
|
121
129
|
server: "SyncServer" = Depends(get_letta_server),
|
|
130
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
122
131
|
) -> None:
|
|
123
132
|
"""
|
|
124
133
|
Detach a data source from an existing agent.
|
|
125
134
|
"""
|
|
126
|
-
actor = server.
|
|
135
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
127
136
|
|
|
128
137
|
return server.detach_source_from_agent(source_id=source_id, agent_id=agent_id, user_id=actor.id)
|
|
129
138
|
|
|
@@ -134,11 +143,12 @@ def upload_file_to_source(
|
|
|
134
143
|
source_id: str,
|
|
135
144
|
background_tasks: BackgroundTasks,
|
|
136
145
|
server: "SyncServer" = Depends(get_letta_server),
|
|
146
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
137
147
|
):
|
|
138
148
|
"""
|
|
139
149
|
Upload a file to a data source.
|
|
140
150
|
"""
|
|
141
|
-
actor = server.
|
|
151
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
142
152
|
|
|
143
153
|
source = server.ms.get_source(source_id=source_id, user_id=actor.id)
|
|
144
154
|
assert source is not None, f"Source with id={source_id} not found."
|
|
@@ -166,11 +176,12 @@ def upload_file_to_source(
|
|
|
166
176
|
def list_passages(
|
|
167
177
|
source_id: str,
|
|
168
178
|
server: SyncServer = Depends(get_letta_server),
|
|
179
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
169
180
|
):
|
|
170
181
|
"""
|
|
171
182
|
List all passages associated with a data source.
|
|
172
183
|
"""
|
|
173
|
-
actor = server.
|
|
184
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
174
185
|
passages = server.list_data_source_passages(user_id=actor.id, source_id=source_id)
|
|
175
186
|
return passages
|
|
176
187
|
|
|
@@ -179,11 +190,12 @@ def list_passages(
|
|
|
179
190
|
def list_documents(
|
|
180
191
|
source_id: str,
|
|
181
192
|
server: "SyncServer" = Depends(get_letta_server),
|
|
193
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
182
194
|
):
|
|
183
195
|
"""
|
|
184
196
|
List all documents associated with a data source.
|
|
185
197
|
"""
|
|
186
|
-
actor = server.
|
|
198
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
187
199
|
|
|
188
200
|
documents = server.list_data_source_documents(user_id=actor.id, source_id=source_id)
|
|
189
201
|
return documents
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from typing import List
|
|
1
|
+
from typing import List, Optional
|
|
2
2
|
|
|
3
|
-
from fastapi import APIRouter, Body, Depends, HTTPException
|
|
3
|
+
from fastapi import APIRouter, Body, Depends, Header, HTTPException
|
|
4
4
|
|
|
5
5
|
from letta.schemas.tool import Tool, ToolCreate, ToolUpdate
|
|
6
6
|
from letta.server.rest_api.utils import get_letta_server
|
|
@@ -13,11 +13,12 @@ router = APIRouter(prefix="/tools", tags=["tools"])
|
|
|
13
13
|
def delete_tool(
|
|
14
14
|
tool_id: str,
|
|
15
15
|
server: SyncServer = Depends(get_letta_server),
|
|
16
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
16
17
|
):
|
|
17
18
|
"""
|
|
18
19
|
Delete a tool by name
|
|
19
20
|
"""
|
|
20
|
-
# actor = server.
|
|
21
|
+
# actor = server.get_user_or_default(user_id=user_id)
|
|
21
22
|
server.delete_tool(tool_id=tool_id)
|
|
22
23
|
|
|
23
24
|
|
|
@@ -42,11 +43,12 @@ def get_tool(
|
|
|
42
43
|
def get_tool_id(
|
|
43
44
|
tool_name: str,
|
|
44
45
|
server: SyncServer = Depends(get_letta_server),
|
|
46
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
45
47
|
):
|
|
46
48
|
"""
|
|
47
49
|
Get a tool ID by name
|
|
48
50
|
"""
|
|
49
|
-
actor = server.
|
|
51
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
50
52
|
|
|
51
53
|
tool_id = server.get_tool_id(tool_name, user_id=actor.id)
|
|
52
54
|
if tool_id is None:
|
|
@@ -58,11 +60,12 @@ def get_tool_id(
|
|
|
58
60
|
@router.get("/", response_model=List[Tool], operation_id="list_tools")
|
|
59
61
|
def list_all_tools(
|
|
60
62
|
server: SyncServer = Depends(get_letta_server),
|
|
63
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
61
64
|
):
|
|
62
65
|
"""
|
|
63
66
|
Get a list of all tools available to agents created by a user
|
|
64
67
|
"""
|
|
65
|
-
actor = server.
|
|
68
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
66
69
|
actor.id
|
|
67
70
|
|
|
68
71
|
# TODO: add back when user-specific
|
|
@@ -75,11 +78,12 @@ def create_tool(
|
|
|
75
78
|
tool: ToolCreate = Body(...),
|
|
76
79
|
update: bool = False,
|
|
77
80
|
server: SyncServer = Depends(get_letta_server),
|
|
81
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
78
82
|
):
|
|
79
83
|
"""
|
|
80
84
|
Create a new tool
|
|
81
85
|
"""
|
|
82
|
-
actor = server.
|
|
86
|
+
actor = server.get_user_or_default(user_id=user_id)
|
|
83
87
|
|
|
84
88
|
return server.create_tool(
|
|
85
89
|
request=tool,
|
|
@@ -94,10 +98,11 @@ def update_tool(
|
|
|
94
98
|
tool_id: str,
|
|
95
99
|
request: ToolUpdate = Body(...),
|
|
96
100
|
server: SyncServer = Depends(get_letta_server),
|
|
101
|
+
user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
|
97
102
|
):
|
|
98
103
|
"""
|
|
99
104
|
Update an existing tool
|
|
100
105
|
"""
|
|
101
106
|
assert tool_id == request.id, "Tool ID in path must match tool ID in request body"
|
|
102
|
-
server.
|
|
107
|
+
# actor = server.get_user_or_default(user_id=user_id)
|
|
103
108
|
return server.update_tool(request)
|
letta/server/server.py
CHANGED
|
@@ -45,12 +45,13 @@ from letta.metadata import MetadataStore
|
|
|
45
45
|
from letta.prompts import gpt_system
|
|
46
46
|
from letta.providers import (
|
|
47
47
|
AnthropicProvider,
|
|
48
|
+
AzureProvider,
|
|
48
49
|
GoogleAIProvider,
|
|
49
50
|
OllamaProvider,
|
|
50
51
|
OpenAIProvider,
|
|
51
52
|
VLLMProvider,
|
|
52
53
|
)
|
|
53
|
-
from letta.schemas.agent import AgentState, CreateAgent, UpdateAgentState
|
|
54
|
+
from letta.schemas.agent import AgentState, AgentType, CreateAgent, UpdateAgentState
|
|
54
55
|
from letta.schemas.api_key import APIKey, APIKeyCreate
|
|
55
56
|
from letta.schemas.block import (
|
|
56
57
|
Block,
|
|
@@ -270,6 +271,14 @@ class SyncServer(Server):
|
|
|
270
271
|
self._enabled_providers.append(VLLMProvider(base_url=model_settings.vllm_base_url))
|
|
271
272
|
if model_settings.gemini_api_key:
|
|
272
273
|
self._enabled_providers.append(GoogleAIProvider(api_key=model_settings.gemini_api_key))
|
|
274
|
+
if model_settings.azure_api_key and model_settings.azure_base_url:
|
|
275
|
+
self._enabled_providers.append(
|
|
276
|
+
AzureProvider(
|
|
277
|
+
api_key=model_settings.azure_api_key,
|
|
278
|
+
base_url=model_settings.azure_base_url,
|
|
279
|
+
api_version=model_settings.azure_api_version,
|
|
280
|
+
)
|
|
281
|
+
)
|
|
273
282
|
|
|
274
283
|
def save_agents(self):
|
|
275
284
|
"""Saves all the agents that are in the in-memory object store"""
|
|
@@ -332,7 +341,10 @@ class SyncServer(Server):
|
|
|
332
341
|
# Make sure the memory is a memory object
|
|
333
342
|
assert isinstance(agent_state.memory, Memory)
|
|
334
343
|
|
|
335
|
-
|
|
344
|
+
if agent_state.agent_type == AgentType.memgpt_agent:
|
|
345
|
+
letta_agent = Agent(agent_state=agent_state, interface=interface, tools=tool_objs)
|
|
346
|
+
else:
|
|
347
|
+
raise NotImplementedError("Only base agents are supported as of right now!")
|
|
336
348
|
|
|
337
349
|
# Add the agent to the in-memory store and return its reference
|
|
338
350
|
logger.debug(f"Adding agent to the agent cache: user_id={user_id}, agent_id={agent_id}")
|
|
@@ -596,7 +608,7 @@ class SyncServer(Server):
|
|
|
596
608
|
)
|
|
597
609
|
|
|
598
610
|
# Run the agent state forward
|
|
599
|
-
usage = self._step(user_id=user_id, agent_id=agent_id, input_message=
|
|
611
|
+
usage = self._step(user_id=user_id, agent_id=agent_id, input_message=message, timestamp=timestamp)
|
|
600
612
|
return usage
|
|
601
613
|
|
|
602
614
|
def system_message(
|
|
@@ -784,6 +796,7 @@ class SyncServer(Server):
|
|
|
784
796
|
name=request.name,
|
|
785
797
|
user_id=user_id,
|
|
786
798
|
tools=request.tools if request.tools else [],
|
|
799
|
+
agent_type=request.agent_type or AgentType.memgpt_agent,
|
|
787
800
|
llm_config=llm_config,
|
|
788
801
|
embedding_config=embedding_config,
|
|
789
802
|
system=request.system,
|
|
@@ -1064,7 +1077,11 @@ class SyncServer(Server):
|
|
|
1064
1077
|
|
|
1065
1078
|
def get_user(self, user_id: str) -> User:
|
|
1066
1079
|
"""Get the user"""
|
|
1067
|
-
|
|
1080
|
+
user = self.ms.get_user(user_id=user_id)
|
|
1081
|
+
if user is None:
|
|
1082
|
+
raise ValueError(f"User with user_id {user_id} does not exist")
|
|
1083
|
+
else:
|
|
1084
|
+
return user
|
|
1068
1085
|
|
|
1069
1086
|
def get_agent_memory(self, agent_id: str) -> Memory:
|
|
1070
1087
|
"""Return the memory of an agent (core memory)"""
|
|
@@ -1880,20 +1897,6 @@ class SyncServer(Server):
|
|
|
1880
1897
|
letta_agent = self._get_or_load_agent(agent_id=agent_id)
|
|
1881
1898
|
return letta_agent.retry_message()
|
|
1882
1899
|
|
|
1883
|
-
def set_current_user(self, user_id: Optional[str]):
|
|
1884
|
-
"""Very hacky way to set the current user for the server, to be replaced once server becomes stateless
|
|
1885
|
-
|
|
1886
|
-
NOTE: clearly not thread-safe, only exists to provide basic user_id support for REST API for now
|
|
1887
|
-
"""
|
|
1888
|
-
|
|
1889
|
-
# Make sure the user_id actually exists
|
|
1890
|
-
if user_id is not None:
|
|
1891
|
-
user_obj = self.get_user(user_id)
|
|
1892
|
-
if not user_obj:
|
|
1893
|
-
raise ValueError(f"User with id {user_id} not found")
|
|
1894
|
-
|
|
1895
|
-
self._current_user = user_id
|
|
1896
|
-
|
|
1897
1900
|
def get_default_user(self) -> User:
|
|
1898
1901
|
|
|
1899
1902
|
from letta.constants import (
|
|
@@ -1910,8 +1913,9 @@ class SyncServer(Server):
|
|
|
1910
1913
|
self.ms.create_organization(org)
|
|
1911
1914
|
|
|
1912
1915
|
# check if default user exists
|
|
1913
|
-
|
|
1914
|
-
|
|
1916
|
+
try:
|
|
1917
|
+
self.get_user(DEFAULT_USER_ID)
|
|
1918
|
+
except ValueError:
|
|
1915
1919
|
user = User(name=DEFAULT_USER_NAME, org_id=DEFAULT_ORG_ID, id=DEFAULT_USER_ID)
|
|
1916
1920
|
self.ms.create_user(user)
|
|
1917
1921
|
|
|
@@ -1922,23 +1926,15 @@ class SyncServer(Server):
|
|
|
1922
1926
|
# check if default org exists
|
|
1923
1927
|
return self.get_user(DEFAULT_USER_ID)
|
|
1924
1928
|
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
if hasattr(self, "_current_user") and self._current_user is not None:
|
|
1935
|
-
current_user = self.get_user(self._current_user)
|
|
1936
|
-
if not current_user:
|
|
1937
|
-
warnings.warn(f"Provided user '{self._current_user}' not found, using default user")
|
|
1938
|
-
else:
|
|
1939
|
-
return current_user
|
|
1940
|
-
|
|
1941
|
-
return self.get_default_user()
|
|
1929
|
+
def get_user_or_default(self, user_id: Optional[str]) -> User:
|
|
1930
|
+
"""Get the user object for user_id if it exists, otherwise return the default user object"""
|
|
1931
|
+
if user_id is None:
|
|
1932
|
+
return self.get_default_user()
|
|
1933
|
+
else:
|
|
1934
|
+
try:
|
|
1935
|
+
return self.get_user(user_id=user_id)
|
|
1936
|
+
except ValueError:
|
|
1937
|
+
raise HTTPException(status_code=404, detail=f"User with id {user_id} not found")
|
|
1942
1938
|
|
|
1943
1939
|
def list_llm_models(self) -> List[LLMConfig]:
|
|
1944
1940
|
"""List available models"""
|
letta/settings.py
CHANGED
|
@@ -13,8 +13,8 @@ class ModelSettings(BaseSettings):
|
|
|
13
13
|
openai_api_key: Optional[str] = None
|
|
14
14
|
# TODO: provide overriding BASE_URL?
|
|
15
15
|
|
|
16
|
-
#
|
|
17
|
-
|
|
16
|
+
# groq
|
|
17
|
+
groq_api_key: Optional[str] = None
|
|
18
18
|
|
|
19
19
|
# anthropic
|
|
20
20
|
anthropic_api_key: Optional[str] = None
|
|
@@ -23,7 +23,9 @@ class ModelSettings(BaseSettings):
|
|
|
23
23
|
ollama_base_url: Optional[str] = None
|
|
24
24
|
|
|
25
25
|
# azure
|
|
26
|
-
|
|
26
|
+
azure_api_key: Optional[str] = None
|
|
27
|
+
azure_base_url: Optional[str] = None
|
|
28
|
+
azure_api_version: Optional[str] = None
|
|
27
29
|
|
|
28
30
|
# google ai
|
|
29
31
|
gemini_api_key: Optional[str] = None
|
|
@@ -54,116 +56,6 @@ class Settings(BaseSettings):
|
|
|
54
56
|
pg_port: Optional[int] = None
|
|
55
57
|
pg_uri: Optional[str] = None # option to specifiy full uri
|
|
56
58
|
|
|
57
|
-
## llm configuration
|
|
58
|
-
# llm_endpoint: Optional[str] = None
|
|
59
|
-
# llm_endpoint_type: Optional[str] = None
|
|
60
|
-
# llm_model: Optional[str] = None
|
|
61
|
-
# llm_context_window: Optional[int] = None
|
|
62
|
-
|
|
63
|
-
## embedding configuration
|
|
64
|
-
# embedding_endpoint: Optional[str] = None
|
|
65
|
-
# embedding_endpoint_type: Optional[str] = None
|
|
66
|
-
# embedding_dim: Optional[int] = None
|
|
67
|
-
# embedding_model: Optional[str] = None
|
|
68
|
-
# embedding_chunk_size: int = 300
|
|
69
|
-
|
|
70
|
-
# @property
|
|
71
|
-
# def llm_config(self):
|
|
72
|
-
|
|
73
|
-
# # try to get LLM config from settings
|
|
74
|
-
# if self.llm_endpoint and self.llm_endpoint_type and self.llm_model and self.llm_context_window:
|
|
75
|
-
# return LLMConfig(
|
|
76
|
-
# model=self.llm_model,
|
|
77
|
-
# model_endpoint_type=self.llm_endpoint_type,
|
|
78
|
-
# model_endpoint=self.llm_endpoint,
|
|
79
|
-
# model_wrapper=None,
|
|
80
|
-
# context_window=self.llm_context_window,
|
|
81
|
-
# )
|
|
82
|
-
# else:
|
|
83
|
-
# if not self.llm_endpoint:
|
|
84
|
-
# printd(f"No LETTA_LLM_ENDPOINT provided")
|
|
85
|
-
# if not self.llm_endpoint_type:
|
|
86
|
-
# printd(f"No LETTA_LLM_ENDPOINT_TYPE provided")
|
|
87
|
-
# if not self.llm_model:
|
|
88
|
-
# printd(f"No LETTA_LLM_MODEL provided")
|
|
89
|
-
# if not self.llm_context_window:
|
|
90
|
-
# printd(f"No LETTA_LLM_CONTEX_WINDOW provided")
|
|
91
|
-
|
|
92
|
-
# # quickstart options
|
|
93
|
-
# if self.llm_model:
|
|
94
|
-
# try:
|
|
95
|
-
# return LLMConfig.default_config(self.llm_model)
|
|
96
|
-
# except ValueError:
|
|
97
|
-
# pass
|
|
98
|
-
|
|
99
|
-
# # try to read from config file (last resort)
|
|
100
|
-
# from letta.config import LettaConfig
|
|
101
|
-
|
|
102
|
-
# if LettaConfig.exists():
|
|
103
|
-
# config = LettaConfig.load()
|
|
104
|
-
# llm_config = LLMConfig(
|
|
105
|
-
# model=config.default_llm_config.model,
|
|
106
|
-
# model_endpoint_type=config.default_llm_config.model_endpoint_type,
|
|
107
|
-
# model_endpoint=config.default_llm_config.model_endpoint,
|
|
108
|
-
# model_wrapper=config.default_llm_config.model_wrapper,
|
|
109
|
-
# context_window=config.default_llm_config.context_window,
|
|
110
|
-
# )
|
|
111
|
-
# return llm_config
|
|
112
|
-
|
|
113
|
-
# # check OpenAI API key
|
|
114
|
-
# if os.getenv("OPENAI_API_KEY"):
|
|
115
|
-
# return LLMConfig.default_config(self.llm_model if self.llm_model else "gpt-4")
|
|
116
|
-
|
|
117
|
-
# return LLMConfig.default_config("letta")
|
|
118
|
-
|
|
119
|
-
# @property
|
|
120
|
-
# def embedding_config(self):
|
|
121
|
-
|
|
122
|
-
# # try to get LLM config from settings
|
|
123
|
-
# if self.embedding_endpoint and self.embedding_endpoint_type and self.embedding_model and self.embedding_dim:
|
|
124
|
-
# return EmbeddingConfig(
|
|
125
|
-
# embedding_model=self.embedding_model,
|
|
126
|
-
# embedding_endpoint_type=self.embedding_endpoint_type,
|
|
127
|
-
# embedding_endpoint=self.embedding_endpoint,
|
|
128
|
-
# embedding_dim=self.embedding_dim,
|
|
129
|
-
# embedding_chunk_size=self.embedding_chunk_size,
|
|
130
|
-
# )
|
|
131
|
-
# else:
|
|
132
|
-
# if not self.embedding_endpoint:
|
|
133
|
-
# printd(f"No LETTA_EMBEDDING_ENDPOINT provided")
|
|
134
|
-
# if not self.embedding_endpoint_type:
|
|
135
|
-
# printd(f"No LETTA_EMBEDDING_ENDPOINT_TYPE provided")
|
|
136
|
-
# if not self.embedding_model:
|
|
137
|
-
# printd(f"No LETTA_EMBEDDING_MODEL provided")
|
|
138
|
-
# if not self.embedding_dim:
|
|
139
|
-
# printd(f"No LETTA_EMBEDDING_DIM provided")
|
|
140
|
-
|
|
141
|
-
# # TODO
|
|
142
|
-
# ## quickstart options
|
|
143
|
-
# # if self.embedding_model:
|
|
144
|
-
# # try:
|
|
145
|
-
# # return EmbeddingConfig.default_config(self.embedding_model)
|
|
146
|
-
# # except ValueError as e:
|
|
147
|
-
# # pass
|
|
148
|
-
|
|
149
|
-
# # try to read from config file (last resort)
|
|
150
|
-
# from letta.config import LettaConfig
|
|
151
|
-
|
|
152
|
-
# if LettaConfig.exists():
|
|
153
|
-
# config = LettaConfig.load()
|
|
154
|
-
# return EmbeddingConfig(
|
|
155
|
-
# embedding_model=config.default_embedding_config.embedding_model,
|
|
156
|
-
# embedding_endpoint_type=config.default_embedding_config.embedding_endpoint_type,
|
|
157
|
-
# embedding_endpoint=config.default_embedding_config.embedding_endpoint,
|
|
158
|
-
# embedding_dim=config.default_embedding_config.embedding_dim,
|
|
159
|
-
# embedding_chunk_size=config.default_embedding_config.embedding_chunk_size,
|
|
160
|
-
# )
|
|
161
|
-
|
|
162
|
-
# if os.getenv("OPENAI_API_KEY"):
|
|
163
|
-
# return EmbeddingConfig.default_config(self.embedding_model if self.embedding_model else "text-embedding-ada-002")
|
|
164
|
-
|
|
165
|
-
# return EmbeddingConfig.default_config("letta")
|
|
166
|
-
|
|
167
59
|
@property
|
|
168
60
|
def letta_pg_uri(self) -> str:
|
|
169
61
|
if self.pg_uri:
|