Spaces:
Paused
Paused
import re | |
from typing import Union | |
from langchain.agents.agent import AgentOutputParser | |
from langchain.agents.mrkl.output_parser import MRKLOutputParser | |
#from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS | |
from langchain.schema import AgentAction, AgentFinish, OutputParserException | |
FORMAT_INSTRUCTIONS0 = """Use the following format and be sure to use new lines after each task. | |
Question: the input question you must answer | |
Thought: you should always think about what to do | |
Action: Exactly only one word out of: {tool_names} | |
Action Input: the input to the action | |
Observation: the result of the action | |
(this Thought/Action/Action Input/Observation can repeat N times) | |
Thought: I now know the final answer | |
Final Answer: the final answer to the original input question""" | |
FORMAT_INSTRUCTIONS = """List of tools, use exactly one word when choosing Action: {tool_names} | |
Here is an example sequence to follow: | |
Question: What is the latest news? | |
Thought: I should search online for the latest news. | |
Action: Search | |
Action Input: What is the latest news? | |
Observation: X is going away. Z is again happening. | |
Thought: That is interesting, I should search for more information about X and Z and also search about Q. | |
Action: Search | |
Action Input: How is X impacting things. Why is Z happening again, and what are the consequences? | |
Observation: X is causing Y. Z may be caused by P and will lead to H. | |
Thought: I now know the final answer | |
Final Answer: The latest news is: | |
* X is going away, and this is caused by Y. | |
* Z is happening again, and the cause is P and will lead to H. | |
Overall, X and Z are important problems. | |
""" | |
FINAL_ANSWER_ACTION = "Final Answer:" | |
MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE = ( | |
"Invalid Format: Missing 'Action:' after 'Thought:" | |
) | |
MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE = ( | |
"Invalid Format: Missing 'Action Input:' after 'Action:'" | |
) | |
FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE = ( | |
"Parsing LLM output produced both a final answer and a parse-able action:" | |
) | |
class H2OMRKLOutputParser(MRKLOutputParser): | |
"""MRKL Output parser for the chat agent.""" | |
def get_format_instructions(self) -> str: | |
return FORMAT_INSTRUCTIONS | |
def parse(self, text: str) -> Union[AgentAction, AgentFinish]: | |
includes_answer = FINAL_ANSWER_ACTION in text | |
regex = ( | |
r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)" | |
) | |
action_match = re.search(regex, text, re.DOTALL) | |
if includes_answer: | |
return AgentFinish( | |
{"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()}, text | |
) | |
elif action_match: | |
action = action_match.group(1).strip() | |
action_input = action_match.group(2) | |
tool_input = action_input.strip(" ") | |
# ensure if its a well formed SQL query we don't remove any trailing " chars | |
if tool_input.startswith("SELECT ") is False: | |
tool_input = tool_input.strip('"') | |
return AgentAction(action, tool_input, text) | |
if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL): | |
raise OutputParserException( | |
f"Could not parse LLM output: `{text}`", | |
observation=MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE, | |
llm_output=text, | |
send_to_llm=True, | |
) | |
elif not re.search( | |
r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)", text, re.DOTALL | |
): | |
raise OutputParserException( | |
f"Could not parse LLM output: `{text}`", | |
observation=MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE, | |
llm_output=text, | |
send_to_llm=True, | |
) | |
else: | |
raise OutputParserException(f"Could not parse LLM output: `{text}`") | |
def _type(self) -> str: | |
return "mrkl" | |