letta-nightly 0.4.1.dev20241014104152__py3-none-any.whl → 0.5.0.dev20241015014828__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 (32) hide show
  1. letta/__init__.py +2 -2
  2. letta/agent_store/db.py +18 -7
  3. letta/agent_store/lancedb.py +2 -2
  4. letta/agent_store/milvus.py +1 -1
  5. letta/agent_store/qdrant.py +1 -1
  6. letta/agent_store/storage.py +12 -10
  7. letta/cli/cli_load.py +1 -1
  8. letta/client/client.py +51 -0
  9. letta/data_sources/connectors.py +124 -124
  10. letta/data_sources/connectors_helper.py +97 -0
  11. letta/llm_api/mistral.py +47 -0
  12. letta/metadata.py +58 -0
  13. letta/providers.py +44 -0
  14. letta/schemas/file.py +31 -0
  15. letta/schemas/job.py +1 -1
  16. letta/schemas/letta_request.py +3 -3
  17. letta/schemas/llm_config.py +1 -0
  18. letta/schemas/message.py +6 -2
  19. letta/schemas/passage.py +3 -3
  20. letta/schemas/source.py +2 -2
  21. letta/server/rest_api/routers/v1/agents.py +10 -16
  22. letta/server/rest_api/routers/v1/jobs.py +17 -1
  23. letta/server/rest_api/routers/v1/sources.py +7 -9
  24. letta/server/server.py +86 -13
  25. letta/server/static_files/assets/{index-9a9c449b.js → index-dc228d4a.js} +4 -4
  26. letta/server/static_files/index.html +1 -1
  27. {letta_nightly-0.4.1.dev20241014104152.dist-info → letta_nightly-0.5.0.dev20241015014828.dist-info}/METADATA +1 -1
  28. {letta_nightly-0.4.1.dev20241014104152.dist-info → letta_nightly-0.5.0.dev20241015014828.dist-info}/RECORD +31 -29
  29. letta/schemas/document.py +0 -21
  30. {letta_nightly-0.4.1.dev20241014104152.dist-info → letta_nightly-0.5.0.dev20241015014828.dist-info}/LICENSE +0 -0
  31. {letta_nightly-0.4.1.dev20241014104152.dist-info → letta_nightly-0.5.0.dev20241015014828.dist-info}/WHEEL +0 -0
  32. {letta_nightly-0.4.1.dev20241014104152.dist-info → letta_nightly-0.5.0.dev20241015014828.dist-info}/entry_points.txt +0 -0
letta/server/server.py CHANGED
@@ -47,6 +47,7 @@ from letta.providers import (
47
47
  AnthropicProvider,
48
48
  AzureProvider,
49
49
  GoogleAIProvider,
50
+ GroqProvider,
50
51
  LettaProvider,
51
52
  OllamaProvider,
52
53
  OpenAIProvider,
@@ -63,16 +64,16 @@ from letta.schemas.block import (
63
64
  CreatePersona,
64
65
  UpdateBlock,
65
66
  )
66
- from letta.schemas.document import Document
67
67
  from letta.schemas.embedding_config import EmbeddingConfig
68
68
 
69
69
  # openai schemas
70
70
  from letta.schemas.enums import JobStatus
71
+ from letta.schemas.file import FileMetadata
71
72
  from letta.schemas.job import Job
72
73
  from letta.schemas.letta_message import LettaMessage
73
74
  from letta.schemas.llm_config import LLMConfig
74
75
  from letta.schemas.memory import ArchivalMemorySummary, Memory, RecallMemorySummary
75
- from letta.schemas.message import Message, UpdateMessage
76
+ from letta.schemas.message import Message, MessageCreate, MessageRole, UpdateMessage
76
77
  from letta.schemas.openai.chat_completion_response import UsageStatistics
77
78
  from letta.schemas.organization import Organization, OrganizationCreate
78
79
  from letta.schemas.passage import Passage
@@ -141,6 +142,11 @@ class Server(object):
141
142
  """Process a message from the system, internally calls step"""
142
143
  raise NotImplementedError
143
144
 
145
+ @abstractmethod
146
+ def send_messages(self, user_id: str, agent_id: str, messages: Union[MessageCreate, List[Message]]) -> None:
147
+ """Send a list of messages to the agent"""
148
+ raise NotImplementedError
149
+
144
150
  @abstractmethod
145
151
  def run_command(self, user_id: str, agent_id: str, command: str) -> Union[str, None]:
146
152
  """Run a command on the agent, e.g. /memory
@@ -292,6 +298,12 @@ class SyncServer(Server):
292
298
  base_url=model_settings.vllm_api_base,
293
299
  )
294
300
  )
301
+ if model_settings.groq_api_key:
302
+ self._enabled_providers.append(
303
+ GroqProvider(
304
+ api_key=model_settings.groq_api_key,
305
+ )
306
+ )
295
307
 
296
308
  def save_agents(self):
297
309
  """Saves all the agents that are in the in-memory object store"""
@@ -725,6 +737,68 @@ class SyncServer(Server):
725
737
  # Run the agent state forward
726
738
  return self._step(user_id=user_id, agent_id=agent_id, input_messages=message)
727
739
 
740
+ def send_messages(
741
+ self,
742
+ user_id: str,
743
+ agent_id: str,
744
+ messages: Union[List[MessageCreate], List[Message]],
745
+ # whether or not to wrap user and system message as MemGPT-style stringified JSON
746
+ wrap_user_message: bool = True,
747
+ wrap_system_message: bool = True,
748
+ ) -> LettaUsageStatistics:
749
+ """Send a list of messages to the agent
750
+
751
+ If the messages are of type MessageCreate, we need to turn them into
752
+ Message objects first before sending them through step.
753
+
754
+ Otherwise, we can pass them in directly.
755
+ """
756
+ if self.ms.get_user(user_id=user_id) is None:
757
+ raise ValueError(f"User user_id={user_id} does not exist")
758
+ if self.ms.get_agent(agent_id=agent_id, user_id=user_id) is None:
759
+ raise ValueError(f"Agent agent_id={agent_id} does not exist")
760
+
761
+ message_objects: List[Message] = []
762
+
763
+ if all(isinstance(m, MessageCreate) for m in messages):
764
+ for message in messages:
765
+ assert isinstance(message, MessageCreate)
766
+
767
+ # If wrapping is eanbled, wrap with metadata before placing content inside the Message object
768
+ if message.role == MessageRole.user and wrap_user_message:
769
+ message.text = system.package_user_message(user_message=message.text)
770
+ elif message.role == MessageRole.system and wrap_system_message:
771
+ message.text = system.package_system_message(system_message=message.text)
772
+ else:
773
+ raise ValueError(f"Invalid message role: {message.role}")
774
+
775
+ # Create the Message object
776
+ message_objects.append(
777
+ Message(
778
+ user_id=user_id,
779
+ agent_id=agent_id,
780
+ role=message.role,
781
+ text=message.text,
782
+ name=message.name,
783
+ # assigned later?
784
+ model=None,
785
+ # irrelevant
786
+ tool_calls=None,
787
+ tool_call_id=None,
788
+ )
789
+ )
790
+
791
+ elif all(isinstance(m, Message) for m in messages):
792
+ for message in messages:
793
+ assert isinstance(message, Message)
794
+ message_objects.append(message)
795
+
796
+ else:
797
+ raise ValueError(f"All messages must be of type Message or MessageCreate, got {type(messages)}")
798
+
799
+ # Run the agent state forward
800
+ return self._step(user_id=user_id, agent_id=agent_id, input_messages=message_objects)
801
+
728
802
  # @LockingServer.agent_lock_decorator
729
803
  def run_command(self, user_id: str, agent_id: str, command: str) -> LettaUsageStatistics:
730
804
  """Run a command on the agent"""
@@ -1596,7 +1670,7 @@ class SyncServer(Server):
1596
1670
  # job.status = JobStatus.failed
1597
1671
  # job.metadata_["error"] = error
1598
1672
  # self.ms.update_job(job)
1599
- # # TODO: delete any associated passages/documents?
1673
+ # # TODO: delete any associated passages/files?
1600
1674
 
1601
1675
  # # return failed job
1602
1676
  # return job
@@ -1625,11 +1699,10 @@ class SyncServer(Server):
1625
1699
 
1626
1700
  # get the data connectors
1627
1701
  passage_store = StorageConnector.get_storage_connector(TableType.PASSAGES, self.config, user_id=user_id)
1628
- # TODO: add document store support
1629
- document_store = None # StorageConnector.get_storage_connector(TableType.DOCUMENTS, self.config, user_id=user_id)
1702
+ file_store = StorageConnector.get_storage_connector(TableType.FILES, self.config, user_id=user_id)
1630
1703
 
1631
1704
  # load data into the document store
1632
- passage_count, document_count = load_data(connector, source, passage_store, document_store)
1705
+ passage_count, document_count = load_data(connector, source, passage_store, file_store)
1633
1706
  return passage_count, document_count
1634
1707
 
1635
1708
  def attach_source_to_agent(
@@ -1686,14 +1759,14 @@ class SyncServer(Server):
1686
1759
  # list all attached sources to an agent
1687
1760
  return self.ms.list_attached_sources(agent_id)
1688
1761
 
1762
+ def list_files_from_source(self, source_id: str, limit: int = 1000, cursor: Optional[str] = None) -> List[FileMetadata]:
1763
+ # list all attached sources to an agent
1764
+ return self.ms.list_files_from_source(source_id=source_id, limit=limit, cursor=cursor)
1765
+
1689
1766
  def list_data_source_passages(self, user_id: str, source_id: str) -> List[Passage]:
1690
1767
  warnings.warn("list_data_source_passages is not yet implemented, returning empty list.", category=UserWarning)
1691
1768
  return []
1692
1769
 
1693
- def list_data_source_documents(self, user_id: str, source_id: str) -> List[Document]:
1694
- warnings.warn("list_data_source_documents is not yet implemented, returning empty list.", category=UserWarning)
1695
- return []
1696
-
1697
1770
  def list_all_sources(self, user_id: str) -> List[Source]:
1698
1771
  """List all sources (w/ extra metadata) belonging to a user"""
1699
1772
 
@@ -1707,9 +1780,9 @@ class SyncServer(Server):
1707
1780
  passage_conn = StorageConnector.get_storage_connector(TableType.PASSAGES, self.config, user_id=user_id)
1708
1781
  num_passages = passage_conn.size({"source_id": source.id})
1709
1782
 
1710
- # TODO: add when documents table implemented
1711
- ## count number of documents
1712
- # document_conn = StorageConnector.get_storage_connector(TableType.DOCUMENTS, self.config, user_id=user_id)
1783
+ # TODO: add when files table implemented
1784
+ ## count number of files
1785
+ # document_conn = StorageConnector.get_storage_connector(TableType.FILES, self.config, user_id=user_id)
1713
1786
  # num_documents = document_conn.size({"data_source": source.name})
1714
1787
  num_documents = 0
1715
1788