123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- 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.
- """
- # Extract the model name from the schema title.
- model_name = tool_dict["name"]
- schema = tool_dict["parameters"]
- # Extract the field definitions from the schema properties.
- field_definitions = {
- name: json_schema_to_pydantic_field(name, prop, schema.get("required", []))
- for name, prop in schema.get("properties", {}).items()
- }
- # Create the BaseModel class using create_model().
- 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.
- """
- # Get the field type.
- type_ = json_schema_to_pydantic_type(json_schema)
- # Get the field description.
- description = json_schema.get("description")
- # Get the field examples.
- examples = json_schema.get("examples")
- # Create a Field object with the type, description, and examples.
- # The 'required' flag will be set later when creating the model.
- 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":
- # Handle nested models.
- 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] # Use Optional[Any] for nullable fields
- elif type_ == "literal":
- enum = json_schema.get("enum")
- if enum is None:
- raise ValueError("Enum values must be provided for 'literal' type.")
- return Literal[literal_eval(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_}")
|