mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-28 06:48:50 +00:00
core[major]: Add restrictions on create_model field names to match pydantic constraints (#26345)
Pydantic 2 is stricter in terms of which field names are allowed in pydantic models. This PR results in the following breaking changes: These will raise ValueErrors: ```python ChatPromptTemplate([("system", "{_private}")]).get_input_schema() ChatPromptTemplate([("system","{model_json_schema}")]).get_input_schema() ``` This PR should properly suppress warnings for the following cases: ```python ChatPromptTemplate([("system", "{schema}")]).get_input_schema() ChatPromptTemplate([("system","{model_id}")]).get_input_schema() ```
This commit is contained in:
@@ -864,3 +864,34 @@ async def test_chat_tmpl_serdes(snapshot: SnapshotAssertion) -> None:
|
||||
)
|
||||
assert dumpd(template) == snapshot()
|
||||
assert load(dumpd(template)) == template
|
||||
|
||||
|
||||
def test_chat_prompt_template_variable_names() -> None:
|
||||
"""This test was written for an edge case that triggers a warning from Pydantic.
|
||||
|
||||
Verify that no run time warnings are raised.
|
||||
"""
|
||||
with pytest.warns(None) as record: # type: ignore
|
||||
prompt = ChatPromptTemplate([("system", "{schema}")])
|
||||
prompt.get_input_schema()
|
||||
|
||||
if record:
|
||||
error_msg = []
|
||||
for warning in record:
|
||||
error_msg.append(
|
||||
f"Warning type: {warning.category.__name__}, "
|
||||
f"Warning message: {warning.message}, "
|
||||
f"Warning location: {warning.filename}:{warning.lineno}"
|
||||
)
|
||||
msg = "\n".join(error_msg)
|
||||
else:
|
||||
msg = ""
|
||||
|
||||
assert list(record) == [], msg
|
||||
|
||||
# Verify value errors raised from illegal names
|
||||
with pytest.raises(ValueError):
|
||||
ChatPromptTemplate([("system", "{_private}")]).get_input_schema()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
ChatPromptTemplate([("system", "{model_json_schema}")]).get_input_schema()
|
||||
|
@@ -35,3 +35,9 @@ EXPECTED_ALL = [
|
||||
|
||||
def test_all_imports() -> None:
|
||||
assert set(__all__) == set(EXPECTED_ALL)
|
||||
|
||||
|
||||
def test_imports_for_specific_funcs() -> None:
|
||||
"""Test that a few specific imports in more internal namespaces."""
|
||||
# create_model implementation has been moved to langchain_core.utils.pydantic
|
||||
from langchain_core.runnables.utils import create_model # noqa
|
||||
|
@@ -8,6 +8,7 @@ from pydantic import ConfigDict
|
||||
from langchain_core.utils.pydantic import (
|
||||
PYDANTIC_MAJOR_VERSION,
|
||||
_create_subset_model_v2,
|
||||
create_model_v2,
|
||||
get_fields,
|
||||
is_basemodel_instance,
|
||||
is_basemodel_subclass,
|
||||
@@ -194,3 +195,44 @@ def test_fields_pydantic_v1_from_2() -> None:
|
||||
|
||||
fields = get_fields(Foo)
|
||||
assert fields == {"x": Foo.__fields__["x"]}
|
||||
|
||||
|
||||
def test_create_model_v2() -> None:
|
||||
"""Test that create model v2 works as expected."""
|
||||
|
||||
with pytest.warns(None) as record: # type: ignore
|
||||
foo = create_model_v2("Foo", field_definitions={"a": (int, None)})
|
||||
foo.model_json_schema()
|
||||
|
||||
assert list(record) == []
|
||||
|
||||
# schema is used by pydantic, but OK to re-use
|
||||
with pytest.warns(None) as record: # type: ignore
|
||||
foo = create_model_v2("Foo", field_definitions={"schema": (int, None)})
|
||||
foo.model_json_schema()
|
||||
|
||||
assert list(record) == []
|
||||
|
||||
# From protected namespaces, but definitely OK to use.
|
||||
with pytest.warns(None) as record: # type: ignore
|
||||
foo = create_model_v2("Foo", field_definitions={"model_id": (int, None)})
|
||||
foo.model_json_schema()
|
||||
|
||||
assert list(record) == []
|
||||
|
||||
# Used by pydantic, not OK to re-use
|
||||
with pytest.raises(ValueError):
|
||||
create_model_v2("Foo", field_definitions={"model_json_schema": (int, None)})
|
||||
|
||||
# Private attributes raise an error for now since pydantic 2 considers them
|
||||
# to be private attributes.
|
||||
with pytest.raises(ValueError):
|
||||
create_model_v2("Foo", field_definitions={"_a": (int, None)})
|
||||
|
||||
with pytest.warns(None) as record: # type: ignore
|
||||
# Verify that we can use non-English characters
|
||||
field_name = "もしもし"
|
||||
foo = create_model_v2("Foo", field_definitions={field_name: (int, None)})
|
||||
foo.model_json_schema()
|
||||
|
||||
assert list(record) == []
|
||||
|
Reference in New Issue
Block a user