From fb676d8a9bbbceb23f78ce544263361a347af1c8 Mon Sep 17 00:00:00 2001 From: Leonid Ganeline Date: Mon, 15 Jan 2024 10:54:49 -0800 Subject: [PATCH] community[minor], langchain[minor]: refactor `output_parsers` Rail (#15852) Moved Rail parser to `community` package. --- .../output_parsers/__init__.py | 14 +++ .../output_parsers/rail_parser.py | 109 +++++++++++++++++ .../langchain/output_parsers/rail_parser.py | 112 +----------------- 3 files changed, 127 insertions(+), 108 deletions(-) create mode 100644 libs/community/langchain_community/output_parsers/__init__.py create mode 100644 libs/community/langchain_community/output_parsers/rail_parser.py diff --git a/libs/community/langchain_community/output_parsers/__init__.py b/libs/community/langchain_community/output_parsers/__init__.py new file mode 100644 index 00000000000..62740af5441 --- /dev/null +++ b/libs/community/langchain_community/output_parsers/__init__.py @@ -0,0 +1,14 @@ +"""**OutputParser** classes parse the output of an LLM call. + +**Class hierarchy:** + +.. code-block:: + + BaseLLMOutputParser --> BaseOutputParser --> OutputParser # GuardrailsOutputParser + +**Main helpers:** + +.. code-block:: + + Serializable, Generation, PromptValue +""" # noqa: E501 diff --git a/libs/community/langchain_community/output_parsers/rail_parser.py b/libs/community/langchain_community/output_parsers/rail_parser.py new file mode 100644 index 00000000000..f0cabc13eb5 --- /dev/null +++ b/libs/community/langchain_community/output_parsers/rail_parser.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +from typing import Any, Callable, Dict, Optional + +from langchain_core.output_parsers import BaseOutputParser + + +class GuardrailsOutputParser(BaseOutputParser): + """Parse the output of an LLM call using Guardrails.""" + + guard: Any + """The Guardrails object.""" + api: Optional[Callable] + """The LLM API passed to Guardrails during parsing. An example is `openai.completions.create`.""" # noqa: E501 + args: Any + """Positional arguments to pass to the above LLM API callable.""" + kwargs: Any + """Keyword arguments to pass to the above LLM API callable.""" + + @property + def _type(self) -> str: + return "guardrails" + + @classmethod + def from_rail( + cls, + rail_file: str, + num_reasks: int = 1, + api: Optional[Callable] = None, + *args: Any, + **kwargs: Any, + ) -> GuardrailsOutputParser: + """Create a GuardrailsOutputParser from a rail file. + + Args: + rail_file: a rail file. + num_reasks: number of times to re-ask the question. + api: the API to use for the Guardrails object. + *args: The arguments to pass to the API + **kwargs: The keyword arguments to pass to the API. + + Returns: + GuardrailsOutputParser + """ + try: + from guardrails import Guard + except ImportError: + raise ImportError( + "guardrails-ai package not installed. " + "Install it by running `pip install guardrails-ai`." + ) + return cls( + guard=Guard.from_rail(rail_file, num_reasks=num_reasks), + api=api, + args=args, + kwargs=kwargs, + ) + + @classmethod + def from_rail_string( + cls, + rail_str: str, + num_reasks: int = 1, + api: Optional[Callable] = None, + *args: Any, + **kwargs: Any, + ) -> GuardrailsOutputParser: + try: + from guardrails import Guard + except ImportError: + raise ImportError( + "guardrails-ai package not installed. " + "Install it by running `pip install guardrails-ai`." + ) + return cls( + guard=Guard.from_rail_string(rail_str, num_reasks=num_reasks), + api=api, + args=args, + kwargs=kwargs, + ) + + @classmethod + def from_pydantic( + cls, + output_class: Any, + num_reasks: int = 1, + api: Optional[Callable] = None, + *args: Any, + **kwargs: Any, + ) -> GuardrailsOutputParser: + try: + from guardrails import Guard + except ImportError: + raise ImportError( + "guardrails-ai package not installed. " + "Install it by running `pip install guardrails-ai`." + ) + return cls( + guard=Guard.from_pydantic(output_class, "", num_reasks=num_reasks), + api=api, + args=args, + kwargs=kwargs, + ) + + def get_format_instructions(self) -> str: + return self.guard.raw_prompt.format_instructions + + def parse(self, text: str) -> Dict: + return self.guard.parse(text, llm_api=self.api, *self.args, **self.kwargs) diff --git a/libs/langchain/langchain/output_parsers/rail_parser.py b/libs/langchain/langchain/output_parsers/rail_parser.py index f0cabc13eb5..3f796938be1 100644 --- a/libs/langchain/langchain/output_parsers/rail_parser.py +++ b/libs/langchain/langchain/output_parsers/rail_parser.py @@ -1,109 +1,5 @@ -from __future__ import annotations +from langchain_community.output_parsers.rail_parser import ( + GuardrailsOutputParser, +) -from typing import Any, Callable, Dict, Optional - -from langchain_core.output_parsers import BaseOutputParser - - -class GuardrailsOutputParser(BaseOutputParser): - """Parse the output of an LLM call using Guardrails.""" - - guard: Any - """The Guardrails object.""" - api: Optional[Callable] - """The LLM API passed to Guardrails during parsing. An example is `openai.completions.create`.""" # noqa: E501 - args: Any - """Positional arguments to pass to the above LLM API callable.""" - kwargs: Any - """Keyword arguments to pass to the above LLM API callable.""" - - @property - def _type(self) -> str: - return "guardrails" - - @classmethod - def from_rail( - cls, - rail_file: str, - num_reasks: int = 1, - api: Optional[Callable] = None, - *args: Any, - **kwargs: Any, - ) -> GuardrailsOutputParser: - """Create a GuardrailsOutputParser from a rail file. - - Args: - rail_file: a rail file. - num_reasks: number of times to re-ask the question. - api: the API to use for the Guardrails object. - *args: The arguments to pass to the API - **kwargs: The keyword arguments to pass to the API. - - Returns: - GuardrailsOutputParser - """ - try: - from guardrails import Guard - except ImportError: - raise ImportError( - "guardrails-ai package not installed. " - "Install it by running `pip install guardrails-ai`." - ) - return cls( - guard=Guard.from_rail(rail_file, num_reasks=num_reasks), - api=api, - args=args, - kwargs=kwargs, - ) - - @classmethod - def from_rail_string( - cls, - rail_str: str, - num_reasks: int = 1, - api: Optional[Callable] = None, - *args: Any, - **kwargs: Any, - ) -> GuardrailsOutputParser: - try: - from guardrails import Guard - except ImportError: - raise ImportError( - "guardrails-ai package not installed. " - "Install it by running `pip install guardrails-ai`." - ) - return cls( - guard=Guard.from_rail_string(rail_str, num_reasks=num_reasks), - api=api, - args=args, - kwargs=kwargs, - ) - - @classmethod - def from_pydantic( - cls, - output_class: Any, - num_reasks: int = 1, - api: Optional[Callable] = None, - *args: Any, - **kwargs: Any, - ) -> GuardrailsOutputParser: - try: - from guardrails import Guard - except ImportError: - raise ImportError( - "guardrails-ai package not installed. " - "Install it by running `pip install guardrails-ai`." - ) - return cls( - guard=Guard.from_pydantic(output_class, "", num_reasks=num_reasks), - api=api, - args=args, - kwargs=kwargs, - ) - - def get_format_instructions(self) -> str: - return self.guard.raw_prompt.format_instructions - - def parse(self, text: str) -> Dict: - return self.guard.parse(text, llm_api=self.api, *self.args, **self.kwargs) +__all__ = ["GuardrailsOutputParser"]