From 6c608a73bad500b2eaec7eda14a12f08a6a0a29b Mon Sep 17 00:00:00 2001 From: Steven Su Date: Sun, 10 Mar 2024 11:07:52 +0800 Subject: [PATCH 1/2] Add Amazon Bedrock Claude3 Sonnet support Signed-off-by: Steven Su --- requirements.txt | 4 ++-- tool_use_package/tool_user.py | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/requirements.txt b/requirements.txt index 81a5e3b..741a952 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ aiohttp==3.8.6 aiosignal==1.3.1 annotated-types==0.6.0 -anthropic==0.16.0 -anthropic-bedrock==0.8.0 +anthropic==0.19.1 +boto3==1.34.59 anyio==3.7.1 async-timeout==4.0.3 attrs==23.1.0 diff --git a/tool_use_package/tool_user.py b/tool_use_package/tool_user.py index 635d08f..4faafd6 100644 --- a/tool_use_package/tool_user.py +++ b/tool_use_package/tool_user.py @@ -1,5 +1,5 @@ from anthropic import Anthropic -from anthropic_bedrock import AnthropicBedrock +from anthropic import AnthropicBedrock import re import builtins import ast @@ -43,10 +43,12 @@ def __init__(self, tools, temperature=0, max_retries=3, first_party=True, model= self.model=model self.client = Anthropic() else: - if model == "anthropic.claude-v2:1" or model == "default": + if model == "anthropic.claude-v2:1" or model == "default" : self.model = "anthropic.claude-v2:1" + elif "anthropic.claude-3" in model : + self.model = model else: - raise ValueError("Only Claude 2.1 is currently supported when working with bedrock in this sdk. If you'd like to use another model, please use the first party anthropic API (and set first_party=true).") + raise ValueError("Only Claude 2.1 and Claude 3 Sonnet is currently supported when working with bedrock in this sdk. If you'd like to use another model, please use the first party anthropic API (and set first_party=true).") self.client = AnthropicBedrock() self.current_prompt = None self.current_num_retries = 0 @@ -203,7 +205,7 @@ def _construct_next_injection(self, invoke_results): raise ValueError(f"Unrecognized status from invoke_results, {invoke_results['status']}.") def _complete(self, prompt, max_tokens_to_sample, temperature): - if self.first_party: + if self.first_party or "anthropic.claude-3" in self.model: return self._messages_complete(prompt, max_tokens_to_sample, temperature) else: return self._completions_complete(prompt, max_tokens_to_sample, temperature) From 4b84c7c34ced683498f642d1da766b589d2f7788 Mon Sep 17 00:00:00 2001 From: Steven Su Date: Sun, 10 Mar 2024 17:39:26 +0800 Subject: [PATCH 2/2] add tools_example.py example --- tools_example.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tools_example.py diff --git a/tools_example.py b/tools_example.py new file mode 100644 index 0000000..b1978fb --- /dev/null +++ b/tools_example.py @@ -0,0 +1,65 @@ +import requests + +from tool_use_package.tools.base_tool import BaseTool +from tool_use_package.tool_user import ToolUser + +# 1. Define the Tool +class GetLatitudeAndLongitude(BaseTool): + """Returns the latitude and longitude for a given place name.""" + + def use_tool(self,place): + + url = "https://nominatim.openstreetmap.org/search" + params = {'q': place, 'format': 'json', 'limit': 1} + response = requests.get(url, params=params).json() + if response: + lat = response[0]["lat"] + lon = response[0]["lon"] + print(f"invoke lat and lon tools {place}, {lat},{lon}") + return {"latitude": lat, "longitude": lon} + else: + return None + +class GetWeatherTool(BaseTool): + """Returns weather data for a given latitude and longitude.""" + + def use_tool(self,latitude: str, longitude: str): + url = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}¤t_weather=true" + response = requests.get(url) + result = response.json() + print(f"invoke getweather tools {latitude}, {longitude},{result}") + return result + + + + + +# 2. Tool Description +getweather_tool_name = "perform_getweather" +getweather_tool_description = """Returns weather data for a given latitude and longitude. +Use this tool WHENEVER you need to perform any getweather calculation, as it will ensure your answer is precise.""" +getweather_tool_parameters = [ + {"name": "latitude", "type": "str", "description": "latitude."}, + {"name": "longitude", "type": "str", "description": "longitude."} +] + +getlat_and_lon_tool_name = "perform_getweather_tools" +getlat_and_lon_tool_description = """Returns the latitude and longitude for a given place name.. +Use this tool WHENEVER you need to perform any getweather calculation, as it will ensure your answer is precise.""" +getlat_and_lon_tool_parameters = [ + {"name": "place", "type": "str", "description": "place name."}, +] + +getweather_tool = GetWeatherTool(getweather_tool_name, getweather_tool_description, getweather_tool_parameters) +getlatitude_longitude_tool = GetLatitudeAndLongitude(getlat_and_lon_tool_name ,getlat_and_lon_tool_description,getlat_and_lon_tool_parameters) + +# 3. Assign Tool and Ask Claude +tool_user = ToolUser([getlatitude_longitude_tool,getweather_tool],first_party=False , model="anthropic.claude-3-sonnet-20240229-v1:0") +messages = [ + { + "role":"user", + "content":""" + Can you check the weather for me in Paris, France?""" + } +] +print(tool_user.use_tools(messages, execution_mode="automatic")) \ No newline at end of file