diff --git a/libs/core/langchain_core/output_parsers/json.py b/libs/core/langchain_core/output_parsers/json.py index d16316596a7..c107cd0c765 100644 --- a/libs/core/langchain_core/output_parsers/json.py +++ b/libs/core/langchain_core/output_parsers/json.py @@ -221,7 +221,8 @@ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]): if self.pydantic_object is None: return "Return a JSON object." else: - schema = self.pydantic_object.schema() + # Copy schema to avoid altering original Pydantic schema. + schema = {k: v for k, v in self.pydantic_object.schema().items()} # Remove extraneous fields. reduced_schema = schema diff --git a/libs/core/tests/unit_tests/output_parsers/test_json.py b/libs/core/tests/unit_tests/output_parsers/test_json.py index 6d8cb4bee39..8cedc767699 100644 --- a/libs/core/tests/unit_tests/output_parsers/test_json.py +++ b/libs/core/tests/unit_tests/output_parsers/test_json.py @@ -8,6 +8,8 @@ from langchain_core.output_parsers.json import ( parse_json_markdown, parse_partial_json, ) +from langchain_core.pydantic_v1 import BaseModel +from langchain_core.utils.function_calling import convert_to_openai_function GOOD_JSON = """```json { @@ -579,3 +581,17 @@ def test_partial_text_json_output_parser_with_json_code_block() -> None: {"country_name": "France", "population_size": 673915}, {"country_name": "France", "population_size": 67391582}, ] + + +def test_base_model_schema_consistency() -> None: + class Joke(BaseModel): + setup: str + punchline: str + + initial_joke_schema = {k: v for k, v in Joke.schema().items()} + SimpleJsonOutputParser(pydantic_object=Joke) + openai_func = convert_to_openai_function(Joke) + retrieved_joke_schema = {k: v for k, v in Joke.schema().items()} + + assert initial_joke_schema == retrieved_joke_schema + assert openai_func.get("name", None) is not None diff --git a/libs/langchain/langchain/output_parsers/pydantic.py b/libs/langchain/langchain/output_parsers/pydantic.py index 1248560c0ca..9e415650425 100644 --- a/libs/langchain/langchain/output_parsers/pydantic.py +++ b/libs/langchain/langchain/output_parsers/pydantic.py @@ -29,7 +29,8 @@ class PydanticOutputParser(JsonOutputParser): raise OutputParserException(msg, llm_output=json_object) def get_format_instructions(self) -> str: - schema = self.pydantic_object.schema() + # Copy schema to avoid altering original Pydantic schema. + schema = {k: v for k, v in self.pydantic_object.schema().items()} # Remove extraneous fields. reduced_schema = schema diff --git a/libs/langchain/langchain/output_parsers/yaml.py b/libs/langchain/langchain/output_parsers/yaml.py index 528fc93f507..21bcf359a2c 100644 --- a/libs/langchain/langchain/output_parsers/yaml.py +++ b/libs/langchain/langchain/output_parsers/yaml.py @@ -43,7 +43,8 @@ class YamlOutputParser(BaseOutputParser[T]): raise OutputParserException(msg, llm_output=text) from e def get_format_instructions(self) -> str: - schema = self.pydantic_object.schema() + # Copy schema to avoid altering original Pydantic schema. + schema = {k: v for k, v in self.pydantic_object.schema().items()} # Remove extraneous fields. reduced_schema = schema