mirror of
https://github.com/hwchase17/langchain.git
synced 2026-03-18 02:53:16 +00:00
fix(core): improve error message for non-JSON-serializable tool schemas (#34376)
This commit is contained in:
committed by
GitHub
parent
d6e46bb4b0
commit
2d1492a864
@@ -22,6 +22,7 @@ from typing import (
|
||||
|
||||
import typing_extensions
|
||||
from pydantic import BaseModel
|
||||
from pydantic.errors import PydanticInvalidForJsonSchema
|
||||
from pydantic.v1 import BaseModel as BaseModelV1
|
||||
from pydantic.v1 import Field as Field_v1
|
||||
from pydantic.v1 import create_model as create_model_v1
|
||||
@@ -176,17 +177,32 @@ def _convert_pydantic_to_openai_function(
|
||||
|
||||
Raises:
|
||||
TypeError: If the model is not a Pydantic model.
|
||||
TypeError: If the model contains types that cannot be converted to JSON schema.
|
||||
|
||||
Returns:
|
||||
The function description.
|
||||
"""
|
||||
if hasattr(model, "model_json_schema"):
|
||||
schema = model.model_json_schema() # Pydantic 2
|
||||
elif hasattr(model, "schema"):
|
||||
schema = model.schema() # Pydantic 1
|
||||
else:
|
||||
msg = "Model must be a Pydantic model."
|
||||
raise TypeError(msg)
|
||||
try:
|
||||
if hasattr(model, "model_json_schema"):
|
||||
schema = model.model_json_schema() # Pydantic 2
|
||||
elif hasattr(model, "schema"):
|
||||
schema = model.schema() # Pydantic 1
|
||||
else:
|
||||
msg = "Model must be a Pydantic model."
|
||||
raise TypeError(msg)
|
||||
except PydanticInvalidForJsonSchema as e:
|
||||
model_name = getattr(model, "__name__", str(model))
|
||||
msg = (
|
||||
f"Failed to generate JSON schema for '{model_name}': {e}\n\n"
|
||||
"Tool argument schemas must be JSON-serializable. If your schema includes "
|
||||
"custom Python classes, consider:\n"
|
||||
" 1. Converting them to Pydantic models with JSON-compatible fields\n"
|
||||
" 2. Using primitive types (str, int, float, bool, list, dict) instead\n"
|
||||
" 3. Passing the data as serialized JSON strings\n\n"
|
||||
"For more information, see: "
|
||||
"https://python.langchain.com/docs/how_to/custom_tools/"
|
||||
)
|
||||
raise PydanticInvalidForJsonSchema(msg) from e
|
||||
return _convert_json_schema_to_openai_function(
|
||||
schema, name=name, description=description, rm_titles=rm_titles
|
||||
)
|
||||
|
||||
@@ -22,7 +22,8 @@ except ImportError:
|
||||
from importlib.metadata import version
|
||||
|
||||
from packaging.version import parse
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from pydantic.errors import PydanticInvalidForJsonSchema
|
||||
|
||||
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
|
||||
from langchain_core.runnables import Runnable, RunnableLambda
|
||||
@@ -1171,6 +1172,38 @@ def test_convert_to_openai_function_strict_required() -> None:
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_convert_to_openai_function_arbitrary_type_error() -> None:
|
||||
"""Test that a helpful error is raised for non-JSON-serializable types.
|
||||
|
||||
When a Pydantic model contains a custom Python class that cannot be
|
||||
serialized to JSON schema, we should raise a PydanticInvalidForJsonSchema
|
||||
with a helpful error message explaining the issue and suggesting solutions.
|
||||
|
||||
See: https://github.com/langchain-ai/langchain/issues/34371
|
||||
"""
|
||||
|
||||
# Define a custom Python class that isn't JSON-serializable
|
||||
class CustomClass:
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
class SchemaWithArbitraryType(BaseModel):
|
||||
"""Schema with arbitrary type."""
|
||||
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
custom_obj: CustomClass = Field(..., description="A custom object")
|
||||
name: str = Field(..., description="A name")
|
||||
|
||||
with pytest.raises(PydanticInvalidForJsonSchema) as exc_info:
|
||||
convert_to_openai_function(SchemaWithArbitraryType)
|
||||
|
||||
error_message = str(exc_info.value)
|
||||
# Check that the error message contains helpful information
|
||||
assert "SchemaWithArbitraryType" in error_message
|
||||
assert "JSON-serializable" in error_message
|
||||
assert "Pydantic models" in error_message
|
||||
|
||||
|
||||
def test_convert_to_openai_function_strict_defaults() -> None:
|
||||
class MyModel(BaseModel):
|
||||
"""Dummy schema."""
|
||||
|
||||
Reference in New Issue
Block a user