Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion langchain/chains/hyde/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def combine_embeddings(self, embeddings: List[List[float]]) -> List[float]:
def embed_query(self, text: str) -> List[float]:
"""Generate a hypothetical document and embedded it."""
var_name = self.llm_chain.input_keys[0]
result = self.llm_chain.generate([{var_name: text}])
result, _ = self.llm_chain.generate([{var_name: text}])
documents = [generation.text for generation in result.generations[0]]
embeddings = self.embed_documents(documents)
return self.combine_embeddings(embeddings)
Expand Down
58 changes: 44 additions & 14 deletions langchain/chains/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@

from typing import Any, Dict, List, Optional, Sequence, Tuple, Union

from pydantic import BaseModel, Extra
from pydantic import BaseModel, Extra, Field

from langchain.chains.base import Chain
from langchain.input import get_colored_text
from langchain.output_parsers.base import OutputGuardrail
from langchain.prompts.base import BasePromptTemplate
from langchain.prompts.prompt import PromptTemplate
from langchain.schema import BaseLanguageModel, LLMResult, PromptValue
from langchain.schema import (
BaseLanguageModel,
Guardrail,
LLMResult,
PromptValue,
ValidationError,
)


class LLMChain(Chain, BaseModel):
Expand All @@ -30,6 +37,8 @@ class LLMChain(Chain, BaseModel):
"""Prompt object to use."""
llm: BaseLanguageModel
output_key: str = "text" #: :meta private:
output_parser: Optional[OutputGuardrail] = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Dead field — output_parser is never read

output_parser: Optional[OutputGuardrail] = None is declared on LLMChain but is never consulted in _get_final_output, apply, or any other method. A user who sets this field expecting it to be applied will see it silently ignored. Either wire it into _get_final_output (e.g., prepend it to the guardrails loop) or remove the field.

guardrails: List[Guardrail] = Field(default_factory=list)

class Config:
"""Configuration for this pydantic object."""
Expand All @@ -56,15 +65,19 @@ def output_keys(self) -> List[str]:
def _call(self, inputs: Dict[str, Any]) -> Dict[str, str]:
return self.apply([inputs])[0]

def generate(self, input_list: List[Dict[str, Any]]) -> LLMResult:
def generate(
self, input_list: List[Dict[str, Any]]
) -> Tuple[LLMResult, List[PromptValue]]:
"""Generate LLM result from inputs."""
prompts, stop = self.prep_prompts(input_list)
return self.llm.generate_prompt(prompts, stop)
return self.llm.generate_prompt(prompts, stop), prompts

async def agenerate(self, input_list: List[Dict[str, Any]]) -> LLMResult:
async def agenerate(
self, input_list: List[Dict[str, Any]]
) -> Tuple[LLMResult, List[PromptValue]]:
"""Generate LLM result from inputs."""
prompts, stop = await self.aprep_prompts(input_list)
return await self.llm.agenerate_prompt(prompts, stop)
return await self.llm.agenerate_prompt(prompts, stop), prompts

def prep_prompts(
self, input_list: List[Dict[str, Any]]
Expand Down Expand Up @@ -115,20 +128,37 @@ async def aprep_prompts(

def apply(self, input_list: List[Dict[str, Any]]) -> List[Dict[str, str]]:
"""Utilize the LLM generate method for speed gains."""
response = self.generate(input_list)
return self.create_outputs(response)
response, prompts = self.generate(input_list)
return self.create_outputs(response, prompts)

async def aapply(self, input_list: List[Dict[str, Any]]) -> List[Dict[str, str]]:
"""Utilize the LLM generate method for speed gains."""
response = await self.agenerate(input_list)
return self.create_outputs(response)

def create_outputs(self, response: LLMResult) -> List[Dict[str, str]]:
response, prompts = await self.agenerate(input_list)
return self.create_outputs(response, prompts)

def _get_final_output(self, text: str, prompt_value: PromptValue) -> Any:
result: Any = text
for guardrail in self.guardrails:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

For a chain constructed with output_parser=SomeParser() but no guardrails list, a trigger like model output 'not-json' is no longer parsed at all because create_outputs only consults self.guardrails and ignores the new output_parser field, breaking callers that expect parsed outputs after this refactor.

Also reported at: langchain/chains/llm.py L40–L41

Preserve previous/new contract by automatically running self.output_parser when set, or wrap it into guardrails during initialization so create_outputs always applies it.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 141-141
Issue Type: functional-high
Severity: high

Issue Description:
For a chain constructed with output_parser=SomeParser() but no guardrails list, a trigger like model output 'not-json' is no longer parsed at all because create_outputs only consults self.guardrails and ignores the new output_parser field, breaking callers that expect parsed outputs after this refactor.

_Also reported at: `langchain/chains/llm.py` L40–L41_

Current Code:
for guardrail in self.guardrails:

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

if isinstance(guardrail, OutputGuardrail):
try:
result = guardrail.output_parser.parse(result)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

When any parser or guardrail raises, _get_final_output constructs ValidationError(text=e) but langchain/schema.py now defines ValidationError.error_message, so a malformed output such as non-JSON text under an OutputGuardrail turns a recoverable validation failure into a pydantic initialization exception.

Instantiate the new schema correctly in both call sites, e.g. ValidationError(error_message=str(e)), and update any guardrail implementations to populate/read error_message.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 144-144
Issue Type: functional-high
Severity: high

Issue Description:
When any parser or guardrail raises, _get_final_output constructs ValidationError(text=e) but langchain/schema.py now defines ValidationError.error_message, so a malformed output such as non-JSON text under an OutputGuardrail turns a recoverable validation failure into a pydantic initialization exception.

Current Code:
                try:
                    result = guardrail.output_parser.parse(result)
                    error = None
                except Exception as e:
                    error = ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional Critical

If any guardrail parser/fixer raises (e.g. invalid output triggers OutputGuardrail on '{'), _get_final_output constructs ValidationError(text=e) but schema.ValidationError now requires error_message, so the guardrail path crashes instead of returning a fixed value.

Instantiate ValidationError with the declared field, e.g. ValidationError(error_message=str(e)), and make OutputGuardrail.check do the same.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 144-144
Issue Type: functional-critical
Severity: critical

Issue Description:
If any guardrail parser/fixer raises (e.g. invalid output triggers OutputGuardrail on '{'), _get_final_output constructs ValidationError(text=e) but schema.ValidationError now requires error_message, so the guardrail path crashes instead of returning a fixed value.

Current Code:
                try:
                    result = guardrail.output_parser.parse(result)
                    error = None
                except Exception as e:
                    error = ValidationError(text=e)
            else:
                error = guardrail.check(prompt_value, result)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

error = None
except Exception as e:
error = ValidationError(text=e)
Comment on lines +146 to +147

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The exception e is an Exception object, but ValidationError.text (or error_message as currently defined) is typed as str. Passing the raw exception will fail Pydantic's type validation. It should be str(e).

Suggested change
except Exception as e:
error = ValidationError(text=e)
except Exception as e:
error = ValidationError(text=str(e))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

Any invalid model output that triggers an OutputGuardrail parse/check failure now crashes in create_outputs because both llm.py and output_parsers/base.py instantiate ValidationError with text=..., but schema.py changed ValidationError to require error_message; e.g. a parser rejecting the literal output not json raises a Pydantic validation error instead of invoking the fixer.

Also reported at: langchain/chains/llm.py L151

Construct ValidationError with the new field name everywhere, e.g. ValidationError(error_message=str(e)), and likewise update output_parsers/base.py.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 147-147
Issue Type: functional-high
Severity: high

Issue Description:
Any invalid model output that triggers an OutputGuardrail parse/check failure now crashes in create_outputs because both llm.py and output_parsers/base.py instantiate ValidationError with `text=...`, but schema.py changed ValidationError to require `error_message`; e.g. a parser rejecting the literal output `not json` raises a Pydantic validation error instead of invoking the fixer.

_Also reported at: `langchain/chains/llm.py` L151_

Current Code:
                    error = ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Comment on lines +143 to +147

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness High

The broad exception handler hides parser and programmer errors; catch the parser's validation exception explicitly and let unexpected exceptions propagate.

Suggested fix
                try:
                    result = guardrail.output_parser.parse(result)
                    error = None
                except ValidationError as e:
                    error = e
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 143-147
Issue Type: robustness-high
Severity: high

Issue Description:
The broad exception handler hides parser and programmer errors; catch the parser's validation exception explicitly and let unexpected exceptions propagate.

Current Code:
                try:
                    result = guardrail.output_parser.parse(result)
                    error = None
                except Exception as e:
                    error = ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

The ValidationError is being constructed with an incorrect keyword argument text=e when it should use error_message=str(e). The field defined in schema.py is error_message: str, but the code passes text as the keyword argument. Additionally, e is an Exception instance, not a string, so it needs to be converted using str(e) to match the expected str type.

Suggested change
error = ValidationError(text=e)
error = ValidationError(error_message=str(e))
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert bash developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 147-147
Issue Type: functional-high
Severity: high

Issue Description:
The `ValidationError` is being constructed with an incorrect keyword argument `text=e` when it should use `error_message=str(e)`. The field defined in `schema.py` is `error_message: str`, but the code passes `text` as the keyword argument. Additionally, `e` is an `Exception` instance, not a string, so it needs to be converted using `str(e)` to match the expected `str` type.

Current Code:
                    error = ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

else:
error = guardrail.check(prompt_value, result)
if error is not None:
result = guardrail.fix(prompt_value, result, error)
return result
Comment on lines +139 to +152

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 OutputGuardrail.check() bypassed for OutputGuardrail instances

When iterating self.guardrails, the code special-cases OutputGuardrail by calling guardrail.output_parser.parse(result) directly — duplicating the logic already encapsulated in OutputGuardrail.check(). Non-OutputGuardrail items go through guardrail.check(). This asymmetry means any future changes to OutputGuardrail.check won't be picked up here. The branch should call guardrail.check() uniformly for all guardrail types.


def create_outputs(
self, response: LLMResult, prompts: List[PromptValue]
) -> List[Dict[str, str]]:
"""Create outputs from response."""
return [
# Get the text of the top generated string.
{self.output_key: generation[0].text}
for generation in response.generations
{self.output_key: self._get_final_output(generation[0].text, prompts[i])}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional High

When an LLMChain is configured with an OutputGuardrail and the model returns invalid JSON like '{', create_outputs now stores the parsed/fixed object instead of the raw text, but cross-file callers such as QA generation still read res[0].text from generate() and therefore silently bypass guardrails/fixes on that trigger.

Either apply guardrails inside generate()/agenerate() so callers consuming LLMResult see the fixed output too, or update all generate() callers to use apply()/create_outputs() instead of reading generation.text directly.

Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/chains/llm.py
Lines: 160-160
Issue Type: functional-high
Severity: high

Issue Description:
When an LLMChain is configured with an OutputGuardrail and the model returns invalid JSON like '{', create_outputs now stores the parsed/fixed object instead of the raw text, but cross-file callers such as QA generation still read res[0].text from generate() and therefore silently bypass guardrails/fixes on that trigger.

Current Code:
{self.output_key: self._get_final_output(generation[0].text, prompts[i])}

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

for i, generation in enumerate(response.generations)
]

async def _acall(self, inputs: Dict[str, Any]) -> Dict[str, str]:
Expand Down
2 changes: 1 addition & 1 deletion langchain/chains/qa_generation/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def output_keys(self) -> List[str]:

def _call(self, inputs: Dict[str, str]) -> Dict[str, Any]:
docs = self.text_splitter.create_documents([inputs[self.input_key]])
results = self.llm_chain.generate([{"text": d.page_content} for d in docs])
results, _ = self.llm_chain.generate([{"text": d.page_content} for d in docs])
qa = [json.loads(res[0].text) for res in results.generations]
return {self.output_key: qa}

Expand Down
23 changes: 22 additions & 1 deletion langchain/output_parsers/base.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, Dict
from typing import Any, Dict, Optional

from pydantic import BaseModel

from langchain.schema import Fixer, Guardrail, PromptValue, ValidationError


class BaseOutputParser(BaseModel, ABC):
"""Class to parse the output of an LLM call."""
Expand All @@ -26,3 +28,22 @@ def dict(self, **kwargs: Any) -> Dict:
output_parser_dict = super().dict()
output_parser_dict["_type"] = self._type
return output_parser_dict


class OutputGuardrail(Guardrail, BaseModel):
output_parser: BaseOutputParser
fixer: Fixer

def check(
self, prompt_value: PromptValue, result: Any
) -> Optional[ValidationError]:
try:
self.output_parser.parse(result)
return None
except Exception as e:
return ValidationError(text=e)
Comment on lines +40 to +44

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robustness Medium

Catching Exception here hides all parser and runtime errors; catch the parser-specific exception types you expect and let unexpected failures propagate.

Suggested fix
        try:
            self.output_parser.parse(result)
            return None
        except (ValueError, TypeError) as e:
            return ValidationError(text=str(e))
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/output_parsers/base.py
Lines: 40-44
Issue Type: robustness-medium
Severity: medium

Issue Description:
Catching Exception here hides all parser and runtime errors; catch the parser-specific exception types you expect and let unexpected failures propagate.

Current Code:
        try:
            self.output_parser.parse(result)
            return None
        except Exception as e:
            return ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Comment on lines +43 to +44

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional Medium

The exception object is passed directly into ValidationError.text, so convert it to a string before storing it.

Suggested fix
        except (ValueError, TypeError) as e:
            return ValidationError(text=str(e))
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert python developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/output_parsers/base.py
Lines: 43-44
Issue Type: functional-medium
Severity: medium

Issue Description:
The exception object is passed directly into ValidationError.text, so convert it to a string before storing it.

Current Code:
        except Exception as e:
            return ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow python best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue Jira

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional Critical

ValidationError is constructed with text=e but the field is named error_message and expects a str, not an Exception. The code should pass the exception message as a string to the correct field name.

Suggested change
return ValidationError(text=e)
return ValidationError(error_message=str(e))
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert bash developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/output_parsers/base.py
Lines: 44-44
Issue Type: functional-critical
Severity: critical

Issue Description:
ValidationError is constructed with `text=e` but the field is named `error_message` and expects a `str`, not an `Exception`. The code should pass the exception message as a string to the correct field name.

Current Code:
            return ValidationError(text=e)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue


def fix(
self, prompt_value: PromptValue, result: Any, error: ValidationError
) -> Any:
return self.fixer(prompt_value, result, error)
Comment on lines +37 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Fixer is an abstract class with a fix method, not a callable object. Calling self.fixer(prompt_value, result, error) will raise TypeError: 'Fixer' object is not callable at runtime. The correct call is self.fixer.fix(...). Additionally, the exception passed to ValidationError should be str(e) since the field is typed as str.

Suggested change
def check(
self, prompt_value: PromptValue, result: Any
) -> Optional[ValidationError]:
try:
self.output_parser.parse(result)
return None
except Exception as e:
return ValidationError(text=e)
def fix(
self, prompt_value: PromptValue, result: Any, error: ValidationError
) -> Any:
return self.fixer(prompt_value, result, error)
def check(
self, prompt_value: PromptValue, result: Any
) -> Optional[ValidationError]:
try:
self.output_parser.parse(result)
return None
except Exception as e:
return ValidationError(text=str(e))
def fix(
self, prompt_value: PromptValue, result: Any, error: ValidationError
) -> Any:
return self.fixer.fix(prompt_value, result, error)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional Critical

The OutputGuardrail.fix method incorrectly invokes self.fixer as a callable using self.fixer(...), but self.fixer is typed as Fixer, an abstract base class that only defines a fix(prompt_value, result, error) method and does not implement __call__. This causes a TypeError: 'Fixer' object is not callable at runtime. The correct invocation should call the fix method directly.

Suggested change
return self.fixer(prompt_value, result, error)
return self.fixer.fix(prompt_value, result, error)
Prompt for AI assistance

Copy the prompt below and paste it into ChatGPT, Claude, or any LLM:

You are an expert bash developer with deep knowledge of security, performance, and best practices.

### Context

File: langchain/output_parsers/base.py
Lines: 49-49
Issue Type: functional-critical
Severity: critical

Issue Description:
The `OutputGuardrail.fix` method incorrectly invokes `self.fixer` as a callable using `self.fixer(...)`, but `self.fixer` is typed as `Fixer`, an abstract base class that only defines a `fix(prompt_value, result, error)` method and does not implement `__call__`. This causes a `TypeError: 'Fixer' object is not callable` at runtime. The correct invocation should call the `fix` method directly.

Current Code:
        return self.fixer(prompt_value, result, error)

---

### Instructions

1. Fix the issue described above
2. Maintain the exact indentation and code style from the original
3. Follow bash best practices and language-specific idioms
4. Ensure the fix addresses the root cause, not just the symptoms
5. Add brief inline comments explaining the fix if needed

### Constraints

- Do not change functionality beyond fixing the identified issue
- Preserve existing variable names and function signatures unless they are part of the problem
- Ensure the fix is production-ready

---


Like Dislike Create Issue

26 changes: 26 additions & 0 deletions langchain/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,29 @@ def clear(self) -> None:


Memory = BaseMemory


class ValidationError(BaseModel):
error_message: str
Comment on lines +225 to +226

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 The ValidationError model defines its field as error_message, but every call site in this PR passes text=e — e.g., ValidationError(text=e) in both llm.py and output_parsers/base.py. Pydantic will raise a ValidationError (its own!) on any code path that triggers guardrail error handling, making the entire guardrails feature broken at runtime. The field must be renamed to text to match the call sites, and the exception must be coerced to str.

Suggested change
class ValidationError(BaseModel):
error_message: str
class ValidationError(BaseModel):
text: str

Comment on lines +225 to +226

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Name collision with pydantic.ValidationError

Defining a class named ValidationError in langchain.schema shadows Pydantic's own pydantic.ValidationError. Since from langchain.schema import ValidationError is used in llm.py and output_parsers/base.py, any except pydantic.ValidationError clauses in those files (or callers) may inadvertently catch the wrong class. Consider a more specific name such as GuardrailValidationError.



class Guardrail(ABC):
@abstractmethod
def check(
self, prompt_value: PromptValue, result: Any
) -> Optional[ValidationError]:
"""Check whether there's a validation error."""

@abstractmethod
def fix(
self, prompt_value: PromptValue, result: Any, error: ValidationError
) -> Any:
""""""


class Fixer(ABC):
@abstractmethod
def fix(
self, prompt_value: PromptValue, result: Any, error: ValidationError
) -> Any:
""""""