Implementation:Run llama Llama index Tool Schema Utils
Overview
The utils.py module provides the create_schema_from_function utility, which dynamically generates a Pydantic BaseModel class from a Python function's signature. This auto-generated schema is used throughout the LlamaIndex tool framework to produce JSON schemas that describe a tool's expected parameters, enabling LLMs to correctly invoke tools with properly structured arguments.
Source File: llama-index-core/llama_index/core/tools/utils.py
Module: llama_index.core.tools.utils
Lines of Code: 108
Dependencies
| Dependency | Type | Purpose |
|---|---|---|
inspect.signature |
Standard Library | Introspection of function parameter signatures |
typing |
Standard Library | Type annotation utilities (Any, Awaitable, Callable, List, Optional, Tuple, Type, Union, cast, get_origin, get_args)
|
datetime |
Standard Library | Date/time type detection for JSON schema format hints |
llama_index.core.bridge.pydantic.BaseModel |
Internal | Base class for generated schema models |
llama_index.core.bridge.pydantic.FieldInfo |
Internal | Field metadata for schema fields |
llama_index.core.bridge.pydantic.create_model |
Internal | Dynamic Pydantic model creation |
Function: create_schema_from_function
Signature
def create_schema_from_function(
name: str,
func: Union[Callable[..., Any], Callable[..., Awaitable[Any]]],
additional_fields: Optional[
List[Union[Tuple[str, Type, Any], Tuple[str, Type]]]
] = None,
ignore_fields: Optional[List[str]] = None,
) -> Type[BaseModel]
Parameters
| Parameter | Type | Description |
|---|---|---|
name |
str |
Name for the generated Pydantic model class |
func |
Union[Callable, Callable[..., Awaitable]] |
The function whose signature will be analyzed (supports both sync and async functions) |
additional_fields |
Optional[List[...]] |
Extra fields to add beyond what is in the function signature; each entry is a tuple of (name, type, default) or (name, type)
|
ignore_fields |
Optional[List[str]] |
Parameter names to skip when building the schema |
Return Value
Returns a dynamically created Type[BaseModel] -- a Pydantic model class whose fields correspond to the function's parameters.
Processing Logic
The function processes each parameter from the function signature through the following steps:
Step 1: Parameter Iteration
Iterates over all parameters in the function signature (obtained via inspect.signature(func).parameters), skipping any in the ignore_fields list.
Step 2: Annotated Type Handling
If a parameter's type annotation is typing.Annotated, the function extracts:
- The actual type from the first argument.
- A description string if the second argument is a
str. - A
FieldInfoobject if the second argument is aFieldInfo, extracting its description and anyjson_schema_extra.
if get_origin(param_type) is typing.Annotated:
args = get_args(param_type)
param_type = args[0]
if isinstance(args[1], str):
description = args[1]
elif isinstance(args[1], FieldInfo):
description = args[1].description
if args[1].json_schema_extra and isinstance(args[1].json_schema_extra, dict):
json_schema_extra.update(args[1].json_schema_extra)
Step 3: DateTime Format Injection
Automatically adds JSON schema format hints for standard datetime types:
| Python Type | JSON Schema Format |
|---|---|
datetime.date |
"date"
|
datetime.datetime |
"date-time"
|
datetime.time |
"time"
|
Uses setdefault to avoid overwriting any format already provided via Annotated metadata.
Step 4: Missing Annotation Handling
If a parameter has no type annotation (param_type is params[param_name].empty), the type defaults to Any.
Step 5: Field Construction
Three cases for building the field tuple:
- No default value (required parameter): Creates a
FieldInfowith description and json_schema_extra. - Default is a
FieldInfoinstance: Uses the existingFieldInfodirectly (supportspydantic.Fieldas a default value). - Has a regular default value: Creates a
FieldInfowith the default value, description, and json_schema_extra.
Step 6: Additional Fields
Processes the additional_fields list:
- 3-element tuples
(name, type, default): Creates a field with the specified default. - 2-element tuples
(name, type): Creates a required field. - Other lengths raise a
ValueError.
Step 7: Model Creation
Calls create_model(name, **fields) to dynamically construct and return the Pydantic model.
Usage Examples
Basic Usage
The function is used internally by tool classes to generate schemas:
# In OnDemandLoaderTool.from_defaults:
fn_schema = create_schema_from_function(
name or "LoadData",
reader.load_data,
[(query_str_kwargs_key, str, None)],
)
This generates a Pydantic model that mirrors the reader.load_data signature, plus an additional query_str field.
With Annotated Types
Functions using typing.Annotated for parameter descriptions are fully supported:
from typing import Annotated
def my_func(query: Annotated[str, "The search query"]) -> str:
...
schema = create_schema_from_function("MyFunc", my_func)
# Results in a model with a 'query' field of type str and description "The search query"
Design Patterns
Reflection-Based Schema Generation
The function uses Python's inspect module to reflect on function signatures at runtime. This eliminates the need for manual schema definitions and keeps tool schemas in sync with their underlying function signatures.
Extensible Field System
The additional_fields parameter allows callers to inject extra parameters into the schema that do not exist in the original function signature. This is used, for example, by OnDemandLoaderTool to add a query_str parameter that is consumed by the tool wrapper rather than the underlying loader function.
Pydantic Integration
By producing a Pydantic BaseModel, the generated schema integrates directly with Pydantic's JSON schema generation (model.model_json_schema()), which is used to produce OpenAI-compatible function calling schemas.
See Also
- Implementation:Run_llama_Llama_index_Tool_Calling - Tool invocation utilities that use tools with these schemas
- Implementation:Run_llama_Llama_index_OnDemandLoaderTool - Consumer of
create_schema_from_function - Implementation:Run_llama_Llama_index_QueryPlanTool - Uses Pydantic models as tool schemas