schemas.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from pydantic import BaseModel, Field, create_model
  2. from typing import Any, Optional, Type
  3. def json_schema_to_model(tool_dict: dict[str, Any]) -> Type[BaseModel]:
  4. """
  5. Converts a JSON schema to a Pydantic BaseModel class.
  6. Args:
  7. json_schema: The JSON schema to convert.
  8. Returns:
  9. A Pydantic BaseModel class.
  10. """
  11. # Extract the model name from the schema title.
  12. model_name = tool_dict["name"]
  13. schema = tool_dict["parameters"]
  14. # Extract the field definitions from the schema properties.
  15. field_definitions = {
  16. name: json_schema_to_pydantic_field(name, prop, schema.get("required", []))
  17. for name, prop in schema.get("properties", {}).items()
  18. }
  19. # Create the BaseModel class using create_model().
  20. return create_model(model_name, **field_definitions)
  21. def json_schema_to_pydantic_field(
  22. name: str, json_schema: dict[str, Any], required: list[str]
  23. ) -> Any:
  24. """
  25. Converts a JSON schema property to a Pydantic field definition.
  26. Args:
  27. name: The field name.
  28. json_schema: The JSON schema property.
  29. Returns:
  30. A Pydantic field definition.
  31. """
  32. # Get the field type.
  33. type_ = json_schema_to_pydantic_type(json_schema)
  34. # Get the field description.
  35. description = json_schema.get("description")
  36. # Get the field examples.
  37. examples = json_schema.get("examples")
  38. # Create a Field object with the type, description, and examples.
  39. # The 'required' flag will be set later when creating the model.
  40. return (
  41. type_,
  42. Field(
  43. description=description,
  44. examples=examples,
  45. default=... if name in required else None,
  46. ),
  47. )
  48. def json_schema_to_pydantic_type(json_schema: dict[str, Any]) -> Any:
  49. """
  50. Converts a JSON schema type to a Pydantic type.
  51. Args:
  52. json_schema: The JSON schema to convert.
  53. Returns:
  54. A Pydantic type.
  55. """
  56. type_ = json_schema.get("type")
  57. if type_ == "string" or type_ == "str":
  58. return str
  59. elif type_ == "integer" or type_ == "int":
  60. return int
  61. elif type_ == "number" or type_ == "float":
  62. return float
  63. elif type_ == "boolean" or type_ == "bool":
  64. return bool
  65. elif type_ == "array" or type_ == "list":
  66. items_schema = json_schema.get("items")
  67. if items_schema:
  68. item_type = json_schema_to_pydantic_type(items_schema)
  69. return list[item_type]
  70. else:
  71. return list
  72. elif type_ == "object":
  73. # Handle nested models.
  74. properties = json_schema.get("properties")
  75. if properties:
  76. nested_model = json_schema_to_model(json_schema)
  77. return nested_model
  78. else:
  79. return dict
  80. elif type_ == "null":
  81. return Optional[Any] # Use Optional[Any] for nullable fields
  82. else:
  83. raise ValueError(f"Unsupported JSON schema type: {type_}")