Skip to main content

Pydantic shim for config stuff

Project description

Schemez

PyPI License Package status Monthly downloads Distribution format Wheel availability Python version Implementation Releases Github Contributors Github Discussions Github Forks Github Issues Github Issues Github Watchers Github Stars Github Repository size Github last commit Github release date Github language count Github commits this month Package status PyUp

Read the documentation!

OpenAI Function Schema Generator

Convert Python functions to OpenAI-compatible function schemas automatically.

Installation

pip install schemez

Basic Usage

from schemez import create_schema
from typing import Literal

def get_weather(
    location: str,
    unit: Literal["C", "F"] = "C",
    detailed: bool = False,
) -> dict[str, str | float]:
    """Get the weather for a location.

    Args:
        location: City or address to get weather for
        unit: Temperature unit (Celsius or Fahrenheit)
        detailed: Include extended forecast
    """
    return {"temp": 22.5, "conditions": "sunny"}

# Create schema
schema = create_schema(get_weather)

# The schema.model_dump_openai() returns a TypedDict with the complete OpenAI tool definition:
# OpenAIFunctionTool = TypedDict({
#     "type": Literal["function"],
#     "function": OpenAIFunctionDefinition
# })

# Use with OpenAI
from openai import OpenAI

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "What's the weather in London?"}],
    tools=[schema.model_dump_openai()],  # Schema includes the type: "function" wrapper
    tool_choice="auto"
)

Note: This library supports the OpenAI API v1 format (openai>=1.0.0). For older versions of the OpenAI package that use the legacy functions API, you'll need to unwrap the function definition using schema.model_dump_openai()["function"].


## Supported Types

### Basic Types
```python
def func(
    text: str,              # -> "type": "string"
    number: int,            # -> "type": "integer"
    amount: float,          # -> "type": "number"
    enabled: bool,          # -> "type": "boolean"
    anything: Any,          # -> "type": "string"
) -> None: ...

Container Types

def func(
    items: list[str],                    # -> "type": "array", "items": {"type": "string"}
    numbers: set[int],                   # -> same as list
    mapping: dict[str, Any],            # -> "type": "object", "additionalProperties": true
    nested: list[dict[str, int]],       # -> nested array/object types
    sequence: Sequence[str],            # -> "type": "array"
    collection: Collection[int],        # -> "type": "array"
) -> None: ...

Enums and Literals

class Color(Enum):
    RED = "red"
    BLUE = "blue"

def func(
    color: Color,                       # -> "type": "string", "enum": ["red", "blue"]
    mode: Literal["fast", "slow"],      # -> "type": "string", "enum": ["fast", "slow"]
) -> None: ...

Optional and Union Types

def func(
    opt1: str | None,                   # -> "type": "string"
    opt2: int | None,                   # -> "type": "integer"
    union: str | int,                   # -> "type": "string" (first type)
) -> None: ...

Custom Types

@dataclass
class User:
    name: str
    age: int

def func(
    user: User,                         # -> "type": "object"
    data: JsonDict,                     # -> "type": "object"
) -> None: ...

Type Aliases

JsonValue = dict[str, Any] | list[Any] | str | int | float | bool | None
JsonDict = dict[str, JsonValue]

def func(
    data: JsonDict,                     # -> "type": "object"
    values: list[JsonValue],            # -> "type": "array"
) -> None: ...

Recursive Types

def func(
    tree: dict[str, "dict[str, Any] | str"],  # -> "type": "object"
    nested: dict[str, list["dict[str, Any]"]], # -> "type": "object"
) -> None: ...

Generated Schema Example

{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the weather for a location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "City or address to get weather for"
                },
                "unit": {
                    "type": "string",
                    "enum": ["C", "F"],
                    "description": "Temperature unit (Celsius or Fahrenheit)",
                    "default": "C"
                },
                "detailed": {
                    "type": "boolean",
                    "description": "Include extended forecast",
                    "default": false
                }
            },
            "required": ["location"]
        }
    }
}

Schema Generators

Module Schemas

You can generate schemas for all public functions in a module using create_schemas_from_module:

from schemez import create_schemas_from_module
import math

# Generate schemas for all public functions
schemas = create_schemas_from_module(math)

# Generate schemas for specific functions only
schemas = create_schemas_from_module(math, include_functions=['sin', 'cos'])

# Import module by string name
schemas = create_schemas_from_module('math')

Class Schemas

Generate schemas for all public methods in a class using create_schemas_from_class:

from schemez import create_schemas_from_class

class Calculator:
    def add(self, x: int, y: int) -> int:
        """Add two numbers.

        Args:
            x: First number
            y: Second number

        Returns:
            Sum of x and y
        """
        return x + y

    @classmethod
    def multiply(cls, x: int, y: int) -> int:
        """Multiply two numbers.

        Args:
            x: First number
            y: Second number

        Returns:
            Product of x and y
        """
        return x * y

    @staticmethod
    def divide(x: float, y: float) -> float:
        """Divide two numbers.

        Args:
            x: Numerator
            y: Denominator

        Returns:
            Result of x divided by y
        """
        return x / y

# Generate schemas for all public methods
schemas = create_schemas_from_class(Calculator)

# Access individual method schemas
add_schema = schemas['Calculator.add']
multiply_schema = schemas['Calculator.multiply']
divide_schema = schemas['Calculator.divide']

The schema generators support:

  • Regular functions
  • Regular instance methods (bound and unbound)
  • Class methods
  • Static methods
  • Decorated functions / methods
  • Async functions / methods
  • Property methods
  • Basically all stdlib typing features as well as many stdlib types
  • Method docstrings for descriptions
  • Default values
  • Return type hints

Diferences to pydantic schema generation

While Pydantics schema generation preserves detailed type information, schema.model_dump_openai() simplifies types to match OpenAI's function calling format. Most special types (datetime, UUID, Path, etc.) are handled similarly by both (we only strip unused information), but we handle enums differently: Instead of preserving enum class information, we extract just the values as a string enum. Union types and Optionals are also handled differently - we typically pick the first type to keep the schema simple and practical for AI interaction. This ensures compatibility with OpenAI's function calling API while maintaining enough type information for the AI to understand the function signature.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

schemez-2.0.0.tar.gz (45.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

schemez-2.0.0-py3-none-any.whl (55.2 kB view details)

Uploaded Python 3

File details

Details for the file schemez-2.0.0.tar.gz.

File metadata

  • Download URL: schemez-2.0.0.tar.gz
  • Upload date:
  • Size: 45.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for schemez-2.0.0.tar.gz
Algorithm Hash digest
SHA256 0cdeb34172199b11d590656bdd6541a50f04e7b3d8c72529cebf452e08d5ace6
MD5 14a24532315b0d6f900ffb126c0039ae
BLAKE2b-256 2fb990ab9d7f29a7334aef13c194ddae28cd55a1b45cb73e9e40b8d0213e17cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for schemez-2.0.0.tar.gz:

Publisher: build.yml on phil65/schemez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file schemez-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: schemez-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 55.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for schemez-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8eae5a0f6653dfa7665fe8285b58d069aad9caac5eab202ec58eaf463dbda5aa
MD5 06e396fbe3a10bc635ff1e7176e4e1e2
BLAKE2b-256 1fd2392eeb5f2ba2b0fd80e06fae822126bd40b3eada9f74fb84e4f538f9f304

See more details on using hashes here.

Provenance

The following attestation bundles were made for schemez-2.0.0-py3-none-any.whl:

Publisher: build.yml on phil65/schemez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page