feat: Support writing packed func return to ToolReturn object (#5209)
* wip * Add func_response to ToolReturn object * Fix response packaging * Backpopulate in to_pydantic * Fix ordering of packaging * Add more checks
This commit is contained in:
committed by
Caren Thomas
parent
c31521c7ad
commit
0f27bf5bdd
@@ -33961,6 +33961,18 @@
|
||||
],
|
||||
"title": "Stderr",
|
||||
"description": "Captured stderr from the tool invocation"
|
||||
},
|
||||
"func_response": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Func Response",
|
||||
"description": "The function response string"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
|
||||
@@ -7,7 +7,8 @@ from sqlalchemy.orm import Mapped, Session, mapped_column, relationship
|
||||
from letta.orm.custom_columns import MessageContentColumn, ToolCallColumn, ToolReturnColumn
|
||||
from letta.orm.mixins import AgentMixin, OrganizationMixin
|
||||
from letta.orm.sqlalchemy_base import SqlalchemyBase
|
||||
from letta.schemas.letta_message_content import MessageContent, TextContent as PydanticTextContent
|
||||
from letta.schemas.enums import MessageRole
|
||||
from letta.schemas.letta_message_content import MessageContent, TextContent, TextContent as PydanticTextContent
|
||||
from letta.schemas.message import Message as PydanticMessage, ToolReturn
|
||||
from letta.settings import DatabaseChoice, settings
|
||||
|
||||
@@ -89,6 +90,18 @@ class Message(SqlalchemyBase, OrganizationMixin, AgentMixin):
|
||||
# If there are no tool calls, set tool_calls to None
|
||||
if self.tool_calls is None or len(self.tool_calls) == 0:
|
||||
model.tool_calls = None
|
||||
|
||||
# Handle legacy case of tool message with single tool return + single text content
|
||||
if (
|
||||
self.role == MessageRole.tool
|
||||
and self.tool_returns
|
||||
and len(self.tool_returns) == 1
|
||||
and self.content
|
||||
and len(self.content) == 1
|
||||
and isinstance(self.content[0], TextContent)
|
||||
):
|
||||
self.tool_returns[0].func_response = self.content[0].text
|
||||
|
||||
return model
|
||||
|
||||
|
||||
|
||||
@@ -547,7 +547,9 @@ class Message(BaseMessage):
|
||||
"time": formatted_time,
|
||||
}
|
||||
"""
|
||||
if self.content and len(self.content) == 1 and isinstance(self.content[0], TextContent):
|
||||
if self.tool_returns and len(self.tool_returns) == 1:
|
||||
text_content = self.tool_returns[0].func_response
|
||||
elif self.content and len(self.content) == 1 and isinstance(self.content[0], TextContent):
|
||||
text_content = self.content[0].text
|
||||
else:
|
||||
raise ValueError(f"Invalid tool return (no text object on message): {self.content}")
|
||||
@@ -1506,7 +1508,7 @@ class ToolReturn(BaseModel):
|
||||
status: Literal["success", "error"] = Field(..., description="The status of the tool call")
|
||||
stdout: Optional[List[str]] = Field(default=None, description="Captured stdout (e.g. prints, logs) from the tool invocation")
|
||||
stderr: Optional[List[str]] = Field(default=None, description="Captured stderr from the tool invocation")
|
||||
# func_return: Optional[Any] = Field(None, description="The function return object")
|
||||
func_response: Optional[str] = Field(None, description="The function response string")
|
||||
|
||||
|
||||
class MessageSearchRequest(BaseModel):
|
||||
|
||||
@@ -319,9 +319,10 @@ def create_letta_messages_from_llm_response(
|
||||
# TODO: Use ToolReturnContent instead of TextContent
|
||||
# TODO: This helps preserve ordering
|
||||
if tool_execution_result is not None:
|
||||
packaged_function_response = package_function_response(tool_execution_result.success_flag, function_response, timezone)
|
||||
tool_message = Message(
|
||||
role=MessageRole.tool,
|
||||
content=[TextContent(text=package_function_response(tool_execution_result.success_flag, function_response, timezone))],
|
||||
content=[TextContent(text=packaged_function_response)],
|
||||
agent_id=agent_id,
|
||||
model=model,
|
||||
tool_calls=[],
|
||||
@@ -335,7 +336,7 @@ def create_letta_messages_from_llm_response(
|
||||
status=tool_execution_result.status,
|
||||
stderr=tool_execution_result.stderr,
|
||||
stdout=tool_execution_result.stdout,
|
||||
# func_return=tool_execution_result.func_return,
|
||||
func_response=packaged_function_response,
|
||||
)
|
||||
],
|
||||
run_id=run_id,
|
||||
|
||||
Reference in New Issue
Block a user