mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-13 05:25:07 +00:00
core[patch]: Add pydantic metadata to subset model (#25032)
- **Description:** This includes Pydantic field metadata in `_create_subset_model_v2` so that it gets included in the final serialized form that get sent out. - **Issue:** #25031 - **Dependencies:** n/a - **Twitter handle:** @gramliu --------- Co-authored-by: Bagatur <baskaryan@gmail.com> Co-authored-by: Bagatur <22008038+baskaryan@users.noreply.github.com>
This commit is contained in:
@@ -1863,3 +1863,41 @@ def test__get_all_basemodel_annotations_v1() -> None:
|
||||
}
|
||||
actual = _get_all_basemodel_annotations(ModelD[int])
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.skipif(PYDANTIC_MAJOR_VERSION != 2, reason="Testing pydantic v2.")
|
||||
def test_tool_args_schema_pydantic_v2_with_metadata() -> None:
|
||||
from pydantic import BaseModel as BaseModelV2 # pydantic: ignore
|
||||
from pydantic import Field as FieldV2 # pydantic: ignore
|
||||
from pydantic import ValidationError as ValidationErrorV2 # pydantic: ignore
|
||||
|
||||
class Foo(BaseModelV2):
|
||||
x: List[int] = FieldV2(
|
||||
description="List of integers", min_length=10, max_length=15
|
||||
)
|
||||
|
||||
@tool(args_schema=Foo)
|
||||
def foo(x): # type: ignore[no-untyped-def]
|
||||
"""foo"""
|
||||
return x
|
||||
|
||||
assert foo.tool_call_schema.schema() == {
|
||||
"description": "foo",
|
||||
"properties": {
|
||||
"x": {
|
||||
"description": "List of integers",
|
||||
"items": {"type": "integer"},
|
||||
"maxItems": 15,
|
||||
"minItems": 10,
|
||||
"title": "X",
|
||||
"type": "array",
|
||||
}
|
||||
},
|
||||
"required": ["x"],
|
||||
"title": "foo",
|
||||
"type": "object",
|
||||
}
|
||||
|
||||
assert foo.invoke({"x": [0] * 10})
|
||||
with pytest.raises(ValidationErrorV2):
|
||||
foo.invoke({"x": [0] * 9})
|
||||
|
@@ -1,10 +1,13 @@
|
||||
"""Test for some custom pydantic decorators."""
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import pytest
|
||||
|
||||
from langchain_core.pydantic_v1 import BaseModel, Field
|
||||
from langchain_core.utils.pydantic import (
|
||||
PYDANTIC_MAJOR_VERSION,
|
||||
_create_subset_model_v2,
|
||||
is_basemodel_instance,
|
||||
is_basemodel_subclass,
|
||||
pre_init,
|
||||
@@ -121,3 +124,32 @@ def test_is_basemodel_instance() -> None:
|
||||
assert is_basemodel_instance(Bar(x=5))
|
||||
else:
|
||||
raise ValueError(f"Unsupported Pydantic version: {PYDANTIC_MAJOR_VERSION}")
|
||||
|
||||
|
||||
@pytest.mark.skipif(PYDANTIC_MAJOR_VERSION != 2, reason="Only tests Pydantic v2")
|
||||
def test_with_field_metadata() -> None:
|
||||
"""Test pydantic with field metadata"""
|
||||
from pydantic import BaseModel as BaseModelV2 # pydantic: ignore
|
||||
from pydantic import Field as FieldV2 # pydantic: ignore
|
||||
|
||||
class Foo(BaseModelV2):
|
||||
x: List[int] = FieldV2(
|
||||
description="List of integers", min_length=10, max_length=15
|
||||
)
|
||||
|
||||
subset_model = _create_subset_model_v2("Foo", Foo, ["x"])
|
||||
assert subset_model.model_json_schema() == {
|
||||
"properties": {
|
||||
"x": {
|
||||
"description": "List of integers",
|
||||
"items": {"type": "integer"},
|
||||
"maxItems": 15,
|
||||
"minItems": 10,
|
||||
"title": "X",
|
||||
"type": "array",
|
||||
}
|
||||
},
|
||||
"required": ["x"],
|
||||
"title": "Foo",
|
||||
"type": "object",
|
||||
}
|
||||
|
Reference in New Issue
Block a user