diff --git a/application/llm/google_ai.py b/application/llm/google_ai.py index ae888042..31943601 100644 --- a/application/llm/google_ai.py +++ b/application/llm/google_ai.py @@ -57,25 +57,35 @@ class GoogleLLM(BaseLLM): for tool_data in tools_list: if tool_data["type"] == "function": function = tool_data["function"] - genai_function = dict( - name=function["name"], - description=function["description"], - parameters={ - "type": "OBJECT", - "properties": { - k: { - **v, - "type": v["type"].upper() if v["type"] else None, - } - for k, v in function["parameters"]["properties"].items() + parameters = function["parameters"] + properties = parameters.get("properties", {}) + + if properties: + genai_function = dict( + name=function["name"], + description=function["description"], + parameters={ + "type": "OBJECT", + "properties": { + k: { + **v, + "type": v["type"].upper() if v["type"] else None, + } + for k, v in properties.items() + }, + "required": ( + parameters["required"] + if "required" in parameters + else [] + ), }, - "required": ( - function["parameters"]["required"] - if "required" in function["parameters"] - else [] - ), - }, - ) + ) + else: + genai_function = dict( + name=function["name"], + description=function["description"], + ) + genai_tool = types.Tool(function_declarations=[genai_function]) genai_tools.append(genai_tool) diff --git a/application/tools/agent.py b/application/tools/agent.py index 209184d2..740e1689 100644 --- a/application/tools/agent.py +++ b/application/tools/agent.py @@ -42,22 +42,26 @@ class Agent: if key != "filled_by_llm" and key != "value" } for k, v in action["parameters"]["properties"].items() - if v.get("filled_by_llm", False) + if v.get("filled_by_llm", True) }, "required": [ key for key in action["parameters"]["required"] if key in action["parameters"]["properties"] and action["parameters"]["properties"][key].get( - "filled_by_llm", False + "filled_by_llm", True ) ], }, }, } for tool_id, tool in tools_dict.items() - for action in tool["actions"] - if action["active"] + for action in ( + tool["config"]["actions"].values() + if tool["name"] == "api_tool" + else tool["actions"] + ) + if action.get("active", True) ] def _execute_tool_action(self, tools_dict, call): @@ -65,8 +69,14 @@ class Agent: tool_id, action_name, call_args = parser.parse_args(call) tool_data = tools_dict[tool_id] - action_data = next( - action for action in tool_data["actions"] if action["name"] == action_name + action_data = ( + tool_data["config"]["actions"][action_name] + if tool_data["name"] == "api_tool" + else next( + action + for action in tool_data["actions"] + if action["name"] == action_name + ) ) for param, details in action_data["parameters"]["properties"].items(): @@ -74,7 +84,14 @@ class Agent: call_args[param] = details["value"] tm = ToolManager(config={}) - tool = tm.load_tool(tool_data["name"], tool_config=tool_data["config"]) + tool = tm.load_tool( + tool_data["name"], + tool_config=( + tool_data["config"]["actions"][action_name] + if tool_data["name"] == "api_tool" + else tool_data["config"] + ), + ) print(f"Executing tool: {action_name} with args: {call_args}") result = tool.execute_action(action_name, **call_args) call_id = getattr(call, "id", None) diff --git a/application/tools/implementations/api_tool.py b/application/tools/implementations/api_tool.py new file mode 100644 index 00000000..da105e39 --- /dev/null +++ b/application/tools/implementations/api_tool.py @@ -0,0 +1,49 @@ +import json + +import requests +from application.tools.base import Tool + + +class APITool(Tool): + """ + API Tool + A flexible tool for performing various API actions (e.g., sending messages, retrieving data) via custom user-specified APIs + """ + + def __init__(self, config): + self.config = config + self.url = config.get("url", "") + self.method = config.get("method", "GET") + self.headers = config.get("headers", {"Content-Type": "application/json"}) + + def execute_action(self, action_name, **kwargs): + return self._make_api_call(self.url, self.method, self.headers, kwargs) + + def _make_api_call(self, url, method, headers, body): + if isinstance(body, dict): + body = json.dumps(body) + try: + print(f"Making API call: {method} {url} with body: {body}") + response = requests.request(method, url, headers=headers, data=body) + response.raise_for_status() + try: + data = response.json() + except ValueError: + data = None + + return { + "status_code": response.status_code, + "data": data, + "message": "API call successful.", + } + except requests.exceptions.RequestException as e: + return { + "status_code": response.status_code if response else None, + "message": f"API call failed: {str(e)}", + } + + def get_actions_metadata(self): + return [] + + def get_config_requirements(self): + return {} diff --git a/frontend/public/toolIcons/tool_api_tool.svg b/frontend/public/toolIcons/tool_api_tool.svg new file mode 100644 index 00000000..1e923cf3 --- /dev/null +++ b/frontend/public/toolIcons/tool_api_tool.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file