letta-nightly 0.6.4.dev20241213193437__py3-none-any.whl → 0.6.4.dev20241214104034__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.

Files changed (62) hide show
  1. letta/__init__.py +1 -1
  2. letta/agent.py +54 -45
  3. letta/chat_only_agent.py +6 -8
  4. letta/cli/cli.py +2 -10
  5. letta/client/client.py +121 -138
  6. letta/config.py +0 -161
  7. letta/main.py +3 -8
  8. letta/memory.py +3 -14
  9. letta/o1_agent.py +1 -5
  10. letta/offline_memory_agent.py +2 -6
  11. letta/orm/__init__.py +2 -0
  12. letta/orm/agent.py +109 -0
  13. letta/orm/agents_tags.py +10 -18
  14. letta/orm/block.py +29 -4
  15. letta/orm/blocks_agents.py +5 -11
  16. letta/orm/custom_columns.py +152 -0
  17. letta/orm/message.py +3 -38
  18. letta/orm/organization.py +2 -7
  19. letta/orm/passage.py +10 -32
  20. letta/orm/source.py +5 -25
  21. letta/orm/sources_agents.py +13 -0
  22. letta/orm/sqlalchemy_base.py +54 -30
  23. letta/orm/tool.py +1 -19
  24. letta/orm/tools_agents.py +7 -24
  25. letta/orm/user.py +3 -4
  26. letta/schemas/agent.py +48 -65
  27. letta/schemas/memory.py +2 -1
  28. letta/schemas/sandbox_config.py +12 -1
  29. letta/server/rest_api/app.py +0 -5
  30. letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +1 -1
  31. letta/server/rest_api/routers/v1/agents.py +99 -78
  32. letta/server/rest_api/routers/v1/blocks.py +22 -25
  33. letta/server/rest_api/routers/v1/jobs.py +4 -4
  34. letta/server/rest_api/routers/v1/sandbox_configs.py +10 -10
  35. letta/server/rest_api/routers/v1/sources.py +12 -12
  36. letta/server/rest_api/routers/v1/tools.py +35 -15
  37. letta/server/rest_api/routers/v1/users.py +0 -46
  38. letta/server/server.py +172 -716
  39. letta/server/ws_api/server.py +0 -5
  40. letta/services/agent_manager.py +405 -0
  41. letta/services/block_manager.py +13 -21
  42. letta/services/helpers/agent_manager_helper.py +90 -0
  43. letta/services/organization_manager.py +0 -1
  44. letta/services/passage_manager.py +62 -62
  45. letta/services/sandbox_config_manager.py +3 -3
  46. letta/services/source_manager.py +22 -1
  47. letta/services/user_manager.py +11 -6
  48. letta/utils.py +2 -2
  49. {letta_nightly-0.6.4.dev20241213193437.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/METADATA +1 -1
  50. {letta_nightly-0.6.4.dev20241213193437.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/RECORD +53 -57
  51. letta/metadata.py +0 -407
  52. letta/schemas/agents_tags.py +0 -33
  53. letta/schemas/api_key.py +0 -21
  54. letta/schemas/blocks_agents.py +0 -32
  55. letta/schemas/tools_agents.py +0 -32
  56. letta/server/rest_api/routers/openai/assistants/threads.py +0 -338
  57. letta/services/agents_tags_manager.py +0 -64
  58. letta/services/blocks_agents_manager.py +0 -106
  59. letta/services/tools_agents_manager.py +0 -94
  60. {letta_nightly-0.6.4.dev20241213193437.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/LICENSE +0 -0
  61. {letta_nightly-0.6.4.dev20241213193437.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/WHEEL +0 -0
  62. {letta_nightly-0.6.4.dev20241213193437.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/entry_points.txt +0 -0
letta/schemas/agent.py CHANGED
@@ -1,13 +1,11 @@
1
- from datetime import datetime
2
1
  from enum import Enum
3
2
  from typing import Dict, List, Optional
4
3
 
5
4
  from pydantic import BaseModel, Field, field_validator
6
5
 
7
- from letta.constants import BASE_MEMORY_TOOLS, BASE_TOOLS
8
6
  from letta.schemas.block import CreateBlock
9
7
  from letta.schemas.embedding_config import EmbeddingConfig
10
- from letta.schemas.letta_base import LettaBase
8
+ from letta.schemas.letta_base import OrmMetadataBase
11
9
  from letta.schemas.llm_config import LLMConfig
12
10
  from letta.schemas.memory import Memory
13
11
  from letta.schemas.message import Message, MessageCreate
@@ -15,15 +13,7 @@ from letta.schemas.openai.chat_completion_response import UsageStatistics
15
13
  from letta.schemas.source import Source
16
14
  from letta.schemas.tool import Tool
17
15
  from letta.schemas.tool_rule import ToolRule
18
-
19
-
20
- class BaseAgent(LettaBase, validate_assignment=True):
21
- __id_prefix__ = "agent"
22
- description: Optional[str] = Field(None, description="The description of the agent.")
23
-
24
- # metadata
25
- metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
26
- user_id: Optional[str] = Field(None, description="The user id of the agent.")
16
+ from letta.utils import create_random_username
27
17
 
28
18
 
29
19
  class AgentType(str, Enum):
@@ -38,37 +28,7 @@ class AgentType(str, Enum):
38
28
  chat_only_agent = "chat_only_agent"
39
29
 
40
30
 
41
- class PersistedAgentState(BaseAgent, validate_assignment=True):
42
- # NOTE: this has been changed to represent the data stored in the ORM, NOT what is passed around internally or returned to the user
43
- id: str = BaseAgent.generate_id_field()
44
- name: str = Field(..., description="The name of the agent.")
45
- created_at: datetime = Field(..., description="The datetime the agent was created.", default_factory=datetime.now)
46
-
47
- # in-context memory
48
- message_ids: Optional[List[str]] = Field(default=None, description="The ids of the messages in the agent's in-context memory.")
49
- # tools
50
- # TODO: move to ORM mapping
51
- tool_names: List[str] = Field(..., description="The tools used by the agent.")
52
-
53
- # tool rules
54
- tool_rules: Optional[List[ToolRule]] = Field(default=None, description="The list of tool rules.")
55
-
56
- # system prompt
57
- system: str = Field(..., description="The system prompt used by the agent.")
58
-
59
- # agent configuration
60
- agent_type: AgentType = Field(..., description="The type of agent.")
61
-
62
- # llm information
63
- llm_config: LLMConfig = Field(..., description="The LLM configuration used by the agent.")
64
- embedding_config: EmbeddingConfig = Field(..., description="The embedding configuration used by the agent.")
65
-
66
- class Config:
67
- arbitrary_types_allowed = True
68
- validate_assignment = True
69
-
70
-
71
- class AgentState(PersistedAgentState):
31
+ class AgentState(OrmMetadataBase, validate_assignment=True):
72
32
  """
73
33
  Representation of an agent's state. This is the state of the agent at a given time, and is persisted in the DB backend. The state has all the information needed to recreate a persisted agent.
74
34
 
@@ -85,43 +45,58 @@ class AgentState(PersistedAgentState):
85
45
 
86
46
  """
87
47
 
48
+ __id_prefix__ = "agent"
49
+
88
50
  # NOTE: this is what is returned to the client and also what is used to initialize `Agent`
51
+ id: str = Field(..., description="The id of the agent. Assigned by the database.")
52
+ name: str = Field(..., description="The name of the agent.")
53
+ # tool rules
54
+ tool_rules: Optional[List[ToolRule]] = Field(default=None, description="The list of tool rules.")
55
+
56
+ # in-context memory
57
+ message_ids: Optional[List[str]] = Field(default=None, description="The ids of the messages in the agent's in-context memory.")
58
+
59
+ # system prompt
60
+ system: str = Field(..., description="The system prompt used by the agent.")
61
+
62
+ # agent configuration
63
+ agent_type: AgentType = Field(..., description="The type of agent.")
64
+
65
+ # llm information
66
+ llm_config: LLMConfig = Field(..., description="The LLM configuration used by the agent.")
67
+ embedding_config: EmbeddingConfig = Field(..., description="The embedding configuration used by the agent.")
89
68
 
90
69
  # This is an object representing the in-process state of a running `Agent`
91
70
  # Field in this object can be theoretically edited by tools, and will be persisted by the ORM
71
+ organization_id: Optional[str] = Field(None, description="The unique identifier of the organization associated with the agent.")
72
+
73
+ description: Optional[str] = Field(None, description="The description of the agent.")
74
+ metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
75
+
92
76
  memory: Memory = Field(..., description="The in-context memory of the agent.")
93
77
  tools: List[Tool] = Field(..., description="The tools used by the agent.")
94
78
  sources: List[Source] = Field(..., description="The sources used by the agent.")
95
79
  tags: List[str] = Field(..., description="The tags associated with the agent.")
96
- # TODO: add in context message objects
97
-
98
- def to_persisted_agent_state(self) -> PersistedAgentState:
99
- # turn back into persisted agent
100
- data = self.model_dump()
101
- del data["memory"]
102
- del data["tools"]
103
- del data["sources"]
104
- del data["tags"]
105
- return PersistedAgentState(**data)
106
80
 
107
81
 
108
- class CreateAgent(BaseAgent): #
82
+ class CreateAgent(BaseModel, validate_assignment=True): #
109
83
  # all optional as server can generate defaults
110
- name: Optional[str] = Field(None, description="The name of the agent.")
111
- message_ids: Optional[List[str]] = Field(None, description="The ids of the messages in the agent's in-context memory.")
84
+ name: str = Field(default_factory=lambda: create_random_username(), description="The name of the agent.")
112
85
 
113
86
  # memory creation
114
87
  memory_blocks: List[CreateBlock] = Field(
115
- # [CreateHuman(), CreatePersona()], description="The blocks to create in the agent's in-context memory."
116
88
  ...,
117
89
  description="The blocks to create in the agent's in-context memory.",
118
90
  )
119
-
120
- tools: List[str] = Field(BASE_TOOLS + BASE_MEMORY_TOOLS, description="The tools used by the agent.")
91
+ # TODO: This is a legacy field and should be removed ASAP to force `tool_ids` usage
92
+ tools: Optional[List[str]] = Field(None, description="The tools used by the agent.")
93
+ tool_ids: Optional[List[str]] = Field(None, description="The ids of the tools used by the agent.")
94
+ source_ids: Optional[List[str]] = Field(None, description="The ids of the sources used by the agent.")
95
+ block_ids: Optional[List[str]] = Field(None, description="The ids of the blocks used by the agent.")
121
96
  tool_rules: Optional[List[ToolRule]] = Field(None, description="The tool rules governing the agent.")
122
97
  tags: Optional[List[str]] = Field(None, description="The tags associated with the agent.")
123
98
  system: Optional[str] = Field(None, description="The system prompt used by the agent.")
124
- agent_type: AgentType = Field(AgentType.memgpt_agent, description="The type of agent.")
99
+ agent_type: AgentType = Field(default_factory=lambda: AgentType.memgpt_agent, description="The type of agent.")
125
100
  llm_config: Optional[LLMConfig] = Field(None, description="The LLM configuration used by the agent.")
126
101
  embedding_config: Optional[EmbeddingConfig] = Field(None, description="The embedding configuration used by the agent.")
127
102
  # Note: if this is None, then we'll populate with the standard "more human than human" initial message sequence
@@ -129,6 +104,9 @@ class CreateAgent(BaseAgent): #
129
104
  initial_message_sequence: Optional[List[MessageCreate]] = Field(
130
105
  None, description="The initial set of messages to put in the agent's in-context memory."
131
106
  )
107
+ include_base_tools: bool = Field(True, description="The LLM configuration used by the agent.")
108
+ description: Optional[str] = Field(None, description="The description of the agent.")
109
+ metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
132
110
 
133
111
  @field_validator("name")
134
112
  @classmethod
@@ -156,17 +134,22 @@ class CreateAgent(BaseAgent): #
156
134
  return name
157
135
 
158
136
 
159
- class UpdateAgentState(BaseAgent):
160
- id: str = Field(..., description="The id of the agent.")
137
+ class UpdateAgent(BaseModel):
161
138
  name: Optional[str] = Field(None, description="The name of the agent.")
162
- tool_names: Optional[List[str]] = Field(None, description="The tools used by the agent.")
139
+ tool_ids: Optional[List[str]] = Field(None, description="The ids of the tools used by the agent.")
140
+ source_ids: Optional[List[str]] = Field(None, description="The ids of the sources used by the agent.")
141
+ block_ids: Optional[List[str]] = Field(None, description="The ids of the blocks used by the agent.")
163
142
  tags: Optional[List[str]] = Field(None, description="The tags associated with the agent.")
164
143
  system: Optional[str] = Field(None, description="The system prompt used by the agent.")
144
+ tool_rules: Optional[List[ToolRule]] = Field(None, description="The tool rules governing the agent.")
165
145
  llm_config: Optional[LLMConfig] = Field(None, description="The LLM configuration used by the agent.")
166
146
  embedding_config: Optional[EmbeddingConfig] = Field(None, description="The embedding configuration used by the agent.")
167
-
168
- # TODO: determine if these should be editable via this schema?
169
147
  message_ids: Optional[List[str]] = Field(None, description="The ids of the messages in the agent's in-context memory.")
148
+ description: Optional[str] = Field(None, description="The description of the agent.")
149
+ metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
150
+
151
+ class Config:
152
+ extra = "ignore" # Ignores extra fields
170
153
 
171
154
 
172
155
  class AgentStepResponse(BaseModel):
letta/schemas/memory.py CHANGED
@@ -87,7 +87,7 @@ class Memory(BaseModel, validate_assignment=True):
87
87
  Template(prompt_template)
88
88
 
89
89
  # Validate compatibility with current memory structure
90
- test_render = Template(prompt_template).render(blocks=self.blocks)
90
+ Template(prompt_template).render(blocks=self.blocks)
91
91
 
92
92
  # If we get here, the template is valid and compatible
93
93
  self.prompt_template = prompt_template
@@ -213,6 +213,7 @@ class ChatMemory(BasicBlockMemory):
213
213
  human (str): The starter value for the human block.
214
214
  limit (int): The character limit for each block.
215
215
  """
216
+ # TODO: Should these be CreateBlocks?
216
217
  super().__init__(blocks=[Block(value=persona, limit=limit, label="persona"), Block(value=human, limit=limit, label="human")])
217
218
 
218
219
 
@@ -3,10 +3,11 @@ import json
3
3
  from enum import Enum
4
4
  from typing import Any, Dict, List, Optional, Union
5
5
 
6
- from pydantic import BaseModel, Field
6
+ from pydantic import BaseModel, Field, model_validator
7
7
 
8
8
  from letta.schemas.agent import AgentState
9
9
  from letta.schemas.letta_base import LettaBase, OrmMetadataBase
10
+ from letta.settings import tool_settings
10
11
 
11
12
 
12
13
  # Sandbox Config
@@ -45,6 +46,16 @@ class E2BSandboxConfig(BaseModel):
45
46
  def type(self) -> "SandboxType":
46
47
  return SandboxType.E2B
47
48
 
49
+ @model_validator(mode="before")
50
+ @classmethod
51
+ def set_default_template(cls, data: dict):
52
+ """
53
+ Assign a default template value if the template field is not provided.
54
+ """
55
+ if data.get("template") is None:
56
+ data["template"] = tool_settings.e2b_sandbox_template_id
57
+ return data
58
+
48
59
 
49
60
  class SandboxConfigBase(OrmMetadataBase):
50
61
  __id_prefix__ = "sandbox"
@@ -25,9 +25,6 @@ from letta.server.rest_api.interface import StreamingServerInterface
25
25
  from letta.server.rest_api.routers.openai.assistants.assistants import (
26
26
  router as openai_assistants_router,
27
27
  )
28
- from letta.server.rest_api.routers.openai.assistants.threads import (
29
- router as openai_threads_router,
30
- )
31
28
  from letta.server.rest_api.routers.openai.chat_completions.chat_completions import (
32
29
  router as openai_chat_completions_router,
33
30
  )
@@ -215,7 +212,6 @@ def create_application() -> "FastAPI":
215
212
 
216
213
  # openai
217
214
  app.include_router(openai_assistants_router, prefix=OPENAI_API_PREFIX)
218
- app.include_router(openai_threads_router, prefix=OPENAI_API_PREFIX)
219
215
  app.include_router(openai_chat_completions_router, prefix=OPENAI_API_PREFIX)
220
216
 
221
217
  # /api/auth endpoints
@@ -236,7 +232,6 @@ def create_application() -> "FastAPI":
236
232
  @app.on_event("shutdown")
237
233
  def on_shutdown():
238
234
  global server
239
- server.save_agents()
240
235
  # server = None
241
236
 
242
237
  return app
@@ -36,7 +36,7 @@ async def create_chat_completion(
36
36
  The bearer token will be used to identify the user.
37
37
  The 'user' field in the completion_request should be set to the agent ID.
38
38
  """
39
- actor = server.get_user_or_default(user_id=user_id)
39
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
40
40
 
41
41
  agent_id = completion_request.user
42
42
  if agent_id is None: