Spaces:
Runtime error
Runtime error
import json | |
from typing import ( | |
Any, | |
Dict, | |
List, | |
Union, | |
) | |
from langchain_core._api import deprecated | |
from langchain_core.pydantic_v1 import Field | |
from langchain_anthropic.chat_models import ChatAnthropic | |
SYSTEM_PROMPT_FORMAT = """In this environment you have access to a set of tools you can use to answer the user's question. | |
You may call them like this: | |
<function_calls> | |
<invoke> | |
<tool_name>$TOOL_NAME</tool_name> | |
<parameters> | |
<$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME> | |
... | |
</parameters> | |
</invoke> | |
</function_calls> | |
Here are the tools available: | |
<tools> | |
{formatted_tools} | |
</tools>""" # noqa: E501 | |
TOOL_FORMAT = """<tool_description> | |
<tool_name>{tool_name}</tool_name> | |
<description>{tool_description}</description> | |
<parameters> | |
{formatted_parameters} | |
</parameters> | |
</tool_description>""" | |
TOOL_PARAMETER_FORMAT = """<parameter> | |
<name>{parameter_name}</name> | |
<type>{parameter_type}</type> | |
<description>{parameter_description}</description> | |
</parameter>""" | |
def _get_type(parameter: Dict[str, Any]) -> str: | |
if "type" in parameter: | |
return parameter["type"] | |
if "anyOf" in parameter: | |
return json.dumps({"anyOf": parameter["anyOf"]}) | |
if "allOf" in parameter: | |
return json.dumps({"allOf": parameter["allOf"]}) | |
return json.dumps(parameter) | |
def get_system_message(tools: List[Dict]) -> str: | |
tools_data: List[Dict] = [ | |
{ | |
"tool_name": tool["name"], | |
"tool_description": tool["description"], | |
"formatted_parameters": "\n".join( | |
[ | |
TOOL_PARAMETER_FORMAT.format( | |
parameter_name=name, | |
parameter_type=_get_type(parameter), | |
parameter_description=parameter.get("description"), | |
) | |
for name, parameter in tool["parameters"]["properties"].items() | |
] | |
), | |
} | |
for tool in tools | |
] | |
tools_formatted = "\n".join( | |
[ | |
TOOL_FORMAT.format( | |
tool_name=tool["tool_name"], | |
tool_description=tool["tool_description"], | |
formatted_parameters=tool["formatted_parameters"], | |
) | |
for tool in tools_data | |
] | |
) | |
return SYSTEM_PROMPT_FORMAT.format(formatted_tools=tools_formatted) | |
def _xml_to_dict(t: Any) -> Union[str, Dict[str, Any]]: | |
# Base case: If the element has no children, return its text or an empty string. | |
if len(t) == 0: | |
return t.text or "" | |
# Recursive case: The element has children. Convert them into a dictionary. | |
d: Dict[str, Any] = {} | |
for child in t: | |
if child.tag not in d: | |
d[child.tag] = _xml_to_dict(child) | |
else: | |
# Handle multiple children with the same tag | |
if not isinstance(d[child.tag], list): | |
d[child.tag] = [d[child.tag]] # Convert existing entry into a list | |
d[child.tag].append(_xml_to_dict(child)) | |
return d | |
def _xml_to_function_call(invoke: Any, tools: List[Dict]) -> Dict[str, Any]: | |
name = invoke.find("tool_name").text | |
arguments = _xml_to_dict(invoke.find("parameters")) | |
# make list elements in arguments actually lists | |
filtered_tools = [tool for tool in tools if tool["name"] == name] | |
if len(filtered_tools) > 0 and not isinstance(arguments, str): | |
tool = filtered_tools[0] | |
for key, value in arguments.items(): | |
if key in tool["parameters"]["properties"]: | |
if "type" in tool["parameters"]["properties"][key]: | |
if tool["parameters"]["properties"][key][ | |
"type" | |
] == "array" and not isinstance(value, list): | |
arguments[key] = [value] | |
if ( | |
tool["parameters"]["properties"][key]["type"] != "object" | |
and isinstance(value, dict) | |
and len(value.keys()) == 1 | |
): | |
arguments[key] = list(value.values())[0] | |
return { | |
"function": { | |
"name": name, | |
"arguments": json.dumps(arguments), | |
}, | |
"type": "function", | |
} | |
def _xml_to_tool_calls(elem: Any, tools: List[Dict]) -> List[Dict[str, Any]]: | |
""" | |
Convert an XML element and its children into a dictionary of dictionaries. | |
""" | |
invokes = elem.findall("invoke") | |
return [_xml_to_function_call(invoke, tools) for invoke in invokes] | |
class ChatAnthropicTools(ChatAnthropic): | |
"""Chat model for interacting with Anthropic functions.""" | |
_xmllib: Any = Field(default=None) | |