langchain.core : Use shallow copy for schema manipulation in JsonOutputParser.get_format_instructions (#17162)

- **Description :**  

Fix: Use shallow copy for schema manipulation in get_format_instructions

Prevents side effects on the original schema object by using a
dictionary comprehension for a safer and more controlled manipulation of
schema key-value pairs, enhancing code reliability.

  - **Issue:**  #17161 
  - **Dependencies:** None
  -  **Twitter handle:** None
pull/17488/head
JongRok BAEK 4 months ago committed by GitHub
parent 90f55e6bd1
commit 8d6cc90fc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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

@ -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

@ -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

@ -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

Loading…
Cancel
Save