Spaces:
Sleeping
Sleeping
import re | |
from json import JSONDecodeError | |
from typing import List, Union | |
from langchain_core.agents import AgentAction, AgentActionMessageLog, AgentFinish | |
from langchain_core.exceptions import OutputParserException | |
from langchain_core.messages import ( | |
AIMessage, | |
BaseMessage, | |
) | |
from langchain_core.outputs import ChatGeneration, Generation | |
from langchain.agents.agent import AgentOutputParser | |
from agents.output_parsers.utils import parse_tool_call, check_tool_call | |
import ast | |
class FunctionsAgentOutputParser(AgentOutputParser): | |
"""Parses a message into agent action/finish. | |
Is meant to be used with a model with Nous Hermes 2 Pro as the base, as it relies on the specific | |
function_call parameter from Nous Research to convey what tools to use. | |
If a function_call parameter is passed, then that is used to get | |
the tool and tool input. | |
If one is not passed, then the AIMessage is assumed to be the final output. | |
It was add a | |
""" | |
def _type(self) -> str: | |
return "functions-agent" | |
def _parse_ai_message(message: BaseMessage): | |
"""Parse an AI message.""" | |
if not isinstance(message, AIMessage): | |
raise TypeError(f"Expected an AI message got {type(message)}") | |
actions = [] | |
pattern = re.compile(r"<tool_call>(.*?)</tool_call>", re.DOTALL) | |
try: | |
tool_calls = [parse_tool_call(t.strip()) for t in pattern.findall(message.content)] | |
except: | |
raise OutputParserException( | |
f"Could not parse tool calls from message content: {message.content}. Please ensure that the tool calls are valid JSON." | |
) | |
if not tool_calls: | |
return AgentFinish( | |
return_values={"output": message.content}, log=str(message.content) | |
) | |
for tool_call in tool_calls: | |
tool_name, tool_input = check_tool_call(tool_call) | |
content_msg = f"\n{message.content}\n" if message.content else "\n" | |
log = f"\nInvoking: `{tool_name}` with `{tool_input}`\n{content_msg}\n" | |
actions.append(AgentActionMessageLog( | |
tool=tool_name, | |
tool_input=tool_input, | |
log=log, | |
message_log=[message], | |
)) | |
return actions | |
def parse_result( | |
self, result: List[Generation], *, partial: bool = False | |
) -> Union[AgentAction, AgentFinish]: | |
if not isinstance(result[0], ChatGeneration): | |
raise ValueError("This output parser only works on ChatGeneration output") | |
message = result[0].message | |
return self._parse_ai_message(message) | |
def parse(self, text: str) -> Union[AgentAction, AgentFinish]: | |
raise ValueError("Can only parse messages") |