Merge branch 'main' into matt/let-671-for-local-sandbox-using-local-env-variables-instead-of
This commit is contained in:
@@ -396,44 +396,6 @@ def generate_schema(function, name: Optional[str] = None, description: Optional[
|
||||
return schema
|
||||
|
||||
|
||||
def generate_schema_from_args_schema_v1(
|
||||
args_schema: Type[V1BaseModel], name: Optional[str] = None, description: Optional[str] = None, append_heartbeat: bool = True
|
||||
) -> Dict[str, Any]:
|
||||
properties = {}
|
||||
required = []
|
||||
for field_name, field in args_schema.__fields__.items():
|
||||
if field.type_ == str:
|
||||
field_type = "string"
|
||||
elif field.type_ == int:
|
||||
field_type = "integer"
|
||||
elif field.type_ == bool:
|
||||
field_type = "boolean"
|
||||
else:
|
||||
field_type = field.type_.__name__
|
||||
|
||||
properties[field_name] = {
|
||||
"type": field_type,
|
||||
"description": field.field_info.description,
|
||||
}
|
||||
if field.required:
|
||||
required.append(field_name)
|
||||
|
||||
function_call_json = {
|
||||
"name": name,
|
||||
"description": description,
|
||||
"parameters": {"type": "object", "properties": properties, "required": required},
|
||||
}
|
||||
|
||||
if append_heartbeat:
|
||||
function_call_json["parameters"]["properties"]["request_heartbeat"] = {
|
||||
"type": "boolean",
|
||||
"description": "Request an immediate heartbeat after function execution. Set to `True` if you want to send a follow-up message or run a follow-up function.",
|
||||
}
|
||||
function_call_json["parameters"]["required"].append("request_heartbeat")
|
||||
|
||||
return function_call_json
|
||||
|
||||
|
||||
def generate_schema_from_args_schema_v2(
|
||||
args_schema: Type[BaseModel], name: Optional[str] = None, description: Optional[str] = None, append_heartbeat: bool = True
|
||||
) -> Dict[str, Any]:
|
||||
@@ -441,19 +403,8 @@ def generate_schema_from_args_schema_v2(
|
||||
required = []
|
||||
for field_name, field in args_schema.model_fields.items():
|
||||
field_type_annotation = field.annotation
|
||||
if field_type_annotation == str:
|
||||
field_type = "string"
|
||||
elif field_type_annotation == int:
|
||||
field_type = "integer"
|
||||
elif field_type_annotation == bool:
|
||||
field_type = "boolean"
|
||||
else:
|
||||
field_type = field_type_annotation.__name__
|
||||
|
||||
properties[field_name] = {
|
||||
"type": field_type,
|
||||
"description": field.description,
|
||||
}
|
||||
properties[field_name] = type_to_json_schema_type(field_type_annotation)
|
||||
properties[field_name]["description"] = field.description
|
||||
if field.is_required():
|
||||
required.append(field_name)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import pytest
|
||||
|
||||
from letta.functions.functions import derive_openai_json_schema
|
||||
from letta.llm_api.helpers import convert_to_structured_output, make_post_request
|
||||
from letta.schemas.tool import ToolCreate
|
||||
|
||||
|
||||
def _clean_diff(d1, d2):
|
||||
@@ -176,3 +177,38 @@ def test_valid_schemas_via_openai(openai_model: str, structured_output: bool):
|
||||
_openai_payload(openai_model, schema, structured_output)
|
||||
else:
|
||||
_openai_payload(openai_model, schema, structured_output)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("openai_model", ["gpt-4o-mini"])
|
||||
@pytest.mark.parametrize("structured_output", [True])
|
||||
def test_composio_tool_schema_generation(openai_model: str, structured_output: bool):
|
||||
"""Test that we can generate the schemas for some Composio tools."""
|
||||
|
||||
if not os.getenv("COMPOSIO_API_KEY"):
|
||||
pytest.skip("COMPOSIO_API_KEY not set")
|
||||
|
||||
try:
|
||||
import composio
|
||||
except ImportError:
|
||||
pytest.skip("Composio not installed")
|
||||
|
||||
for action_name in [
|
||||
"CAL_GET_AVAILABLE_SLOTS_INFO", # has an array arg, needs to be converted properly
|
||||
]:
|
||||
try:
|
||||
tool_create = ToolCreate.from_composio(action_name=action_name)
|
||||
except composio.exceptions.ComposioSDKError:
|
||||
# e.g. "composio.exceptions.ComposioSDKError: No connected account found for app `CAL`; Run `composio add cal` to fix this"
|
||||
pytest.skip(f"Composio account not configured to use action_name {action_name}")
|
||||
|
||||
print(tool_create)
|
||||
|
||||
assert tool_create.json_schema
|
||||
schema = tool_create.json_schema
|
||||
|
||||
try:
|
||||
_openai_payload(openai_model, schema, structured_output)
|
||||
print(f"Successfully called OpenAI using schema {schema} generated from {action_name}")
|
||||
except:
|
||||
print(f"Failed to call OpenAI using schema {schema} generated from {action_name}")
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user