Skip to content

Commit

Permalink
fix: patch new route names (#2378)
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahwooders authored Jan 23, 2025
2 parents d9a0996 + de65656 commit fd66fbf
Show file tree
Hide file tree
Showing 54 changed files with 504 additions and 676 deletions.
2 changes: 1 addition & 1 deletion examples/notebooks/Agentic RAG with Letta.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
}
],
"source": [
"client.jobs.get(job_id=job.id).metadata_"
"client.jobs.get(job_id=job.id).metadata"
]
},
{
Expand Down
1 change: 0 additions & 1 deletion letta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from letta.schemas.llm_config import LLMConfig
from letta.schemas.memory import ArchivalMemorySummary, BasicBlockMemory, ChatMemory, Memory, RecallMemorySummary
from letta.schemas.message import Message
from letta.schemas.openai.chat_completion_response import UsageStatistics
from letta.schemas.organization import Organization
from letta.schemas.passage import Passage
from letta.schemas.source import Source
Expand Down
7 changes: 4 additions & 3 deletions letta/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from abc import ABC, abstractmethod
from typing import List, Optional, Tuple, Union

from openai.types.beta.function_tool import FunctionTool as OpenAITool

from letta.constants import (
CLI_WARNING_PREFIX,
ERROR_MESSAGE_PREFIX,
Expand Down Expand Up @@ -33,7 +35,6 @@
from letta.schemas.enums import MessageRole
from letta.schemas.memory import ContextWindowOverview, Memory
from letta.schemas.message import Message
from letta.schemas.openai.chat_completion_request import Tool as ChatCompletionRequestTool
from letta.schemas.openai.chat_completion_response import ChatCompletionResponse
from letta.schemas.openai.chat_completion_response import Message as ChatCompletionMessage
from letta.schemas.openai.chat_completion_response import UsageStatistics
Expand Down Expand Up @@ -1023,7 +1024,7 @@ def get_context_window(self) -> ContextWindowOverview:
# tokens taken up by function definitions
agent_state_tool_jsons = [t.json_schema for t in self.agent_state.tools]
if agent_state_tool_jsons:
available_functions_definitions = [ChatCompletionRequestTool(type="function", function=f) for f in agent_state_tool_jsons]
available_functions_definitions = [OpenAITool(type="function", function=f) for f in agent_state_tool_jsons]
num_tokens_available_functions_definitions = num_tokens_from_functions(functions=agent_state_tool_jsons, model=self.model)
else:
available_functions_definitions = []
Expand Down Expand Up @@ -1090,7 +1091,7 @@ def save_agent(agent: Agent):
embedding_config=agent_state.embedding_config,
message_ids=agent_state.message_ids,
description=agent_state.description,
metadata_=agent_state.metadata_,
metadata=agent_state.metadata,
# TODO: Add this back in later
# tool_exec_environment_variables=agent_state.get_agent_env_vars_as_dict(),
)
Expand Down
2 changes: 1 addition & 1 deletion letta/chat_only_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def generate_offline_memory_agent():
memory=offline_memory,
llm_config=LLMConfig.default_config("gpt-4"),
embedding_config=EmbeddingConfig.default_config("text-embedding-ada-002"),
tool_ids=self.agent_state.metadata_.get("offline_memory_tools", []),
tool_ids=self.agent_state.metadata.get("offline_memory_tools", []),
include_base_tools=False,
)
self.offline_memory_agent.memory.update_block_value(label="conversation_block", value=recent_convo)
Expand Down
37 changes: 19 additions & 18 deletions letta/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Callable, Dict, Generator, List, Optional, Union

import requests
from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall as OpenAIToolCall

import letta.utils
from letta.constants import ADMIN_PREFIX, BASE_MEMORY_TOOLS, BASE_TOOLS, DEFAULT_HUMAN, DEFAULT_PERSONA, FUNCTION_RETURN_CHAR_LIMIT
Expand All @@ -29,7 +30,6 @@
from letta.schemas.memory import ArchivalMemorySummary, ChatMemory, CreateArchivalMemory, Memory, RecallMemorySummary
from letta.schemas.message import Message, MessageCreate, MessageUpdate
from letta.schemas.openai.chat_completion_response import UsageStatistics
from letta.schemas.openai.chat_completions import ToolCall
from letta.schemas.organization import Organization
from letta.schemas.passage import Passage
from letta.schemas.run import Run
Expand Down Expand Up @@ -586,7 +586,7 @@ def create_agent(
# create agent
create_params = {
"description": description,
"metadata_": metadata,
"metadata": metadata,
"memory_blocks": [],
"block_ids": [b.id for b in memory.get_blocks()] + block_ids,
"tool_ids": tool_ids,
Expand Down Expand Up @@ -631,7 +631,7 @@ def update_message(
role: Optional[MessageRole] = None,
text: Optional[str] = None,
name: Optional[str] = None,
tool_calls: Optional[List[ToolCall]] = None,
tool_calls: Optional[List[OpenAIToolCall]] = None,
tool_call_id: Optional[str] = None,
) -> Message:
request = MessageUpdate(
Expand Down Expand Up @@ -685,7 +685,7 @@ def update_agent(
tool_ids=tool_ids,
tags=tags,
description=description,
metadata_=metadata,
metadata=metadata,
llm_config=llm_config,
embedding_config=embedding_config,
message_ids=message_ids,
Expand Down Expand Up @@ -810,7 +810,8 @@ def get_in_context_memory(self, agent_id: str) -> Memory:
Returns:
memory (Memory): In-context memory of the agent
"""
response = requests.get(f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory", headers=self.headers)

response = requests.get(f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory", headers=self.headers)
if response.status_code != 200:
raise ValueError(f"Failed to get in-context memory: {response.text}")
return Memory(**response.json())
Expand All @@ -831,7 +832,7 @@ def update_in_context_memory(self, agent_id: str, section: str, value: Union[Lis
"""
memory_update_dict = {section: value}
response = requests.patch(
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory", json=memory_update_dict, headers=self.headers
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory", json=memory_update_dict, headers=self.headers
)
if response.status_code != 200:
raise ValueError(f"Failed to update in-context memory: {response.text}")
Expand Down Expand Up @@ -924,7 +925,7 @@ def get_archival_memory(
if after:
params["after"] = str(after)
response = requests.get(
f"{self.base_url}/{self.api_prefix}/agents/{str(agent_id)}/archival_memory", params=params, headers=self.headers
f"{self.base_url}/{self.api_prefix}/agents/{str(agent_id)}/archival-memory", params=params, headers=self.headers
)
assert response.status_code == 200, f"Failed to get archival memory: {response.text}"
return [Passage(**passage) for passage in response.json()]
Expand All @@ -942,7 +943,7 @@ def insert_archival_memory(self, agent_id: str, memory: str) -> List[Passage]:
"""
request = CreateArchivalMemory(text=memory)
response = requests.post(
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/archival_memory", headers=self.headers, json=request.model_dump()
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/archival-memory", headers=self.headers, json=request.model_dump()
)
if response.status_code != 200:
raise ValueError(f"Failed to insert archival memory: {response.text}")
Expand All @@ -956,7 +957,7 @@ def delete_archival_memory(self, agent_id: str, memory_id: str):
agent_id (str): ID of the agent
memory_id (str): ID of the memory
"""
response = requests.delete(f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/archival_memory/{memory_id}", headers=self.headers)
response = requests.delete(f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/archival-memory/{memory_id}", headers=self.headers)
assert response.status_code == 200, f"Failed to delete archival memory: {response.text}"

# messages (recall memory)
Expand Down Expand Up @@ -1906,7 +1907,7 @@ def attach_block(self, agent_id: str, block_id: str) -> AgentState:
block_id (str): ID of the block to attach
"""
response = requests.patch(
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory/blocks/attach/{block_id}",
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory/blocks/attach/{block_id}",
headers=self.headers,
)
if response.status_code != 200:
Expand All @@ -1922,7 +1923,7 @@ def detach_block(self, agent_id: str, block_id: str) -> AgentState:
block_id (str): ID of the block to detach
"""
response = requests.patch(
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory/blocks/detach/{block_id}", headers=self.headers
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory/blocks/detach/{block_id}", headers=self.headers
)
if response.status_code != 200:
raise ValueError(f"Failed to detach block from agent: {response.text}")
Expand All @@ -1938,7 +1939,7 @@ def list_agent_memory_blocks(self, agent_id: str) -> List[Block]:
Returns:
blocks (List[Block]): The blocks in the agent's core memory
"""
response = requests.get(f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory/blocks", headers=self.headers)
response = requests.get(f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory/blocks", headers=self.headers)
if response.status_code != 200:
raise ValueError(f"Failed to get agent memory blocks: {response.text}")
return [Block(**block) for block in response.json()]
Expand All @@ -1955,7 +1956,7 @@ def get_agent_memory_block(self, agent_id: str, label: str) -> Block:
block (Block): The block corresponding to the label
"""
response = requests.get(
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory/blocks/{label}",
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory/blocks/{label}",
headers=self.headers,
)
if response.status_code != 200:
Expand Down Expand Up @@ -1988,7 +1989,7 @@ def update_agent_memory_block(
if limit:
data["limit"] = limit
response = requests.patch(
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core_memory/blocks/{label}",
f"{self.base_url}/{self.api_prefix}/agents/{agent_id}/core-memory/blocks/{label}",
headers=self.headers,
json=data,
)
Expand Down Expand Up @@ -2331,7 +2332,7 @@ def create_agent(
# Create the base parameters
create_params = {
"description": description,
"metadata_": metadata,
"metadata": metadata,
"memory_blocks": [],
"block_ids": [b.id for b in memory.get_blocks()] + block_ids,
"tool_ids": tool_ids,
Expand Down Expand Up @@ -2365,7 +2366,7 @@ def update_message(
role: Optional[MessageRole] = None,
text: Optional[str] = None,
name: Optional[str] = None,
tool_calls: Optional[List[ToolCall]] = None,
tool_calls: Optional[List[OpenAIToolCall]] = None,
tool_call_id: Optional[str] = None,
) -> Message:
message = self.server.update_agent_message(
Expand Down Expand Up @@ -2423,7 +2424,7 @@ def update_agent(
tool_ids=tool_ids,
tags=tags,
description=description,
metadata_=metadata,
metadata=metadata,
llm_config=llm_config,
embedding_config=embedding_config,
message_ids=message_ids,
Expand Down Expand Up @@ -3100,7 +3101,7 @@ def load_file_to_source(self, filename: str, source_id: str, blocking=True):
job = Job(
user_id=self.user_id,
status=JobStatus.created,
metadata_={"type": "embedding", "filename": filename, "source_id": source_id},
metadata={"type": "embedding", "filename": filename, "source_id": source_id},
)
job = self.server.job_manager.create_job(pydantic_job=job, actor=self.user)

Expand Down
2 changes: 1 addition & 1 deletion letta/data_sources/connectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def load_data(connector: DataConnector, source: Source, passage_manager: Passage
text=passage_text,
file_id=file_metadata.id,
source_id=source.id,
metadata_=passage_metadata,
metadata=passage_metadata,
organization_id=source.organization_id,
embedding_config=source.embedding_config,
embedding=embedding,
Expand Down
4 changes: 2 additions & 2 deletions letta/orm/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ def to_pydantic(self) -> PydanticAgentState:
"description": self.description,
"message_ids": self.message_ids,
"tools": self.tools,
"sources": self.sources,
"sources": [source.to_pydantic() for source in self.sources],
"tags": [t.tag for t in self.tags],
"tool_rules": self.tool_rules,
"system": self.system,
"agent_type": self.agent_type,
"llm_config": self.llm_config,
"embedding_config": self.embedding_config,
"metadata_": self.metadata_,
"metadata": self.metadata_,
"memory": Memory(blocks=[b.to_pydantic() for b in self.core_memory]),
"created_by_id": self.created_by_id,
"last_updated_by_id": self.last_updated_by_id,
Expand Down
4 changes: 3 additions & 1 deletion letta/orm/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ def to_pydantic(self) -> Type:
Schema = Persona
case _:
Schema = PydanticBlock
return Schema.model_validate(self)
model_dict = {k: v for k, v in self.__dict__.items() if k in self.__pydantic_model__.model_fields}
model_dict["metadata"] = self.metadata_
return Schema.model_validate(model_dict)


@event.listens_for(Block, "after_update") # Changed from 'before_update'
Expand Down
9 changes: 5 additions & 4 deletions letta/orm/custom_columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
from typing import List, Union

import numpy as np
from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall as OpenAIToolCall
from openai.types.chat.chat_completion_message_tool_call import Function as OpenAIFunction
from sqlalchemy import JSON
from sqlalchemy.types import BINARY, TypeDecorator

from letta.schemas.embedding_config import EmbeddingConfig
from letta.schemas.enums import ToolRuleType
from letta.schemas.llm_config import LLMConfig
from letta.schemas.openai.chat_completions import ToolCall, ToolCallFunction
from letta.schemas.tool_rule import ChildToolRule, ConditionalToolRule, InitToolRule, TerminalToolRule


Expand Down Expand Up @@ -109,7 +110,7 @@ def process_bind_param(self, value, dialect):
if value:
values = []
for v in value:
if isinstance(v, ToolCall):
if isinstance(v, OpenAIToolCall):
values.append(v.model_dump())
else:
values.append(v)
Expand All @@ -122,11 +123,11 @@ def process_result_value(self, value, dialect):
tools = []
for tool_value in value:
if "function" in tool_value:
tool_call_function = ToolCallFunction(**tool_value["function"])
tool_call_function = OpenAIFunction(**tool_value["function"])
del tool_value["function"]
else:
tool_call_function = None
tools.append(ToolCall(function=tool_call_function, **tool_value))
tools.append(OpenAIToolCall(function=tool_call_function, **tool_value))
return tools
return value

Expand Down
4 changes: 2 additions & 2 deletions letta/orm/message.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from typing import Optional

from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall as OpenAIToolCall
from sqlalchemy import ForeignKey, Index
from sqlalchemy.orm import Mapped, mapped_column, relationship

from letta.orm.custom_columns import ToolCallColumn
from letta.orm.mixins import AgentMixin, OrganizationMixin
from letta.orm.sqlalchemy_base import SqlalchemyBase
from letta.schemas.message import Message as PydanticMessage
from letta.schemas.openai.chat_completions import ToolCall


class Message(SqlalchemyBase, OrganizationMixin, AgentMixin):
Expand All @@ -22,7 +22,7 @@ class Message(SqlalchemyBase, OrganizationMixin, AgentMixin):
text: Mapped[Optional[str]] = mapped_column(nullable=True, doc="Message content")
model: Mapped[Optional[str]] = mapped_column(nullable=True, doc="LLM model used")
name: Mapped[Optional[str]] = mapped_column(nullable=True, doc="Name for multi-agent scenarios")
tool_calls: Mapped[ToolCall] = mapped_column(ToolCallColumn, doc="Tool call information")
tool_calls: Mapped[OpenAIToolCall] = mapped_column(ToolCallColumn, doc="Tool call information")
tool_call_id: Mapped[Optional[str]] = mapped_column(nullable=True, doc="ID of the tool call")
step_id: Mapped[Optional[str]] = mapped_column(
ForeignKey("steps.id", ondelete="SET NULL"), nullable=True, doc="ID of the step that this message belongs to"
Expand Down
5 changes: 5 additions & 0 deletions letta/orm/sqlalchemy_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,11 @@ def __pydantic_model__(self) -> "BaseModel":

def to_pydantic(self) -> "BaseModel":
"""converts to the basic pydantic model counterpart"""
if hasattr(self, "metadata_"):
model_dict = {k: v for k, v in self.__dict__.items() if k in self.__pydantic_model__.model_fields}
model_dict["metadata"] = self.metadata_
return self.__pydantic_model__.model_validate(model_dict)

return self.__pydantic_model__.model_validate(self)

def to_record(self) -> "BaseModel":
Expand Down
6 changes: 3 additions & 3 deletions letta/schemas/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class AgentState(OrmMetadataBase, validate_assignment=True):
organization_id: Optional[str] = Field(None, description="The unique identifier of the organization associated with the agent.")

description: Optional[str] = Field(None, description="The description of the agent.")
metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
metadata: Optional[Dict] = Field(None, description="The metadata of the agent.")

memory: Memory = Field(..., description="The in-context memory of the agent.")
tools: List[Tool] = Field(..., description="The tools used by the agent.")
Expand Down Expand Up @@ -122,7 +122,7 @@ class CreateAgent(BaseModel, validate_assignment=True): #
False, description="If true, attaches the Letta multi-agent tools (e.g. sending a message to another agent)."
)
description: Optional[str] = Field(None, description="The description of the agent.")
metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
metadata: Optional[Dict] = Field(None, description="The metadata of the agent.")
model: Optional[str] = Field(
None,
description="The LLM configuration handle used by the agent, specified in the format "
Expand Down Expand Up @@ -203,7 +203,7 @@ class UpdateAgent(BaseModel):
embedding_config: Optional[EmbeddingConfig] = Field(None, description="The embedding configuration used by the agent.")
message_ids: Optional[List[str]] = Field(None, description="The ids of the messages in the agent's in-context memory.")
description: Optional[str] = Field(None, description="The description of the agent.")
metadata_: Optional[Dict] = Field(None, description="The metadata of the agent.", alias="metadata_")
metadata: Optional[Dict] = Field(None, description="The metadata of the agent.")
tool_exec_environment_variables: Optional[Dict[str, str]] = Field(
None, description="The environment variables for tool execution specific to this agent."
)
Expand Down
Loading

0 comments on commit fd66fbf

Please sign in to comment.