|
import json |
|
import re |
|
from typing import Pattern, Union |
|
|
|
from langchain_core.agents import AgentAction, AgentFinish |
|
from langchain_core.exceptions import OutputParserException |
|
|
|
from langchain.agents.agent import AgentOutputParser |
|
from langchain.agents.chat.prompt import FORMAT_INSTRUCTIONS |
|
|
|
FINAL_ANSWER_ACTION = "Final Answer:" |
|
|
|
|
|
class ChatOutputParser(AgentOutputParser): |
|
"""Output parser for the chat agent.""" |
|
|
|
format_instructions: str = FORMAT_INSTRUCTIONS |
|
"""Default formatting instructions""" |
|
|
|
pattern: Pattern = re.compile(r"^.*?`{3}(?:json)?\n(.*?)`{3}.*?$", re.DOTALL) |
|
"""Regex pattern to parse the output.""" |
|
|
|
def get_format_instructions(self) -> str: |
|
"""Returns formatting instructions for the given output parser.""" |
|
return self.format_instructions |
|
|
|
def parse(self, text: str) -> Union[AgentAction, AgentFinish]: |
|
"""Parse the output from the agent into |
|
an AgentAction or AgentFinish object. |
|
|
|
Args: |
|
text: The text to parse. |
|
|
|
Returns: |
|
An AgentAction or AgentFinish object. |
|
|
|
Raises: |
|
OutputParserException: If the output could not be parsed. |
|
ValueError: If the action could not be found. |
|
""" |
|
|
|
includes_answer = FINAL_ANSWER_ACTION in text |
|
try: |
|
found = self.pattern.search(text) |
|
if not found: |
|
|
|
raise ValueError("action not found") |
|
action = found.group(1) |
|
response = json.loads(action.strip()) |
|
includes_action = "action" in response |
|
if includes_answer and includes_action: |
|
raise OutputParserException( |
|
"Parsing LLM output produced a final answer " |
|
f"and a parse-able action: {text}" |
|
) |
|
return AgentAction( |
|
response["action"], response.get("action_input", {}), text |
|
) |
|
|
|
except Exception as exc: |
|
if not includes_answer: |
|
raise OutputParserException( |
|
f"Could not parse LLM output: {text}" |
|
) from exc |
|
output = text.split(FINAL_ANSWER_ACTION)[-1].strip() |
|
return AgentFinish({"output": output}, text) |
|
|
|
@property |
|
def _type(self) -> str: |
|
return "chat" |
|
|