|
from ast import literal_eval |
|
from typing import Any, Literal, Optional, Type |
|
|
|
from pydantic import BaseModel, Field, create_model |
|
|
|
|
|
def json_schema_to_model(tool_dict: dict[str, Any]) -> Type[BaseModel]: |
|
""" |
|
Converts a JSON schema to a Pydantic BaseModel class. |
|
|
|
Args: |
|
json_schema: The JSON schema to convert. |
|
|
|
Returns: |
|
A Pydantic BaseModel class. |
|
""" |
|
|
|
|
|
model_name = tool_dict["name"] |
|
schema = tool_dict["parameters"] |
|
|
|
|
|
field_definitions = { |
|
name: json_schema_to_pydantic_field(name, prop, schema.get("required", [])) |
|
for name, prop in schema.get("properties", {}).items() |
|
} |
|
|
|
|
|
return create_model(model_name, **field_definitions) |
|
|
|
|
|
def json_schema_to_pydantic_field( |
|
name: str, json_schema: dict[str, Any], required: list[str] |
|
) -> Any: |
|
""" |
|
Converts a JSON schema property to a Pydantic field definition. |
|
|
|
Args: |
|
name: The field name. |
|
json_schema: The JSON schema property. |
|
|
|
Returns: |
|
A Pydantic field definition. |
|
""" |
|
|
|
|
|
type_ = json_schema_to_pydantic_type(json_schema) |
|
|
|
|
|
description = json_schema.get("description") |
|
|
|
|
|
examples = json_schema.get("examples") |
|
|
|
|
|
|
|
return ( |
|
type_, |
|
Field( |
|
description=description, |
|
examples=examples, |
|
default=... if name in required else None, |
|
), |
|
) |
|
|
|
|
|
def json_schema_to_pydantic_type(json_schema: dict[str, Any]) -> Any: |
|
""" |
|
Converts a JSON schema type to a Pydantic type. |
|
|
|
Args: |
|
json_schema: The JSON schema to convert. |
|
|
|
Returns: |
|
A Pydantic type. |
|
""" |
|
|
|
type_ = json_schema.get("type") |
|
|
|
if type_ == "string" or type_ == "str": |
|
return str |
|
elif type_ == "integer" or type_ == "int": |
|
return int |
|
elif type_ == "number" or type_ == "float": |
|
return float |
|
elif type_ == "boolean" or type_ == "bool": |
|
return bool |
|
elif type_ == "array" or type_ == "list": |
|
items_schema = json_schema.get("items") |
|
if items_schema: |
|
item_type = json_schema_to_pydantic_type(items_schema) |
|
return list[item_type] |
|
else: |
|
return list |
|
elif type_ == "object": |
|
|
|
properties = json_schema.get("properties") |
|
if properties: |
|
nested_model = json_schema_to_model(json_schema) |
|
return nested_model |
|
else: |
|
return dict |
|
elif type_ == "null": |
|
return Optional[Any] |
|
elif type_ == "literal": |
|
return Literal[literal_eval(json_schema.get("enum"))] |
|
elif type_ == "optional": |
|
inner_schema = json_schema.get("items", {"type": "string"}) |
|
inner_type = json_schema_to_pydantic_type(inner_schema) |
|
return Optional[inner_type] |
|
else: |
|
raise ValueError(f"Unsupported JSON schema type: {type_}") |
|
|