diff --git a/AmazonBedrock/boto3/00_Tutorial_How-To.ipynb b/AmazonBedrock/00_Tutorial_How-To.ipynb
similarity index 50%
rename from AmazonBedrock/boto3/00_Tutorial_How-To.ipynb
rename to AmazonBedrock/00_Tutorial_How-To.ipynb
index a78ae59..ed2c0f7 100755
--- a/AmazonBedrock/boto3/00_Tutorial_How-To.ipynb
+++ b/AmazonBedrock/00_Tutorial_How-To.ipynb
@@ -15,7 +15,7 @@
"source": [
"## How to get started\n",
"\n",
- "1. Clone this repository to your local machine.\n",
+ "1. If you are attending an instructor lead workshop or deployed the workshop infrastructure using the provided [CloudFormation Template](https://raw.githubusercontent.com/aws-samples/prompt-engineering-with-anthropic-claude-v-3/main/cloudformation/workshop-v1-final-cfn.yml) you can proceed to step 2, otherwise you will need to download the workshop [GitHub Repository](https://github.com/aws-samples/prompt-engineering-with-anthropic-claude-v-3) to your local machine.\n",
"\n",
"2. Install the required dependencies by running the following command:\n",
" "
@@ -31,36 +31,20 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"%pip install -qU pip\n",
- "%pip install -qr ../requirements.txt"
+ "%pip install -qUr requirements.txt --force-reinstall"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "3. Restart the kernel after installing dependencies"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# restart kernel\n",
- "from IPython.core.display import HTML\n",
- "HTML(\"\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "4. Run the notebook cells in order, following the instructions provided."
+ "3. Run the notebook cells in order, following the instructions provided."
]
},
{
@@ -77,8 +61,8 @@
"\n",
"- When you reach the bottom of a tutorial page, navigate to the next numbered file in the folder, or to the next numbered folder if you're finished with the content within that chapter file.\n",
"\n",
- "### The Anthropic SDK & the Messages API\n",
- "We will be using the [Anthropic python SDK](https://docs.anthropic.com/claude/reference/client-sdks) and the [Messages API](https://docs.anthropic.com/claude/reference/messages_post) throughout this tutorial. \n",
+ "### The Boto3 SDK & the Converse API\n",
+ "We will be using the [Amazon Boto3 SDK](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime.html) and the [Converse API](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime/client/converse.html) throughout this tutorial. \n",
"\n",
"Below is an example of what running a prompt will look like in this tutorial. First, we create `get_completion`, which is a helper function that sends a prompt to Claude and returns Claude's generated response. Run that cell now."
]
@@ -97,13 +81,30 @@
"outputs": [],
"source": [
"import boto3\n",
- "session = boto3.Session() # create a boto3 session to dynamically get and set the region name\n",
- "AWS_REGION = session.region_name\n",
- "print(\"AWS Region:\", AWS_REGION)\n",
- "MODEL_NAME = \"anthropic.claude-3-haiku-20240307-v1:0\"\n",
+ "import json\n",
+ "from datetime import datetime\n",
+ "from botocore.exceptions import ClientError\n",
"\n",
- "%store MODEL_NAME\n",
- "%store AWS_REGION"
+ "session = boto3.Session()\n",
+ "region = session.region_name"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
+ "modelId = 'anthropic.claude-3-haiku-20240307-v1:0'\n",
+ "\n",
+ "%store modelId\n",
+ "%store region\n",
+ "\n",
+ "print(f'Using modelId: {modelId}')\n",
+ "print('Using region: ', region)\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
]
},
{
@@ -116,29 +117,46 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
- "import boto3\n",
- "import json\n",
+ "def get_completion(prompt, system_prompt=None):\n",
+ " # Define the inference configuration\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0, # Set the temperature for generating diverse responses\n",
+ " \"maxTokens\": 200 # Set the maximum number of tokens to generate\n",
+ " }\n",
+ " # Define additional model fields\n",
+ " additional_model_fields = {\n",
+ " \"top_p\": 1, # Set the top_p value for nucleus sampling\n",
+ " }\n",
+ " # Create the converse method parameters\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId, # Specify the model ID to use\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}], # Provide the user's prompt\n",
+ " \"inferenceConfig\": inference_config, # Pass the inference configuration\n",
+ " \"additionalModelRequestFields\": additional_model_fields # Pass additional model fields\n",
+ " }\n",
+ " # Check if system_text is provided\n",
+ " if system_prompt:\n",
+ " # If system_text is provided, add the system parameter to the converse_params dictionary\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ "\n",
+ " # Send a request to the Bedrock client to generate a response\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
"\n",
- "bedrock = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": ''\n",
- " }\n",
- " )\n",
- " response = bedrock.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ " # Extract the generated text content from the response\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ "\n",
+ " # Return the generated text content\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -153,7 +171,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -167,15 +187,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "The `MODEL_NAME` and `AWS_REGION` variables defined earlier will be used throughout the tutorial. Just make sure to run the cells for each tutorial page from top to bottom."
+ "The `modelId` and `region` variables defined earlier will be used throughout the tutorial. Just make sure to run the cells for each tutorial page from top to bottom."
]
}
],
"metadata": {
"kernelspec": {
- "display_name": "py310",
+ "display_name": "conda_tensorflow2_p310",
"language": "python",
- "name": "python3"
+ "name": "conda_tensorflow2_p310"
},
"language_info": {
"codemirror_mode": {
@@ -187,9 +207,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.0"
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/anthropic/01_Basic_Prompt_Structure.ipynb b/AmazonBedrock/01_Basic_Prompt_Structure.ipynb
similarity index 60%
rename from AmazonBedrock/anthropic/01_Basic_Prompt_Structure.ipynb
rename to AmazonBedrock/01_Basic_Prompt_Structure.ipynb
index 2b9190c..63f9041 100755
--- a/AmazonBedrock/anthropic/01_Basic_Prompt_Structure.ipynb
+++ b/AmazonBedrock/01_Basic_Prompt_Structure.ipynb
@@ -18,38 +18,80 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "%pip install -qU pip\n",
+ "%pip install -qUr requirements.txt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
"# Import python's built-in regular expression library\n",
"import re\n",
- "from anthropic import AnthropicBedrock\n",
+ "import boto3\n",
+ "from botocore.exceptions import ClientError\n",
+ "import json\n",
"\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
+ "# Import the hints module from the utils package\n",
+ "from utils import hints\n",
"\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
+ "# Retrieve the MODEL_NAME variable from the IPython store\n",
+ "%store -r modelId\n",
+ "%store -r region\n",
"\n",
- "def get_completion(prompt, system=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None):\n",
+ " # Define the inference configuration\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0, # Set the temperature for generating diverse responses\n",
+ " \"maxTokens\": 200 # Set the maximum number of tokens to generate\n",
+ " }\n",
+ " # Define additional model fields\n",
+ " additional_model_fields = {\n",
+ " \"top_p\": 1, # Set the top_p value for nucleus sampling\n",
+ " }\n",
+ " # Create the converse method parameters\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId, # Specify the model ID to use\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}], # Provide the user's prompt\n",
+ " \"inferenceConfig\": inference_config, # Pass the inference configuration\n",
+ " \"additionalModelRequestFields\": additional_model_fields # Pass additional model fields\n",
+ " }\n",
+ " # Check if system_text is provided\n",
+ " if system_prompt:\n",
+ " # If system_text is provided, add the system parameter to the converse_params dictionary\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ "\n",
+ " # Send a request to the Bedrock client to generate a response\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " # Extract the generated text content from the response\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ "\n",
+ " # Return the generated text content\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -60,22 +102,24 @@
"\n",
"## Lesson\n",
"\n",
- "Anthropic offers two APIs, the legacy [Text Completions API](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-text-completion.html) and the current [Messages API](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html). For this tutorial, we will be exclusively using the Messages API.\n",
+ "Amazon Bedrock offers three APIs that can be used with Anthropic Claude models, the legacy [Text Completions API](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-text-completion.html) , the [Messages API](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html) and the current [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html). For this tutorial, we will be exclusively using the Converse API.\n",
"\n",
- "At minimum, a call to Claude using the Messages API requires the following parameters:\n",
- "- `model`: the [API model name](https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html#model-ids-arns) of the model that you intend to call\n",
+ "At minimum, a call to Claude using the Converse API requires the following parameters:\n",
+ "- `modelId`: the [API model name](https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html#model-ids-arns) of the model that you intend to call\n",
"\n",
- "- `max_tokens`: the maximum number of tokens to generate before stopping. Note that Claude may stop before reaching this maximum. This parameter only specifies the absolute maximum number of tokens to generate. Furthermore, this is a *hard* stop, meaning that it may cause Claude to stop generating mid-word or mid-sentence.\n",
- "\n",
- "- `messages`: an array of input messages. Our models are trained to operate on alternating `user` and `assistant` conversational turns. When creating a new `Message`, you specify the prior conversational turns with the messages parameter, and the model then generates the next `Message` in the conversation.\n",
- " - Each input message must be an object with a `role` and `content`. You can specify a single `user`-role message, or you can include multiple `user` and `assistant` messages (they must alternate, if so). The first message must always use the user `role`.\n",
+ "- `messages`: an array of input messages. Claude 3 models are trained to operate on alternating `user` and `assistant` conversational turns. When creating a new `Message`, you specify the prior conversational turns with the messages parameter, and the model then generates the next `Message` in the conversation.\n",
+ " - Each input message must be an object with a `role` and `content`. You can specify a single `user`-role message, or you can include multiple `user` and `assistant` messages (they must alternate, if so). **The first message must always use the `user` role.**\n",
+ " \n",
+ " You store the content for the message in the `content` field of a [(ContentBlock)](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ContentBlock.html). Specify text in the `text` field, or if supported by the model, you can also pass the raw bytes for an image in the `image` field of an [(ImageBlock)](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html). The other fields in ContentBlock are for [tool use](https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use.html).\n",
"\n",
"There are also optional parameters, such as:\n",
"- `system`: the system prompt - more on this below.\n",
" \n",
"- `temperature`: the degree of variability in Claude's response. For these lessons and exercises, we have set `temperature` to 0.\n",
"\n",
- "For a complete list of all API parameters, visit our [API documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-claude.html)."
+ "- `max_tokens`: the maximum number of tokens to generate before stopping. Note that Claude may stop before reaching this maximum. This parameter only specifies the absolute maximum number of tokens to generate. Furthermore, this is a *hard* stop, meaning that it may cause Claude to stop generating mid-word or mid-sentence.\n",
+ "\n",
+ "For a complete list of all API parameters, visit our [API documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)."
]
},
{
@@ -90,7 +134,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -103,7 +149,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -116,7 +164,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -130,9 +180,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Now let's take a look at some prompts that do not include the correct Messages API formatting. For these malformatted prompts, the Messages API returns an error.\n",
+ "Now let's take a look at some prompts that do not include the correct Converse API formatting. For these malformatted prompts, the Converse API returns an error.\n",
"\n",
- "First, we have an example of a Messages API call that lacks `role` and `content` fields in the `messages` array."
+ "First, we have an example of a Converse API call that lacks `role` and `content` fields in the `messages` array."
]
},
{
@@ -145,21 +195,27 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Get Claude's response\n",
- "response = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"Hi Claude, how are you?\"}\n",
- " ]\n",
- " )\n",
+ "inference_config = {\n",
+ " \"temperature\": 0.0, # Set the temperature for generating diverse responses\n",
+ " \"max_tokens\": 200 # Set the maximum number of tokens to generate\n",
+ "}\n",
+ "\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"text\":\"Hi Claude, how are you?\"}], # Provide the user's prompt\n",
+ " \"inferenceConfig\": inference_config # Pass the inference configuration\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)\n",
"\n",
"# Print Claude's response\n",
- "print(response[0].text)"
+ "print(response['output']['message']['content'][0]['text'])"
]
},
{
@@ -179,22 +235,29 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
- "# Get Claude's response\n",
- "response = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": \"What year was Celine Dion born in?\"},\n",
- " {\"role\": \"user\", \"content\": \"Also, can you tell me some other facts about her?\"}\n",
- " ]\n",
- " )\n",
+ "inference_config = {\n",
+ " \"temperature\": 0.5,\n",
+ " \"maxTokens\": 200\n",
+ "}\n",
+ "# Create the converse method parameters\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [\n",
+ " {\"role\": \"user\", \"content\": [{\"text\": \"What year was Celine Dion born in?\"}]},\n",
+ " {\"role\": \"user\", \"content\": [{\"text\":\"Also, can you tell me some other facts about her?\"}]}\n",
+ " ],\n",
+ " \"inferenceConfig\": inference_config,\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)\n",
"\n",
"# Print Claude's response\n",
- "print(response[0].text)"
+ "print(response['output']['message']['content'][0]['text'])"
]
},
{
@@ -222,7 +285,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# System prompt\n",
@@ -239,7 +304,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Why use a system prompt? A **well-written system prompt can improve Claude's performance** in a variety of ways, such as increasing Claude's ability to follow rules and instructions. For more information, visit our documentation on [how to use system prompts](https://docs.anthropic.com/claude/docs/how-to-use-system-prompts) with Claude.\n",
+ "Why use a system prompt? A **well-written system prompt can improve Claude's performance** in a variety of ways, such as increasing Claude's ability to follow rules and instructions. For more information, visit Anthropic's documentation on [how to use system prompts](https://docs.anthropic.com/claude/docs/how-to-use-system-prompts) with Claude.\n",
"\n",
"Now we'll dive into some exercises. If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
]
@@ -266,7 +331,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt - this is the only field you should change\n",
@@ -375,7 +442,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -388,7 +457,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -401,7 +472,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -418,17 +491,24 @@
"outputs": [],
"source": [
"# Get Claude's response\n",
- "response = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"Hi Claude, how are you?\"}\n",
- " ]\n",
- " )\n",
+ "inference_config = {\n",
+ " \"temperature\": 0.0\n",
+ "}\n",
+ "additional_model_fields = {\n",
+ " \"max_tokens\": 200\n",
+ "}\n",
+ "\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"text\":\"Hi Claude, how are you?\"}],\n",
+ " \"inferenceConfig\": inference_config,\n",
+ " \"additionalModelRequestFields\": additional_model_fields\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)\n",
"\n",
"# Print Claude's response\n",
- "print(response[0].text)"
+ "print(response['output']['message']['content'][0]['text'])"
]
},
{
@@ -437,25 +517,35 @@
"metadata": {},
"outputs": [],
"source": [
- "# Get Claude's response\n",
- "response = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": \"What year was Celine Dion born in?\"},\n",
- " {\"role\": \"user\", \"content\": \"Also, can you tell me some other facts about her?\"}\n",
- " ]\n",
- " )\n",
+ "inference_config = {\n",
+ " \"temperature\": 0.0\n",
+ "}\n",
+ "additional_model_fields = {\n",
+ " \"top_p\": 1,\n",
+ " \"max_tokens\": 200\n",
+ "}\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [\n",
+ " {\"role\": \"user\", \"content\": [{\"text\": \"What year was Celine Dion born in?\"}]},\n",
+ " {\"role\": \"user\", \"content\": [{\"text\":\"Also, can you tell me some other facts about her?\"}]}\n",
+ " ],\n",
+ " \"inferenceConfig\": inference_config,\n",
+ " \"additionalModelRequestFields\": additional_model_fields\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)\n",
"\n",
"# Print Claude's response\n",
- "print(response[0].text)"
+ "print(response['output']['message']['content'][0]['text'])"
]
},
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# System prompt\n",
@@ -471,9 +561,9 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "conda_tensorflow2_p310",
"language": "python",
- "name": "python3"
+ "name": "conda_tensorflow2_p310"
},
"language_info": {
"codemirror_mode": {
@@ -485,9 +575,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.5"
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/02_Being_Clear_and_Direct.ipynb b/AmazonBedrock/02_Being_Clear_and_Direct.ipynb
similarity index 84%
rename from AmazonBedrock/boto3/02_Being_Clear_and_Direct.ipynb
rename to AmazonBedrock/02_Being_Clear_and_Direct.ipynb
index deaa6cf..2a4b562 100755
--- a/AmazonBedrock/boto3/02_Being_Clear_and_Direct.ipynb
+++ b/AmazonBedrock/02_Being_Clear_and_Direct.ipynb
@@ -18,42 +18,57 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
+ "%store -r modelId\n",
+ "%store -r region\n",
"\n",
- "def get_completion(prompt,system=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " additional_model_fields = {\n",
+ " \"top_p\": 1\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config,\n",
+ " \"additionalModelRequestFields\": additional_model_fields\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -84,7 +99,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -382,7 +399,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -394,10 +413,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/03_Assigning_Roles_Role_Prompting.ipynb b/AmazonBedrock/03_Assigning_Roles_Role_Prompting.ipynb
similarity index 85%
rename from AmazonBedrock/boto3/03_Assigning_Roles_Role_Prompting.ipynb
rename to AmazonBedrock/03_Assigning_Roles_Role_Prompting.ipynb
index e78f86c..d5df1d2 100755
--- a/AmazonBedrock/boto3/03_Assigning_Roles_Role_Prompting.ipynb
+++ b/AmazonBedrock/03_Assigning_Roles_Role_Prompting.ipynb
@@ -18,42 +18,53 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt,system=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "%store -r modelId\n",
+ "%store -r region\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -311,7 +322,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# System prompt\n",
@@ -326,10 +339,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/04_Separating_Data_and_Instructions.ipynb b/AmazonBedrock/04_Separating_Data_and_Instructions.ipynb
similarity index 79%
rename from AmazonBedrock/boto3/04_Separating_Data_and_Instructions.ipynb
rename to AmazonBedrock/04_Separating_Data_and_Instructions.ipynb
index bce6608..d9977a3 100755
--- a/AmazonBedrock/boto3/04_Separating_Data_and_Instructions.ipynb
+++ b/AmazonBedrock/04_Separating_Data_and_Instructions.ipynb
@@ -24,36 +24,45 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
+ "%store -r modelId\n",
+ "%store -r region\n",
"\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt,system=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -64,11 +73,11 @@
"\n",
"## Lesson\n",
"\n",
- "Oftentimes, we don't want to write full prompts, but instead want **prompt templates that can be modified later with additional input data before submitting to Claude**. This might come in handy if you want Claude to do the same thing every time, but the data that Claude uses for its task might be different each time. \n",
+ "Oftentimes, you don't want to write full prompts, but instead want **prompt templates that can be modified later with additional input data before submitting to Claude**. This might come in handy if you want Claude to do the same thing every time, but the data that Claude uses for its task might be different each time. \n",
"\n",
- "Luckily, we can do this pretty easily by **separating the fixed skeleton of the prompt from variable user input, then substituting the user input into the prompt** before sending the full prompt to Claude. \n",
+ "Luckily, you can do this pretty easily by **separating the fixed skeleton of the prompt from variable user input, then substituting the user input into the prompt** before sending the full prompt to Claude. \n",
"\n",
- "Below, we'll walk step by step through how to write a substitutable prompt template, as well as how to substitute in user input."
+ "Below, you'll walk step by step through how to write a substitutable prompt template, as well as how to substitute in user input."
]
},
{
@@ -77,9 +86,9 @@
"source": [
"### Examples\n",
"\n",
- "In this first example, we're asking Claude to act as an animal noise generator. Notice that the full prompt submitted to Claude is just the `PROMPT_TEMPLATE` substituted with the input (in this case, \"Cow\"). Notice that the word \"Cow\" replaces the `ANIMAL` placeholder via an f-string when we print out the full prompt.\n",
+ "In this first example, you're asking Claude to act as an animal noise generator. Notice that the full prompt submitted to Claude is just the `PROMPT_TEMPLATE` substituted with the input (in this case, \"Cow\"). Notice that the word \"Cow\" replaces the `ANIMAL` placeholder via an f-string when you print out the full prompt.\n",
"\n",
- "**Note:** You don't have to call your placeholder variable anything in particular in practice. We called it `ANIMAL` in this example, but just as easily, we could have called it `CREATURE` or `A` (although it's generally good to have your variable names be specific and relevant so that your prompt template is easy to understand even without the substitution, just for user parseability). Just make sure that whatever you name your variable is what you use for the prompt template f-string."
+ "**Note:** You don't have to call your placeholder variable anything in particular in practice. You called it `ANIMAL` in this example, but just as easily, you could have called it `CREATURE` or `A` (although it's generally good to have your variable names be specific and relevant so that your prompt template is easy to understand even without the substitution, just for user parseability). Just make sure that whatever you name your variable is what you use for the prompt template f-string."
]
},
{
@@ -105,9 +114,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Why would we want to separate and substitute inputs like this? Well, **prompt templates simplify repetitive tasks**. Let's say you build a prompt structure that invites third party users to submit content to the prompt (in this case the animal whose sound they want to generate). These third party users don't have to write or even see the full prompt. All they have to do is fill in variables.\n",
+ "Why would you want to separate and substitute inputs like this? Well, **prompt templates simplify repetitive tasks**. Let's say you build a prompt structure that invites third party users to submit content to the prompt (in this case the animal whose sound they want to generate). These third party users don't have to write or even see the full prompt. All they have to do is fill in variables.\n",
"\n",
- "We do this substitution here using variables and f-strings, but you can also do it with the format() method.\n",
+ "You do this substitution here using variables and f-strings, but you can also do it with the format() method.\n",
"\n",
"**Note:** Prompt templates can have as many variables as desired!"
]
@@ -151,11 +160,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "How do we solve this? **Wrap the input in XML tags**! We did this below, and as you can see, there's no more \"Dear Claude\" in the output.\n",
+ "How do you solve this? **Wrap the input in XML tags**! We did this below, and as you can see, there's no more \"Dear Claude\" in the output.\n",
"\n",
"[XML tags](https://docs.anthropic.com/claude/docs/use-xml-tags) are angle-bracket tags like ``. They come in pairs and consist of an opening tag, such as ``, and a closing tag marked by a `/`, such as ``. XML tags are used to wrap around content, like this: `content`.\n",
"\n",
- "**Note:** While Claude can recognize and work with a wide range of separators and delimeters, we recommend that you **use specifically XML tags as separators** for Claude, as Claude was trained specifically to recognize XML tags as a prompt organizing mechanism. Outside of function calling, **there are no special sauce XML tags that Claude has been trained on that you should use to maximally boost your performance**. We have purposefully made Claude very malleable and customizable this way."
+ "**Note:** While Claude can recognize and work with a wide range of separators and delimeters, we recommend that you **use specifically XML tags as separators** for Claude, as Claude was trained specifically to recognize XML tags as a prompt organizing mechanism. Outside of function calling, **there are no special sauce XML tags that Claude has been trained on that you should use to maximally boost your performance**. Anthropic has purposefully made Claude very malleable and customizable this way."
]
},
{
@@ -214,7 +223,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "To fix this, we just need to **surround the user input sentences in XML tags**. This shows Claude where the input data begins and ends despite the misleading hyphen before `Each is about an animal, like rabbits.`"
+ "To fix this, you just need to **surround the user input sentences in XML tags**. This shows Claude where the input data begins and ends despite the misleading hyphen before `Each is about an animal, like rabbits.`"
]
},
{
@@ -247,7 +256,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "**Note:** In the incorrect version of the \"Each is about an animal\" prompt, we had to include the hyphen to get Claude to respond incorrectly in the way we wanted to for this example. This is an important lesson about prompting: **small details matter**! It's always worth it to **scrub your prompts for typos and grammatical errors**. Claude is sensitive to patterns (in its early years, before finetuning, it was a raw text-prediction tool), and it's more likely to make mistakes when you make mistakes, smarter when you sound smart, sillier when you sound silly, and so on.\n",
+ "**Note:** In the incorrect version of the \"Each is about an animal\" prompt, you had to include the hyphen to get Claude to respond incorrectly in the way you wanted to for this example. This is an important lesson about prompting: **small details matter**! It's always worth it to **scrub your prompts for typos and grammatical errors**. Claude is sensitive to patterns (in its early years, before finetuning, it was a raw text-prediction tool), and it's more likely to make mistakes when you make mistakes, smarter when you sound smart, sillier when you sound silly, and so on.\n",
"\n",
"If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
]
@@ -282,7 +291,7 @@
"TOPIC = \"Pigs\"\n",
"\n",
"# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"\"\n",
+ "PROMPT = f\"Create a haiku about {TOPIC}\"\n",
"\n",
"# Get Claude's response\n",
"response = get_completion(PROMPT)\n",
@@ -528,7 +537,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Variable content\n",
@@ -553,10 +564,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_pytorch_p310",
+ "language": "python",
+ "name": "conda_pytorch_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/05_Formatting_Output_and_Speaking_for_Claude.ipynb b/AmazonBedrock/05_Formatting_Output_and_Speaking_for_Claude.ipynb
similarity index 90%
rename from AmazonBedrock/boto3/05_Formatting_Output_and_Speaking_for_Claude.ipynb
rename to AmazonBedrock/05_Formatting_Output_and_Speaking_for_Claude.ipynb
index d656f78..cd8e342 100755
--- a/AmazonBedrock/boto3/05_Formatting_Output_and_Speaking_for_Claude.ipynb
+++ b/AmazonBedrock/05_Formatting_Output_and_Speaking_for_Claude.ipynb
@@ -24,39 +24,47 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\":[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
+ "%store -r modelId\n",
+ "%store -r region\n",
"\n",
- " return response_body.get('content')[0].get('text')"
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None, prefill=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.5,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " if prefill:\n",
+ " converse_api_params[\"messages\"].append({\"role\": \"assistant\", \"content\": [{\"text\": prefill}]})\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -301,7 +309,7 @@
"ANIMAL = \"cats\"\n",
"\n",
"# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Put it in tags.\"\n",
+ "PROMPT = f\"Please write two haikus about {ANIMAL}. Put each haiku in tags.\"\n",
"\n",
"# Prefill for Claude's response\n",
"PREFILL = \"\"\n",
@@ -492,7 +500,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# First input variable\n",
@@ -519,10 +529,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/06_Precognition_Thinking_Step_by_Step.ipynb b/AmazonBedrock/06_Precognition_Thinking_Step_by_Step.ipynb
similarity index 91%
rename from AmazonBedrock/boto3/06_Precognition_Thinking_Step_by_Step.ipynb
rename to AmazonBedrock/06_Precognition_Thinking_Step_by_Step.ipynb
index ed19359..57ecb77 100755
--- a/AmazonBedrock/boto3/06_Precognition_Thinking_Step_by_Step.ipynb
+++ b/AmazonBedrock/06_Precognition_Thinking_Step_by_Step.ipynb
@@ -24,39 +24,47 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
+ "%store -r modelId\n",
+ "%store -r region\n",
"\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\":[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None, prefill=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config,\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " if prefill:\n",
+ " converse_api_params[\"messages\"].append({\"role\": \"assistant\", \"content\": [{\"text\": prefill}]})\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -487,7 +495,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -500,15 +510,23 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "conda_pytorch_p310",
"language": "python",
- "name": "python3"
+ "name": "conda_pytorch_p310"
},
"language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
"name": "python",
- "version": "3.12.0"
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/07_Using_Examples_Few-Shot_Prompting.ipynb b/AmazonBedrock/07_Using_Examples_Few-Shot_Prompting.ipynb
similarity index 90%
rename from AmazonBedrock/boto3/07_Using_Examples_Few-Shot_Prompting.ipynb
rename to AmazonBedrock/07_Using_Examples_Few-Shot_Prompting.ipynb
index 056d4e7..3ba376b 100755
--- a/AmazonBedrock/boto3/07_Using_Examples_Few-Shot_Prompting.ipynb
+++ b/AmazonBedrock/07_Using_Examples_Few-Shot_Prompting.ipynb
@@ -24,39 +24,47 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\":[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "%store -r modelId\n",
+ "%store -r region\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None, prefill=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " if prefill:\n",
+ " converse_api_params[\"messages\"].append({\"role\": \"assistant\", \"content\": [{\"text\": prefill}]})\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -345,7 +353,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt template with a placeholder for the variable content\n",
@@ -394,10 +404,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/08_Avoiding_Hallucinations.ipynb b/AmazonBedrock/08_Avoiding_Hallucinations.ipynb
similarity index 99%
rename from AmazonBedrock/boto3/08_Avoiding_Hallucinations.ipynb
rename to AmazonBedrock/08_Avoiding_Hallucinations.ipynb
index a303f1b..e94133f 100755
--- a/AmazonBedrock/boto3/08_Avoiding_Hallucinations.ipynb
+++ b/AmazonBedrock/08_Avoiding_Hallucinations.ipynb
@@ -24,39 +24,47 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\":[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
+ "%store -r modelId\n",
+ "%store -r region\n",
"\n",
- " return response_body.get('content')[0].get('text')"
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None, prefill=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " if prefill:\n",
+ " converse_api_params[\"messages\"].append({\"role\": \"assistant\", \"content\": [{\"text\": prefill}]})\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -623,7 +631,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"# Prompt\n",
@@ -704,10 +714,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/09_Complex_Prompts_from_Scratch.ipynb b/AmazonBedrock/09_Complex_Prompts_from_Scratch.ipynb
similarity index 97%
rename from AmazonBedrock/boto3/09_Complex_Prompts_from_Scratch.ipynb
rename to AmazonBedrock/09_Complex_Prompts_from_Scratch.ipynb
index f4aae6c..5e4be8f 100755
--- a/AmazonBedrock/boto3/09_Complex_Prompts_from_Scratch.ipynb
+++ b/AmazonBedrock/09_Complex_Prompts_from_Scratch.ipynb
@@ -24,39 +24,47 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
"# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
"from utils import hints\n",
"\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\":[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "%store -r modelId\n",
+ "%store -r region\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(prompt, system_prompt=None, prefill=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.0,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " if prefill:\n",
+ " converse_api_params[\"messages\"].append({\"role\": \"assistant\", \"content\": [{\"text\": prefill}]})\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -1077,7 +1085,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"######################################## INPUT VARIABLES ########################################\n",
@@ -1222,10 +1232,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_pytorch_p310",
+ "language": "python",
+ "name": "conda_pytorch_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/boto3/10_1_Appendix_Chaining_Prompts.ipynb b/AmazonBedrock/10_1_Appendix_Chaining_Prompts.ipynb
old mode 100644
new mode 100755
similarity index 81%
rename from AmazonBedrock/boto3/10_1_Appendix_Chaining_Prompts.ipynb
rename to AmazonBedrock/10_1_Appendix_Chaining_Prompts.ipynb
index 68e9583..d68e5a8
--- a/AmazonBedrock/boto3/10_1_Appendix_Chaining_Prompts.ipynb
+++ b/AmazonBedrock/10_1_Appendix_Chaining_Prompts.ipynb
@@ -23,29 +23,45 @@
"# Import python's built-in regular expression library\n",
"import re\n",
"import boto3\n",
+ "from botocore.exceptions import ClientError\n",
"import json\n",
"\n",
+ "# Import the hints module from the utils package\n",
+ "from utils import hints\n",
+ "\n",
"# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(messages, system_prompt=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": messages,\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system_prompt\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
+ "%store -r modelId\n",
+ "%store -r region\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_completion(messages, system_prompt=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.5,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": inference_config\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")"
]
},
{
@@ -81,10 +97,8 @@
"\n",
"# API messages array\n",
"messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " }\n",
+ " {\"role\": \"user\",\n",
+ " \"content\": [{\"text\": first_user}]}\n",
"]\n",
"\n",
"# Store and print Claude's response\n",
@@ -113,19 +127,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -169,19 +181,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -225,19 +235,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -271,7 +279,7 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
+ " \"content\": [{\"text\": first_user}]\n",
" }\n",
"]\n",
"\n",
@@ -299,19 +307,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -346,13 +352,11 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": prefill\n",
- " \n",
+ " \"content\": [{\"text\": prefill}]\n",
" }\n",
"]\n",
"\n",
@@ -383,19 +387,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": prefill + \"\\n\" + first_response\n",
- " \n",
+ " \"content\": [{\"text\": prefill + \"\\n\" + first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -434,10 +436,8 @@
"\n",
"# API messages array\n",
"messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " }\n",
+ " {\"role\": \"user\",\n",
+ " \"content\": [{\"text\": first_user}]}\n",
"]\n",
"\n",
"# Store and print Claude's response\n",
@@ -457,19 +457,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -506,19 +504,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -555,19 +551,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -590,7 +584,7 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
+ " \"content\": [{\"text\": first_user}]\n",
" }\n",
"]\n",
"\n",
@@ -611,19 +605,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
+ " \"content\": [{\"text\": first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -649,13 +641,11 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": prefill\n",
- " \n",
+ " \"content\": [{\"text\": prefill}]\n",
" }\n",
"]\n",
"\n",
@@ -670,7 +660,9 @@
{
"cell_type": "code",
"execution_count": null,
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [],
"source": [
"second_user = \"Alphabetize the list.\"\n",
@@ -679,19 +671,17 @@
"messages = [\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
+ " \"content\": [{\"text\": first_user}]\n",
" },\n",
" {\n",
" \"role\": \"assistant\",\n",
- " \"content\": prefill + \"\\n\" + first_response\n",
- " \n",
+ " \"content\": [{\"text\": prefill + \"\\n\" + first_response}]\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
+ " \"content\": [{\"text\": second_user}]\n",
+ " },\n",
+ "\n",
"]\n",
"\n",
"# Print Claude's response\n",
@@ -703,10 +693,24 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
"language_info": {
- "name": "python"
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/10_2_1_Your_First_Simple_Tool.ipynb b/AmazonBedrock/10_2_1_Your_First_Simple_Tool.ipynb
new file mode 100755
index 0000000..0d301b6
--- /dev/null
+++ b/AmazonBedrock/10_2_1_Your_First_Simple_Tool.ipynb
@@ -0,0 +1,991 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Appendix 10.2.1: Your First Simple Tool\n",
+ "\n",
+ "In the previous lesson we walked through the tool use workflow. It's time to actually get to work implementing a simple example of tool use. As a recap, there are up to 4 steps in the tool use process: \n",
+ "\n",
+ "1. **Provide Claude with tools and a user prompt:** (API request)\n",
+ " * Define the set of tools you want Claude to have access to, including their names, descriptions, and input schemas.\n",
+ " * Provide a user prompt that may require the use of one or more of these tools to answer.\n",
+ "\n",
+ "2. **Claude uses a tool:** (API response)\n",
+ " * Claude assesses the user prompt and decides whether any of the available tools would help with the user's query or task. If so, it also decides which tool(s) to use and with what input(s).\n",
+ " * Claude outputs a properly formatted tool use request.\n",
+ " * The API response will have a `stop_reason` of `tool_use`, indicating that Claude wants to use an external tool.\n",
+ "\n",
+ "3. **Extract tool input(s), run code, and return results:** (API request)\n",
+ " * On the client side, you should extract the tool name and input from Claude's tool use request.\n",
+ " * Run the actual tool code on the client side.\n",
+ " * Return the results to Claude by continuing the conversation with a new user message containing a `tool_result` content block.\n",
+ "\n",
+ "4. **Claude uses the tool result to formulate a response:** (API response)\n",
+ " * After receiving the tool results, Claude will use that information to formulate its final response to the original user prompt."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We're going to start with a simple demonstration that only requires \"talking\" to Claude once (don't worry, we'll get to more exciting examples soon enough!). This means that we won't bother with step 4 yet. We'll ask Claude to answer a question, Claude will request to use a tool to answer it, and then we'll extract the tool input, run code, and return the resulting value. \n",
+ "\n",
+ "Today's large language models struggle with mathematical operations, as evidenced by the following code. \n",
+ "\n",
+ "We ask Claude to \"Multiply 1984135 by 9343116\": "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "%pip install -qU pip\n",
+ "%pip install -qUr requirements.txt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import boto3\n",
+ "import json\n",
+ "from botocore.exceptions import ClientError\n",
+ "session = boto3.Session() # create a boto3 session to dynamically get and set the region name\n",
+ "region = session.region_name\n",
+ "\n",
+ "# Import the hints module from the utils package\n",
+ "from utils import hints\n",
+ "\n",
+ "modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
+ "#modelId = 'anthropic.claude-3-haiku-20240307-v1:0'\n",
+ "\n",
+ "print(f'Using modelId: {modelId}')\n",
+ "print(f'Using region: ', {region})\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "converse_api_params = {\n",
+ " \"modelId\": modelId, # Specify the model ID to use\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": \"Multiply 1984135 by 9343116. Only respond with the result\"}]}],\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 400}\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ "print(response['output']['message']['content'][0]['text'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We'll likely get a different answer by running the above code multiple times, but this is one answer Claude responded with: \n",
+ "\n",
+ "```\n",
+ "18593367726060\n",
+ "```\n",
+ "\n",
+ "The actual correct answer is :\n",
+ "\n",
+ "```\n",
+ "18538003464660\n",
+ "```\n",
+ "Claude was *slightly* off by `55364261400`! "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Tool use to the rescue!\n",
+ "\n",
+ "Claude isn't great at doing complex math, so let's enhance Claude's capabilities by providing access to a calculator tool. \n",
+ "\n",
+ "Here's a simple diagram explaining the process: \n",
+ "\n",
+ "\n",
+ "The first step is to define the actual calculator function and make sure it works, indepent of Claude. We'll write a VERY simple function that expects three arguments:\n",
+ "* An operation like \"add\" or \"multiply\"\n",
+ "* Two operands\n",
+ "\n",
+ "Here's a basic implementation:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def calculator(operation, operand1, operand2):\n",
+ " if operation == \"add\":\n",
+ " return operand1 + operand2\n",
+ " elif operation == \"subtract\":\n",
+ " return operand1 - operand2\n",
+ " elif operation == \"multiply\":\n",
+ " return operand1 * operand2\n",
+ " elif operation == \"divide\":\n",
+ " if operand2 == 0:\n",
+ " raise ValueError(\"Cannot divide by zero.\")\n",
+ " return operand1 / operand2\n",
+ " else:\n",
+ " raise ValueError(f\"Unsupported operation: {operation}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Please note that this simple function is quite limited in its utility because it can only handle simple expressions like `234 + 213` or `3 * 9`. The point here is to go through the process of working with tools via a very simple educational example.\n",
+ "\n",
+ "Let's test out our function and make sure it works."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "calculator(\"add\", 10, 3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "calculator(\"divide\", 200, 25)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The next step is to define our tool and tell Claude about it. When defining a tool, we follow a very specific format. Each tool definition includes:\n",
+ "\n",
+ "* `name`: The name of the tool. Must match the regular expression ^[a-zA-Z0-9_-]{1,64}$.\n",
+ "* `description`: A detailed plaintext description of what the tool does, when it should be used, and how it behaves.\n",
+ "* `input_schema`: A JSON Schema object defining the expected parameters for the tool.\n",
+ "\n",
+ "Unfamiliar with JSON Schema? [Learn more here](https://json-schema.org/learn/getting-started-step-by-step).\n",
+ "\n",
+ "Here's a simple example for a hypothetical tool:\n",
+ "\n",
+ "```json\n",
+ "{\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"send_email\",\n",
+ " \"description\": \"Sends an email to the specified recipient with the given subject and body.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"to\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The email address of the recipient\"},\n",
+ " \"subject\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The subject line of the email\"},\n",
+ " \"body\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The content of the email message\"}\n",
+ " },\n",
+ " \"required\": [\"to\", \"subject\", \"body\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "```\n",
+ "\n",
+ "This tool, named `send_email`, expects the following inputs:\n",
+ "* `to` which is a string and is required\n",
+ "* `subject` which is a string and is required\n",
+ "* `body` which is a string and is required\n",
+ "\n",
+ "\n",
+ "Here's another tool definition for a tool called `search_product`: \n",
+ "\n",
+ "```json\n",
+ "{\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"search_product\",\n",
+ " \"description\": \"Search for a product by name or keyword and return its current price and availability.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"query\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The product name or search keyword, e.g. 'iPhone 13 Pro' or 'wireless headphones'\"},\n",
+ " \"category\": {\n",
+ " \"type\": \"string\",\n",
+ " \"enum\": [\"electronics\", \"clothing\", \"home\", \"toys\", \"sports\"],\n",
+ " \"description\": \"The product category to narrow down the search results\"},\n",
+ " \"max_price\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The maximum price of the product, used to filter the search results\"}\n",
+ " },\n",
+ " \"required\": [\"query\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "```\n",
+ "This tool has 3 inputs: \n",
+ "* A required `query` string representing the product name or search keyword\n",
+ "* An optional `category` string that must be one of the predefined values to narrow down the search. Notice the `\"enum\"` in the definition.\n",
+ "* An optional `max_price` number to filter results below a certain price point"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Our calculator tool definition\n",
+ "Let's define the corresponding tool for our calculator function we wrote earlier. We know that the calculator function has 3 required arguments: \n",
+ "* `operation` - which can only be \"add\", \"subtract\", \"multiply\", or \"divide\"\n",
+ "* `operand1` which should be a number\n",
+ "* `operand2` which should also be a number\n",
+ "\n",
+ "Here's the tool definition:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "toolConfig = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"calculator\",\n",
+ " \"description\": \"A simple calculator that performs basic arithmetic operations.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"operation\": {\n",
+ " \"type\": \"string\",\n",
+ " \"enum\": [\"add\", \"subtract\", \"multiply\", \"divide\"],\n",
+ " \"description\": \"The arithmetic operation to perform.\"\n",
+ " },\n",
+ " \"operand1\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The first operand.\"},\n",
+ " \"operand2\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The second operand.\"}\n",
+ " },\n",
+ " \"required\": [\"operation\", \"operand1\", \"operand2\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercise\n",
+ "\n",
+ "Let’s practice writing a properly formatted tool definition using the following function as an example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def inventory_lookup(product_name, max_results):\n",
+ " return \"this function doesn't do anything\"\n",
+ " #You do not need to touch this or do anything with it!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This hypothetical `inventory_lookup` function should be called like this:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inventory_lookup(\"AA batteries\", 4)\n",
+ "\n",
+ "inventory_lookup(\"birthday candle\", 10)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Your task is to write a corresponding, properly-formatted tool definition. Assume both arguments are required in your tool definition."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "### Starter tool definition template ###\n",
+ "\n",
+ "```json\n",
+ "toolConfig = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"inventory_lookup\",\n",
+ " \"description\": \" \",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \" \": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \" \"\n",
+ " },\n",
+ " \" \": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \" \"\n",
+ " },\n",
+ " },\n",
+ " \"required\": [\" \", \" \"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Providing Claude with our tool\n",
+ "Now back to our calculator function from earlier. At this point, Claude knows nothing about the calculator tool! It's just a little Python dictionary. When making our request to Claude, we can pass a list of tools to \"tell\" Claude about. Let's try it now:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": \"Multiply 1984135 by 9343116. Only respond with the result.\"}]}],\n",
+ " \"toolConfig\": toolConfig, # provide Claude with details about our calculator tool\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, let's take a look at the response Claude gives us back:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['output']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```\n",
+ "{'message': {'role': 'assistant',\n",
+ " 'content': [{'toolUse': {'toolUseId': 'tooluse_YOMRWNbNQuCP-BR16tY6mw',\n",
+ " 'name': 'calculator', <---------------------------------------------- Claude wants to use the calculator tool\n",
+ " 'input': {'operand1': 1984135,\n",
+ " 'operand2': 9343116,\n",
+ " 'operation': 'multiply'}}}]}}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You might notice that our response looks a bit different that it normally does! Specifically, instead of a plain `Message` we're now getting a `ToolsMessage`.\n",
+ "\n",
+ "Additionally, we can check `response['stopReason']` and see that Claude stopped because it decided it was time to use a tool:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['stopReason']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`response['output']['message']['content']` contains a list containing a `ToolUseBlock` which itself contains information on the name of the tool and inputs:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['output']['message']['content'][-1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "tool_use = response['output']['message']['content'][-1]\n",
+ "tool_name = tool_use['toolUse']['name']\n",
+ "tool_inputs = tool_use['toolUse']['input']\n",
+ "\n",
+ "print(\"The Tool Name Claude Wants To Call:\", tool_name)\n",
+ "print(\"The Inputs Claude Wants To Call It With:\", tool_inputs)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The next step is to simply take the tool name and inputs that Claude provided us with and use them to actually call the calculator function we wrote earlier. Then we'll have our final answer! "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "operation = tool_inputs[\"operation\"]\n",
+ "operand1 = tool_inputs[\"operand1\"]\n",
+ "operand2 = tool_inputs[\"operand2\"]\n",
+ "\n",
+ "result = calculator(operation, operand1, operand2)\n",
+ "print(\"RESULT IS\", result)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We got the correct answer of `18538003464660`!!! Instead of relying on Claude to get the math correct, we simply ask Claude a question and give it access to a tool it can decide to use if necessary. \n",
+ "\n",
+ "#### Important note\n",
+ "If we ask Claude something that does not require tool use, in this case something that has nothing to do with math or calculations, we probably want it to respond as normal. Claude will usually do this, but sometimes Claude is very eager to use its tools! \n",
+ "\n",
+ "Here's an example where sometimes Claude tries to use the calculator even though it doesn't make sense to use it. Let's see what happens when we ask Claude, \"What color are emeralds?\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\":\"What color are emeralds?\"}]}],\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 400},\n",
+ " \"toolConfig\": toolConfig,\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['output']['message']['content']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude gives us this response: \n",
+ "\n",
+ "```\n",
+ "[{'toolUse': {'toolUseId': 'tooluse_PM0i2kehQnOq9gcRFa8QEg',\n",
+ " 'name': 'calculator',\n",
+ " 'input': {'operand1': 0, 'operand2': 0, 'operation': 'add'}}}]\n",
+ "\n",
+ "```\n",
+ "Claude wants us to call the calculator tool? A very easy fix is to adjust our prompt or add a system prompt that says something along the lines of: `You have access to tools, but only use them when necessary. If a tool is not required, respond as normal`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": \"You have access to tools, but only use them when necessary. If a tool is not required, respond as normal\"}],\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\":\"What color are emeralds?\"}]}],\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 400},\n",
+ " \"toolConfig\": toolConfig,\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['output']['message']['content'][0]['text']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now Claude responds back with appropriate content and doesn't try to shoehorn tool usage when it doesn't make sense. This is the new response we get: \n",
+ "\n",
+ "```\n",
+ "'Emeralds are green in color.'\n",
+ "```\n",
+ "\n",
+ "We can also see that `stopReason` is now `end_turn` instead of `tool_use`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['stopReason']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Putting it all together"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import re\n",
+ "import boto3\n",
+ "import json\n",
+ "from botocore.exceptions import ClientError\n",
+ "\n",
+ "\n",
+ "def calculator(operation, operand1, operand2):\n",
+ " if operation == \"add\":\n",
+ " return operand1 + operand2\n",
+ " elif operation == \"subtract\":\n",
+ " return operand1 - operand2\n",
+ " elif operation == \"multiply\":\n",
+ " return operand1 * operand2\n",
+ " elif operation == \"divide\":\n",
+ " if operand2 == 0:\n",
+ " raise ValueError(\"Cannot divide by zero.\")\n",
+ " return operand1 / operand2\n",
+ " else:\n",
+ " raise ValueError(f\"Unsupported operation: {operation}\")\n",
+ "\n",
+ "\n",
+ "toolConfig = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"calculator\",\n",
+ " \"description\": \"A simple calculator that performs basic arithmetic operations.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"operation\": {\n",
+ " \"type\": \"string\",\n",
+ " \"enum\": [\n",
+ " \"add\", \"subtract\", \"multiply\", \"divide\"],\n",
+ " \"description\": \"The arithmetic operation to perform.\"\n",
+ " },\n",
+ " \"operand1\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The first operand.\"\n",
+ " },\n",
+ " \"operand2\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The second operand.\"\n",
+ " }\n",
+ " },\n",
+ " \"required\": [\n",
+ " \"operation\", \"operand1\", \"operand2\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)\n",
+ "\n",
+ "\n",
+ "def prompt_claude(prompt):\n",
+ "\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": \"You have access to tools, but only use them when necessary. If a tool is not required, respond as normal\"}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 400},\n",
+ " \"toolConfig\": toolConfig,\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " if response['stopReason'] == \"tool_use\":\n",
+ " tool_use = response['output']['message']['content'][-1]\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_inputs = tool_use['toolUse']['input']\n",
+ "\n",
+ " if tool_name == \"calculator\":\n",
+ " print(\"Claude wants to use the calculator tool\")\n",
+ " operation = tool_inputs[\"operation\"]\n",
+ " operand1 = tool_inputs[\"operand1\"]\n",
+ " operand2 = tool_inputs[\"operand2\"]\n",
+ "\n",
+ " try:\n",
+ " result = calculator(operation, operand1, operand2)\n",
+ " print(\"Calculation result is:\", result)\n",
+ " except ValueError as e:\n",
+ " print(f\"Error: {str(e)}\")\n",
+ "\n",
+ " elif response['stopReason'] == \"end_turn\":\n",
+ " print(\"Claude didn't want to use a tool\")\n",
+ " print(\"Claude responded with:\")\n",
+ " print(response['output']['message']['content'][0]['text'])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "prompt_claude(\"I had 23 chickens but 2 flew away. How many are left?\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "prompt_claude(\"What is 201 times 2\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "prompt_claude(\"Write me a haiku about the ocean\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "*** "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercise\n",
+ "\n",
+ "Your task is to help build out a research assistant using Claude. A user can enter a topic that they want to research and get a list of Wikipedia article links saved to a markdown file for later reading. We could try asking Claude directly to generate a list of article URLs, but Claude is unreliable with URLs and may hallucinate article URLs. Also, legitimate articles might have moved to a new URL after Claude's training cutoff date. Instead, we're going to use a tool that connects to the real Wikipedia API to make this work! \n",
+ "\n",
+ "We'll provide Claude with access to a tool that accepts a list of possible Wikipedia article titles that Claude has generated but could have hallucinated. We can use this tool to search Wikipedia to find the actual Wikipedia article titles and URLs to ensure that the final list consists of articles that all actually exist. We’ll then save these article URLs to a markdown file for later reading.\n",
+ "\n",
+ "We've provided you with two functions to help:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import wikipedia\n",
+ "def generate_wikipedia_reading_list(research_topic, article_titles):\n",
+ " wikipedia_articles = []\n",
+ " for t in article_titles:\n",
+ " results = wikipedia.search(t)\n",
+ " try:\n",
+ " page = wikipedia.page(results[0])\n",
+ " title = page.title\n",
+ " url = page.url\n",
+ " wikipedia_articles.append({\"title\": title, \"url\": url})\n",
+ " except:\n",
+ " continue\n",
+ " add_to_research_reading_file(wikipedia_articles, research_topic)\n",
+ "\n",
+ "def add_to_research_reading_file(articles, topic):\n",
+ " with open(\"output/research_reading.md\", \"a\", encoding=\"utf-8\") as file:\n",
+ " file.write(f\"## {topic} \\n\")\n",
+ " for article in articles:\n",
+ " title = article[\"title\"]\n",
+ " url = article[\"url\"]\n",
+ " file.write(f\"* [{title}]({url}) \\n\")\n",
+ " file.write(f\"\\n\\n\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The first function, `generate_wikipedia_reading_list` expects to be passed a research topic like \"The history of Hawaii\" or \"Pirates across the world\" and a list of potential Wikipedia article names that we will have Claude generate. The function uses the `wikipedia` package to search for corresponding REAL wikipedia pages and builds a list of dictionaries that contain an article's title and URL.\n",
+ "\n",
+ "Then it calls `add_to_research_reading_file`, passing in the list of Wikipedia article data and the overall research topic. This function simply adds markdown links to each of the Wikipedia articles to a file called `output/research_reading.md`. The filename is hardcoded for now, and the function assumes it exists. It exists in this repo, but you'll need to create it yourself if working somewhere else.\n",
+ "\n",
+ "The idea is that we'll have Claude \"call\" `generate_wikipedia_reading_list` with a list of potential article titles that may or may not be real. Claude might pass the following input list of article titles, some of which are real Wikipedia articles and some of which are not:\n",
+ "\n",
+ "```py\n",
+ "[\"Piracy\", \"Famous Pirate Ships\", \"Golden Age Of Piracy\", \"List of Pirates\", \"Pirates and Parrots\", \"Piracy in the 21st Century\"]\n",
+ "```\n",
+ "\n",
+ "The `generate_wikipedia_reading_list` function goes through each of those article titles and collects the real article titles and corresponding URLs for any Wikipedia articles that actually exist. It then calls `add_to_research_reading_file` to write that content to a markdown file for later reference."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### The end goal\n",
+ "\n",
+ "Your job is to implement a function called `get_research_help` that accepts a research topic and a desired number of articles. This function should use Claude to actually generate the list of possible Wikipedia articles and call the `generate_wikipedia_reading_list` function from above. Here are a few example function calls:\n",
+ "\n",
+ "```py\n",
+ "get_research_help(\"Pirates Across The World\", 7)\n",
+ "\n",
+ "get_research_help(\"History of Hawaii\", 3)\n",
+ "\n",
+ "get_research_help(\"are animals conscious?\", 3)\n",
+ "```\n",
+ "\n",
+ "After these 3 function calls, this is what our output `research_reading.md` file looks like (check it out for yourself in output/research_reading.md): \n",
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "To accomplish this, you'll need to do the following: \n",
+ "\n",
+ "* Write a tool definition for the `generate_wikipedia_reading_list` function\n",
+ "* Implement the `get_research_help` function\n",
+ " * Write a prompt to Claude telling it that you need help gathering research on the specific topic and how many article titles you want it to generate\n",
+ " * Tell Claude about the tool it has access to\n",
+ " * Send off your request to Claude\n",
+ " * Check to see if Claude called the tool. If it did, you'll need to pass the article titles and topic it generated to the `generate_wikipedia_reading_list` function we gave you. That function will gather actual Wikipedia article links and then call `add_to_research_reading_file` to write the links to `output/research_reading.md`\n",
+ " * Open `output/research_reading.md` to see if it worked!\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "##### Starter Code"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "# Here's your starter code!\n",
+ "import wikipedia\n",
+ "def generate_wikipedia_reading_list(research_topic, article_titles):\n",
+ " wikipedia_articles = []\n",
+ " for t in article_titles:\n",
+ " results = wikipedia.search(t)\n",
+ " try:\n",
+ " page = wikipedia.page(results[0])\n",
+ " title = page.title\n",
+ " url = page.url\n",
+ " wikipedia_articles.append({\"title\": title, \"url\": url})\n",
+ " except:\n",
+ " continue\n",
+ " add_to_research_reading_file(wikipedia_articles, research_topic)\n",
+ "\n",
+ "def add_to_research_reading_file(articles, topic):\n",
+ " with open(\"output/research_reading.md\", \"a\", encoding=\"utf-8\") as file:\n",
+ " file.write(f\"## {topic} \\n\")\n",
+ " for article in articles:\n",
+ " title = article[\"title\"]\n",
+ " url = article[\"url\"]\n",
+ " file.write(f\"* [{title}]({url}) \\n\")\n",
+ " file.write(f\"\\n\\n\")\n",
+ " \n",
+ "def get_research_help(topic, num_articles=3):\n",
+ " #Implement this function! \n",
+ " pass"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/AmazonBedrock/10_2_2_Tool_Use_for_Structured_Outputs.ipynb b/AmazonBedrock/10_2_2_Tool_Use_for_Structured_Outputs.ipynb
new file mode 100755
index 0000000..b1b09d4
--- /dev/null
+++ b/AmazonBedrock/10_2_2_Tool_Use_for_Structured_Outputs.ipynb
@@ -0,0 +1,850 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Appendix 10.2.2: Forcing JSON with tool use\n",
+ "\n",
+ "## Learning goals\n",
+ "\n",
+ "* Understand using tools to force a structured response\n",
+ "* Utilize this \"trick\" to generate structured JSON\n",
+ "\n",
+ "One of the more interesting ways of utilizing tool use is in forcing Claude to respond with structured content like JSON. There are many situations in which we may want to get a standardized JSON response from Claude: extracting entities, summarizing data, analyzing sentiment, etc. \n",
+ "\n",
+ "One way of doing this is simply asking Claude to respond with JSON, but this can require additional work to actually extract the JSON from the big string we get back from Claude or to make sure the JSON follows the exact format we want.\n",
+ "\n",
+ "The good news is that **whenever Claude wants to use a tool, it already responds using the perfectly structured format we told it to use when we defined the tool.**\n",
+ "\n",
+ "In the previous lesson, we gave Claude a calculator tool. When it wanted to use the tool, it responded with content like this: \n",
+ "\n",
+ "```\n",
+ "{\n",
+ " 'operand1': 1984135, \n",
+ " 'operand2': 9343116, \n",
+ " 'operation': 'multiply'\n",
+ "}\n",
+ "```\n",
+ "\n",
+ "That looks suspiciously similar to JSON! \n",
+ "\n",
+ "If we want Claude to generate structured JSON, we can use this to our advantage. All we have to do is define a tool that describes a particular JSON structure and then tell Claude about it. That's it. Claude will respond back, thinking it's \"calling a tool\" but really all we care about is the structured response it gives us."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Conceptual overview\n",
+ "\n",
+ "How is this different than what we did in the previous lesson? Here's a diagram of the workflow from the last lesson: \n",
+ "\n",
+ "\n",
+ "\n",
+ "In the last lesson, we gave Claude access to a tool, Claude wanted to call it, and then we actually called the underlying tool function.\n",
+ "\n",
+ "In this lesson, we're going to \"trick\" Claude by telling it about a particular tool, but we won't need to actually call the underlying tool function. We're using the tool as a way of forcing a particular structure of response, as seen in this diagram:\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Sentiment analysis\n",
+ "Let's start with a simple example. Suppose we want Claude to analyze the sentiment in some text and respond with a JSON object that follows this shape: \n",
+ "\n",
+ "```\n",
+ "{\n",
+ " \"negative_score\": 0.6,\n",
+ " \"neutral_score\": 0.3,\n",
+ " \"positive_score\": 0.1\n",
+ "}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "All we have to do is define a tool that captures this shape using JSON Schema. Here's a potential implementation: "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "%pip install -qU pip\n",
+ "%pip install -qUr requirements.txt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import boto3\n",
+ "import json\n",
+ "from datetime import datetime\n",
+ "from botocore.exceptions import ClientError\n",
+ "\n",
+ "# Import the hints module from the utils package\n",
+ "from utils import hints\n",
+ "\n",
+ "session = boto3.Session()\n",
+ "region = session.region_name"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
+ "#modelId = 'anthropic.claude-3-haiku-20240307-v1:0'\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "tools = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"print_sentiment_scores\",\n",
+ " \"description\": \"Prints the sentiment scores of a given text.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"positive_score\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The positive sentiment score, ranging from 0.0 to 1.0.\"},\n",
+ " \"negative_score\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The negative sentiment score, ranging from 0.0 to 1.0.\"},\n",
+ " \"neutral_score\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The neutral sentiment score, ranging from 0.0 to 1.0.\"}\n",
+ " },\n",
+ " \"required\": [\"positive_score\", \"negative_score\", \"neutral_score\"\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we can tell Claude about this tool and explicitly tell Claude to use it, to ensure that it actually does use it. We should get a response telling us that Claude wants to use a tool. The tool use response should contain all the data in the exact format we want."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "tweet = \"I'm a HUGE hater of pickles. I actually despise pickles. They are garbage.\"\n",
+ "\n",
+ "query = f\"\"\"\n",
+ "\n",
+ "{tweet}\n",
+ "\n",
+ "\n",
+ "Only use the print_sentiment_scores tool.\n",
+ "\"\"\"\n",
+ "\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": query}]}],\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 400},\n",
+ " \"toolConfig\": tools,\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['output']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's take a look at the response we get back from Claude. We've bolded the important part:\n",
+ "\n",
+ ">{'message': {'role': 'assistant',\n",
+ " 'content': [{'text': 'Here is the sentiment analysis for the given text:'},\n",
+ " {'toolUse': {'toolUseId': 'tooluse_d2ReNcjDQvKjLLet4u9EOA',\n",
+ " 'name': 'print_sentiment_scores',\n",
+ " **'input': {'positive_score': 0.0,\n",
+ " 'negative_score': 0.7,\n",
+ " 'neutral_score': 0.3}**}}]}}\n",
+ "\n",
+ "Claude \"thinks\" it's calling a tool that will use this sentiment analysis data, but really we're just going to extract the data and turn it into JSON:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "json_sentiment = None\n",
+ "for content in response['output']['message']['content']:\n",
+ " if isinstance(content, dict) and 'toolUse' in content:\n",
+ " tool_use = content['toolUse']\n",
+ " if tool_use['name'] == \"print_sentiment_scores\":\n",
+ " json_sentiment = tool_use['input']\n",
+ " break\n",
+ "\n",
+ "if json_sentiment:\n",
+ " print(\"Sentiment Analysis (JSON):\")\n",
+ " print(json.dumps(json_sentiment, indent=2))\n",
+ "else:\n",
+ " print(\"No sentiment analysis found in the response.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It works! Now let's turn that into a reusable function that takes a tweet or article and then prints or returns the sentiment analysis as JSON."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def analyze_sentiment(content):\n",
+ "\n",
+ " query = f\"\"\"\n",
+ " \n",
+ " {content}\n",
+ " \n",
+ "\n",
+ " Only use the print_sentiment_scores tool.\n",
+ " \"\"\"\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": query}]}],\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": tools,\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " json_sentiment = None\n",
+ " for content in response['output']['message']['content']:\n",
+ " if isinstance(content, dict) and 'toolUse' in content:\n",
+ " tool_use = content['toolUse']\n",
+ " if tool_use['name'] == \"print_sentiment_scores\":\n",
+ " json_sentiment = tool_use['input']\n",
+ " break\n",
+ "\n",
+ " if json_sentiment:\n",
+ " print(\"Sentiment Analysis (JSON):\")\n",
+ " print(json.dumps(json_sentiment, indent=2))\n",
+ " else:\n",
+ " print(\"No sentiment analysis found in the response.\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "analyze_sentiment(\"OMG I absolutely love taking bubble baths soooo much!!!!\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "analyze_sentiment(\"Honestly I have no opinion on taking baths\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Forcing tool use with `toolChoice` \n",
+ "\n",
+ "Currently we're \"forcing\" Claude to use our `print_sentiment_scores` tool through prompting. In our prompt, we write `Only use the print_sentiment_scores tool.` which usually works, but there's a better way! We can actually force Claude to use a specific tool using the `tool_choice` parameter:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "```json\n",
+ "tool_choice = {\n",
+ " \"tool\": {\n",
+ " \"name\": \"print_sentiment_scores\"}\n",
+ "}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The above code tells Claude that it must respond by calling the `print_sentiment_scores` tool. Let's update our tools and function to use it:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# create out toolConfig var and force the toolChoice to be print_sentiment_scores by name\n",
+ "toolConfig = {'tools': [],\n",
+ " \"toolChoice\": {\n",
+ " \"tool\": {\"name\":\"print_sentiment_scores\"},\n",
+ " }\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# append our tool specification to our toolConfig\n",
+ "toolConfig['tools'].append({\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"print_sentiment_scores\",\n",
+ " \"description\": \"Prints the sentiment scores of a given text.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"positive_score\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The positive sentiment score, ranging from 0.0 to 1.0.\"},\n",
+ " \"negative_score\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The negative sentiment score, ranging from 0.0 to 1.0.\"},\n",
+ " \"neutral_score\": {\n",
+ " \"type\": \"number\",\n",
+ " \"description\": \"The neutral sentiment score, ranging from 0.0 to 1.0.\"}\n",
+ " },\n",
+ " \"required\": [\"positive_score\", \"negative_score\", \"neutral_score\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " })"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "# optional uncomment if you want to see the complete toolConfig\n",
+ "#toolConfig"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def analyze_sentiment(content):\n",
+ "\n",
+ " query = f\"\"\"\n",
+ " \n",
+ " {content}\n",
+ " \n",
+ "\n",
+ " Only use the print_sentiment_scores tool.\n",
+ " \"\"\"\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": query}]}],\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": toolConfig\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " json_sentiment = None\n",
+ " for content in response['output']['message']['content']:\n",
+ " if isinstance(content, dict) and 'toolUse' in content:\n",
+ " tool_use = content['toolUse']\n",
+ " if tool_use['name'] == \"print_sentiment_scores\":\n",
+ " json_sentiment = tool_use['input']\n",
+ " break\n",
+ "\n",
+ " if json_sentiment:\n",
+ " print(\"Sentiment Analysis (JSON):\")\n",
+ " print(json.dumps(json_sentiment, indent=2))\n",
+ " else:\n",
+ " print(\"No sentiment analysis found in the response.\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "analyze_sentiment(\"Honestly I have no opinion on taking baths\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We'll cover `toolChoice` in greater detail in an upcoming lesson."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Entity extraction example\n",
+ "\n",
+ "Let's use this same approach to get Claude to generate nicely formatted JSON that contains entities like people, organizations, and locations extracted from a text sample:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "toolConfig = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"print_entities\",\n",
+ " \"description\": \"Prints extract named entities.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"entities\": {\n",
+ " \"type\": \"array\",\n",
+ " \"items\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"name\": {\"type\": \"string\", \"description\": \"The extracted entity name.\"},\n",
+ " \"type\": {\"type\": \"string\", \"description\": \"The entity type (e.g., PERSON, ORGANIZATION, LOCATION).\"},\n",
+ " \"context\": {\"type\": \"string\", \"description\": \"The context in which the entity appears in the text.\"}\n",
+ " },\n",
+ " \"required\": [\"name\", \"type\", \"context\"]\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " \"required\": [\"entities\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "\n",
+ "text = \"John works at Google in New York. He met with Sarah, the CEO of Acme Inc., last week in San Francisco.\"\n",
+ "\n",
+ "query = f\"\"\"\n",
+ "\n",
+ "{text}\n",
+ "\n",
+ "\n",
+ "Use the print_entities tool.\n",
+ "\"\"\"\n",
+ "\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": query}]}],\n",
+ " \"additionalModelRequestFields\": {\"max_tokens\": 4096},\n",
+ " \"toolConfig\": toolConfig\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ "\n",
+ "json_entities = None\n",
+ "for content in response['output']['message']['content']:\n",
+ " if isinstance(content, dict) and 'toolUse' in content:\n",
+ " tool_use = content['toolUse']\n",
+ " if tool_use['name'] == \"print_entities\":\n",
+ " json_entities = tool_use['input']\n",
+ " break\n",
+ "\n",
+ "if json_entities:\n",
+ " print(\"Extracted Entities (JSON):\")\n",
+ " print(json.dumps(json_entities, indent=2))\n",
+ "else:\n",
+ " print(\"No entities found in the response.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We're using the same \"trick\" as before. We tell Claude it has access to a tool as a way of getting Claude to respond with a particular data format. Then we extract the formatted data Claude responded with, and we're good to go. \n",
+ "\n",
+ "Remember that in this use case, it helps to explicitly tell Claude we want it to use a given tool:\n",
+ "\n",
+ "\n",
+ ">Use the print_entities tool.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Wikipedia summary example with more complex data\n",
+ "\n",
+ "Let's try another example that's a little more complex. We'll use the Python `wikipedia` package to get entire Wikipedia page articles and pass them to Claude. We'll use Claude to generate a response that includes:\n",
+ "\n",
+ "* The main subject of the article\n",
+ "* A summary of the article\n",
+ "* A list of keywords and topics mentioned in the article\n",
+ "* A list of category classifications for the article (entertainment, politics, business, etc.) along with a classification score (i.e., how strongly the topic falls into that category)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "If we passed Claude the Wikipedia article about Walt Disney, we might expect a result like this: \n",
+ "\n",
+ "```json\n",
+ "{\n",
+ " \"subject\": \"Walt Disney\",\n",
+ " \"summary\": \"Walter Elias Disney was an American animator, film producer, and entrepreneur. He was a pioneer of the American animation industry and introduced several developments in the production of cartoons. He held the record for most Academy Awards earned and nominations by an individual. He was also involved in the development of Disneyland and other theme parks, as well as television programs.\",\n",
+ " \"keywords\": [\n",
+ " \"Walt Disney\",\n",
+ " \"animation\",\n",
+ " \"film producer\",\n",
+ " \"entrepreneur\",\n",
+ " \"Disneyland\",\n",
+ " \"theme parks\",\n",
+ " \"television\"\n",
+ " ],\n",
+ " \"categories\": [\n",
+ " {\n",
+ " \"name\": \"Entertainment\",\n",
+ " \"score\": 0.9\n",
+ " },\n",
+ " {\n",
+ " \"name\": \"Business\",\n",
+ " \"score\": 0.7\n",
+ " },\n",
+ " {\n",
+ " \"name\": \"Technology\",\n",
+ " \"score\": 0.6\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's an example implementation of a function that expects a Wikipedia page subject, finds the article, downloads the contents, passes it to Claude, and then prints out the resulting JSON data. We use the same strategy of defining a tool to \"coach\" the shape of Claude's response.\n",
+ "\n",
+ "Note: make sure to `pip install wikipedia` if you don't have it on your machine!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import wikipedia\n",
+ "\n",
+ "#tool definition\n",
+ "toolConfig = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"print_article_classification\",\n",
+ " \"description\": \"Prints the classification results.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"subject\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The overall subject of the article\"},\n",
+ " \"summary\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"A paragaph summary of the article\"},\n",
+ " \"keywords\": {\n",
+ " \"type\": \"array\",\n",
+ " \"items\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"List of keywords and topics in the article\"}\n",
+ " },\n",
+ " \"categories\": {\n",
+ " \"type\": \"array\",\n",
+ " \"items\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"name\": {\"type\": \"string\", \"description\": \"The category name.\"},\n",
+ " \"score\": {\"type\": \"number\", \"description\": \"The classification score for the category, ranging from 0.0 to 1.0.\"}\n",
+ " },\n",
+ " \"required\": [\"name\", \"score\"]\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " \"required\": [\"subject\", \"summary\", \"keywords\", \"categories\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "\n",
+ "#The function that generates the json for a given article subject\n",
+ "def generate_json_for_article(subject):\n",
+ " page = wikipedia.page(subject, auto_suggest=True)\n",
+ " query = f\"\"\"\n",
+ " \n",
+ " {page.content}\n",
+ " \n",
+ "\n",
+ " Use the print_article_classification tool. Example categories are Politics, Sports, Technology, Entertainment, Business.\n",
+ " \"\"\"\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": query}]}],\n",
+ " \"additionalModelRequestFields\": {\"max_tokens\": 4096},\n",
+ " \"toolConfig\": toolConfig\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " json_classification = None\n",
+ " for content in response['output']['message']['content']:\n",
+ " if isinstance(content, dict) and 'toolUse' in content:\n",
+ " tool_use = content['toolUse']\n",
+ " if tool_use['name'] == \"print_article_classification\":\n",
+ " json_classification = tool_use['input']\n",
+ " break\n",
+ "\n",
+ " if json_classification:\n",
+ " print(\"Text Classification (JSON):\")\n",
+ " print(json.dumps(json_classification, indent=2))\n",
+ " else:\n",
+ " print(\"No text classification found in the response.\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "generate_json_for_article(\"Jeff Goldblum\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "generate_json_for_article(\"Octopus\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "generate_json_for_article(\"Herbert Hoover\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercise\n",
+ "\n",
+ "Use the above strategy to write a function called `translate` that takes a word or phrase and generates a structured JSON output that includes the original phrase in English and the translated phrase in Spanish, French, Japanese, and Arabic.\n",
+ "\n",
+ "Here is an example of how this should work:\n",
+ "\n",
+ "If we call this:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "translate(\"how much does this cost\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We expect an output like this: \n",
+ "\n",
+ "```json\n",
+ "{\n",
+ " \"english\": \"how much does this cost\",\n",
+ " \"spanish\": \"¿cuánto cuesta esto?\",\n",
+ " \"french\": \"combien ça coûte?\",\n",
+ " \"japanese\": \"これはいくらですか\",\n",
+ " \"arabic\": \"كم تكلفة هذا؟\"\n",
+ "}\n",
+ "```\n",
+ "\n",
+ "**NOTE: If you want to print your results, this line of code will help you print them out nicely:**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "print(json.dumps(translations_from_claude, ensure_ascii=False, indent=2))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/AmazonBedrock/10_2_3_Complete_Tool_Use_Workflow.ipynb b/AmazonBedrock/10_2_3_Complete_Tool_Use_Workflow.ipynb
new file mode 100755
index 0000000..8f4b01d
--- /dev/null
+++ b/AmazonBedrock/10_2_3_Complete_Tool_Use_Workflow.ipynb
@@ -0,0 +1,1018 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Appendix 10.2.3: The complete tool use workflow\n",
+ "\n",
+ "## Learning goals\n",
+ "\n",
+ "* Understand the entire tool use workflow\n",
+ "* Write properly structured `tool_result` messages\n",
+ "* Implement a chatbot that utilizes tool use\n",
+ "\n",
+ "In this lesson, we're going to implement the \"full\" 4-step tool use workflow we covered earlier. So far, we've seen that Claude has used tools, but we haven't sent follow up requests to Claude that contain the result of our tool functionality. Here's a recap of the full 4-step process: \n",
+ "\n",
+ "1. **Provide Claude with tools and a user prompt:** (API request)\n",
+ " * Define the set of tools you want Claude to have access to, including their names, descriptions, and input schemas.\n",
+ " * Provide a user prompt that may require the use of one or more of these tools to answer, such as \"How many shares of General Motors can I buy with $500?\"\n",
+ "\n",
+ "2. **Claude uses a tool:** (API response)\n",
+ " * Claude assesses the user prompt and decides whether any of the available tools would help with the user's query or task. If so, it also decides which tool(s) to use and with what input(s).\n",
+ " * Claude outputs a properly formatted tool use request.\n",
+ " * The API response will have a `stop_reason` of `tool_use`, indicating that Claude wants to use an external tool.\n",
+ "\n",
+ "3. **Extract tool input(s), run code, and return results:** (API request)\n",
+ " * On the client side, you should extract the tool name and input from Claude's tool use request.\n",
+ " * Run the actual tool code on the client side.\n",
+ " * Return the results to Claude by continuing the conversation with a new user message containing a `tool_result` content block.\n",
+ "\n",
+ "4. **Claude uses the tool result to formulate a response:** (API response)\n",
+ " * After receiving the tool results, Claude will use that information to formulate its final response to the original user prompt.\n",
+ "\n",
+ "In this lesson, we'll go through the entire process. \n",
+ "\n",
+ "Here's a diagram with a general overview of the process:\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "attachments": {
+ "wikipedia_diagram.png": {
+ "image/png": "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AAAAAAAAmBDAAAAAAAAAABMCGAAAAAAAAGBCAAMAAAAAAABMCGAAAAAAAACACQEMAAAAAAAAMCGAAQAAAAAAACYEMAAAAAAAAMCEAAYAAAAAAACYEMAAAAAAAAAAEwIYAAAAAAAAYEIAAwAAAAAAAEwIYAAAAAAAAIAJAQwAAAAAAAAwIYABAAAAAAAAJgQwAAAAAAAAwIQABgAAAAAAAJgQwAAAAAAAAAATAhgAAAAAAABgQgADAAAAAAAATAhgAAAAAAAAgAkBDAAAAAAAADAhgAEAAAAAAAAmBDAAAAAAAADAhAAGAAAAAAAAmBDAAAAAAAAAABMCGAAAAAAAAGAiAAAA///s3XlcVXX+x/EXiySk4ZqAiNloKiI2peVKKqij1pSm5VIzZk1lm5nrtD1mRm0mLff6leOSW6WVSy6oqU2amogbwxaLilwQBQRF4Qpc+P2B3BG5IBJwEN7Px4PH43rO937P+8C9Fzyf8/1+VQAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhVAAWEREREREREREREREREakhHI0OICIiIgXMZjNHjx4l3mTCFG/ClJCAyWQiIcFEcnKKtV3Tpk3w9GxB8+bNaeHpiWcLT7xaeNG168MGphcRERERERERERGR6sAu+2pWvtEhREREaqu0tDR27drN7j272b//AGazudx9ubi44OfXiwD/AHr37o2r610VmFREREREREREREREbgcqAIuIiBhg1erVbN68hWPHjlXaMR566CGeePxxhg8fVmnHEBEREREREREREZHqRQVgERGRKpKXl8fGTZtYsGABCQmJVXbcVvfcw8SJb9G/f3/s7Oyq7LgiIiIiIiIiIiIiUvVUABYREakCu3fvYc7cOURFRRuWoaOPD5Mm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2FdXhf6mU1EYEREREREREREREREgaGIgaISQ1vW4XBM8msAEQYAQExPSutEc5+kgRq+HPjFFdZkmxO9gqtGZElSP2WHui8JoiEaHAWCiKEiZtQDzbv+u6rLOzz5F2cZHIjwiIiIiIiIiIiIiIsmcr3wT2StWh7Tu0f97Gi0f75jgEalb9M2fIHXO4hHXc9mt2PnNGyMwIiKiyYE9gImiIG/VuoDLUuctgTEzJ4KjISIiIiIiIiIiIhqbnJVrorJfQ1omUmYtiMq+iYgmOwaAiSJMn5SC9EXLAy4XNDFBA8REREREREREREREk0XyzAUwZmRHfL+5514EQXN6lh4mIgoXA8BEEZa3ah00On3QdbJXnD/iOkRERERERERENDYNDQ04UVkJh8MR7aEQTXmCRoPccy6K+H6zlq2K+D6JiKYK9gAmiiBBEJCz8oIR19MnJiNr2Xlo3vN+BEZFRERERERERPT58O677+H5F16AzWZT/u3Sdetwyy23ICUlOYojI5raspavwsk3/hix/aXNOyMqWcdERFMFM4CJIihjyUoY0jJDWjf33Mi/NUdEREREREREdLp67LHH8eRTT/kEfwHgna1bcff69di/f3+URkY09RnSMpG+cFnE9pdz9oUR2xcR0VTEADBRBOWed3HI6yaVzEZC4fQJHA0RERERERER0edDeXk5tu/YEXB5T08PHnjwIfzmpd/C4/FEcGREp49QKh+OB50pHmkBgs0elzMiYyAimuwYACaKkLjsfKTMXhT6BoKA/NWXTtyAiIiIiIiIiIg+J1597fUR1xFFEZs3b8b3770P7e3tERgV0dTjMPfC2W9RXZa24EzoE5ImfAzZKy9AjD7W799ddit6q49P+P6JiKYCBoCJIiT//EshaEZ3yWUsPRvauPgJGhERERERERER0edDd3d3yOseOXIEd6+/B3v27p3AERFNTaLbhfYDe1SXaXT6iJRmzl5+vuq/dxzaB49jYML3T0Q0FTAATBQBGp0eWctWqS6zd7bB2tqkukxriGMvYCIiIiIiIiKiCLNYLHj44Uew8blNcLlc0R4O0aTStPu9gMuylq+e0H0nFE5HQmGp6rLm3f+a0H0TEU0lDAATRUDOyjXQxSeqLmveux0te7cH3jYCb80REREREREREZG/t956C9/+znfQ3Nwc7aEQTRp9NSdgrjupuiw+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AAAAkBECMAAAAAAAAEBGCMAAAAAAAAAAGSEAAwAAAAAAAGSEAAwAAAAAAACQEQIwAAAAAAAAQEYIwAAAAAAAAAAZIQADAAAAAAAAZIQADAAAAAAAAJARAjAAAAAAAABARgjAAAAAAAAAABkhAAMAAAAAAABkxF8AAAD//+3ZgQwAAADAIH/re3ylkQAGAAAAAAAAmBDAAAAAAAAAABMCGAAAAAAAAGBCAAMAAAAAAABMCGAAAAAAAACACQEMAAAAAAAAMCGAAQAAAAAAACYEMAAAAAAAAMCEAAYAAAAAAACYEMAAAAAAAAAAEwIYAAAAAAAAYEIAAwAAAAAAAEwIYAAAAAAAAIAJAQwAAAAAAAAwIYABAAAAAAAAJgQwAAAAAAAAwIQABgAAAAAAAJgQwAAAAAAAAAATAhgAAAAAAABgQgADAAAAAAAATAhgAAAAAAAAgAkBDAAAAAAAADAhgAEAAAAAAAAmBDAAAAAAAADAhAAGAAAAAAAAmBDAAAAAAAAAABMCGAAAAAAAAGBCAAMAAAAAAABMCGAAAAAAAACACQEMAAAAAAAAMCGAAQAAAAAAACYEMAAAAAAAAMCEAAYAAAAAAACYEMAAAAAAAAAAEwIYAAAAAAAAYCJOIPJhXAha8QAAAABJRU5ErkJggg=="
+ }
+ },
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a diagram explaining how our script will work: \n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "Here are some real exchanges that illustrate the end result we're hoping to achieve: \n",
+ "\n",
+ "> **User**: As of 2024 who has more oscars, Christopher Nolan or Ben Stiller?\n",
+ "\n",
+ "> *Claude wants to get an article for Christopher Nolan* (tool use)\n",
+ "\n",
+ "> *Claude wants to get an article for Ben Stiller* (tool use)\n",
+ "\n",
+ "> **Claude**: As of 2024, filmmaker Christopher Nolan has won 2 Academy Awards for Best Director and Best Picture for his 2023 film Oppenheimer. On the other hand, actor and comedian Ben Stiller has not won any Oscars in his career so far, although he has won other awards like Emmys and MTV Movie Awards. So to directly answer the question, as of 2024, Christopher Nolan has won more Oscars (2) than Ben Stiller, who has not won any.\n",
+ "\n",
+ "Here's another example:\n",
+ "\n",
+ "> **User:** Who won the 2024 Masters Tournament?\n",
+ "\n",
+ "> *Claude wants to get an article for 2024 Masters Tournament* (tool use)\n",
+ "\n",
+ "> **Claude:** Scottie Scheffler won the 2024 Masters Tournament, his second Masters victory. He finished four strokes ahead of runner-up Ludvig Åberg, who was making his debut at the Masters.\n",
+ "\n",
+ "If we ask Claude a question that it can answer without needing to use our tool, it should just answer immediately without using our Wikipedia search tool:\n",
+ "\n",
+ "> **User:** Who won the 2021 Masters?\n",
+ "\n",
+ "> **Claude:** Hideki Matsuyama won the 2021 Masters Tournament, becoming the first Japanese man to win a major golf championship. He finished with a score of 278 (-10) to claim the green jacket at Augusta National Golf Club.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a look at what the `messages` list looks like by the end of this process:\n",
+ "\n",
+ "\n",
+ "\n",
+ "The main new topic in this lesson is how to properly format our `tool_result` user message when responding to Claude's `tool_use` message."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Building the complete workflow\n",
+ "\n",
+ "### 1. Defining our Wikipedia search function\n",
+ "\n",
+ "Before we do anything with Claude, let's write a simple function to search Wikipedia. The following function uses the `wikipedia` package to search for matching wikipedia pages based on a search term. To keep things simple, we take the first returned page title and then use that to access the corresponding page content.\n",
+ "\n",
+ "Note: this simple function assumes we find a Wikipedia article. To keep things brief, the function has no error handling which is not a great idea in the real world!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import boto3\n",
+ "import json\n",
+ "from datetime import datetime\n",
+ "from botocore.exceptions import ClientError\n",
+ "\n",
+ "# Import the hints module from the utils package\n",
+ "from utils import hints\n",
+ "\n",
+ "session = boto3.Session()\n",
+ "region = session.region_name\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import wikipedia\n",
+ "\n",
+ "def get_article(search_term):\n",
+ " results = wikipedia.search(search_term)\n",
+ " first_result = results[0]\n",
+ " page = wikipedia.page(first_result, auto_suggest=False)\n",
+ " return page.content"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "article = get_article(\"Superman\")\n",
+ "print(article[:500]) # article is very long, so let's just print a preview"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "article = get_article(\"Zendaya\")\n",
+ "print(article[:500]) # article is very long, so let's just print a preview"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2. Writing the tool definition\n",
+ "Next up, we need to define our tool using the proper JSON Schema format. This is a very simple tool definition because the function expects a single argument: the search term string. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "toolConfig = {\n",
+ " \"tools\": [\n",
+ " {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"get_article\",\n",
+ " \"description\": \"A tool to retrieve an up to date Wikipedia article.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"search_term\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The search term to find a wikipedia article by title\"\n",
+ " }\n",
+ " },\n",
+ " \"required\": [\"search_term\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3. Provide Claude with the tool and user prompt\n",
+ "\n",
+ "Next, we'll tell Claude it has access to the Wikipedia search tool and ask it to answer a question we know it cannot answer without the tool, like \"Who won the 2024 Masters Tournament?\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "modelId = \"anthropic.claude-3-sonnet-20240229-v1:0\"\n",
+ "messages = [{\"role\": \"user\", \"content\": [{\"text\": \"who won the 2024 Masters Tournament?\"}]}]\n",
+ "\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": toolConfig\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4. Claude uses the tool (API response)\n",
+ "\n",
+ "Let's look at the response we got back. Claude wants to use our tool!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response['output']['message']['content']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude's response contains 2 blocks: \n",
+ "\n",
+ "* A `text` value with the text \"Okay, let me use the available tool to try and find information on who won the 2024 Masters Tournament on Wikipedia:\"\n",
+ "\n",
+ "```\n",
+ "[{'text': 'Okay, let me search Wikipedia for information on the 2024 Masters Tournament winner:'},\n",
+ " {'toolUse': {'toolUseId': 'tooluse_8kC2QECHRYePqW0BS96_9Q',\n",
+ " 'name': 'get_article',\n",
+ " 'input': {'search_term': '2024 Masters Tournament'}}}]\n",
+ "```\n",
+ "\n",
+ "* A `toolUse` value calling our `get_article` tool with the `search_term` \"2024 Masters Tournament\"\n",
+ "\n",
+ "```\n",
+ "{'toolUse': {'toolUseId': 'tooluse_8kC2QECHRYePqW0BS96_9Q',\n",
+ " 'name': 'get_article',\n",
+ " 'input': {'search_term': '2024 Masters Tournament'}}}\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 5. Extract tool input(s), run code, and return results (API request)\n",
+ "\n",
+ "Now that Claude has responded telling us it wants to use a tool, it's time for us to actually run the underlying functionality AND respond back to Claude with the corresponding Wikipedia page content.\n",
+ "\n",
+ "**We need to pay special attention to make sure we update our `messages` list**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We'll begin by updating our `messages` list to include Claude's most recent response:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "messages.append({\"role\": \"assistant\", \"content\": response['output']['message']['content']})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "messages"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, we'll extract the specific tool and arguments that Claude wants to use:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "# This is a simple, but brittle way of getting the tool use information\n",
+ "# We're simply taking the last block from Claude's response.\n",
+ "tool_use = response['output']['message']['content'][-1]\n",
+ "tool_id = tool_use['toolUse']['toolUseId']\n",
+ "tool_name = tool_use['toolUse']['name']\n",
+ "tool_inputs = tool_use['toolUse']['input']\n",
+ "\n",
+ "print(\"Tool Id: \", tool_id)\n",
+ "print(\"Tool name: \", tool_name)\n",
+ "print(\"Tool input\", tool_inputs)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, we'll make sure Claude is calling the `get_article` tool we're expecting. We'll take the `search_term` Claude came up with and pass that to the `get_article` function we wrote earlier."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "if tool_name == \"get_article\":\n",
+ " search_term = tool_inputs[\"search_term\"]\n",
+ " wiki_result = get_article(search_term)\n",
+ " print(f\"Searching Wikipedia for: {search_term}\")\n",
+ " print(\"WIKIPEDIA PAGE CONTENT:\")\n",
+ " print(wiki_result[:500]) #just printing a small bit of the article because it's so long"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now that we've executed the function Claude wanted us to call, it's time to respond back to Claude with the Wikipedia page data.\n",
+ "\n",
+ "As we know, when Claude wants to use a tool, it responds to us with a `stop_reason` of `tool_use` and one or more `tool_use` content blocks in the API response that include:\n",
+ "* `id`: A unique identifier for this particular tool use block. This will be used to match up the tool results later.\n",
+ "* `name`: The name of the tool being used.\n",
+ "* `input`: An object containing the input being passed to the tool, conforming to the tool's `input_schema`.\n",
+ "\n",
+ "Once we have executed our underlying tool function, we need to respond back to Claude with a particular format as well. Specifically, to continue the conversation, we need to send a new message with the **role of `user`** and a content block **containing the `tool_result` type**, along with the following information:\n",
+ "* `toolUseId`: The id of the tool use request this is a result for.\n",
+ "* `content`: The result of the tool, as a string (e.g. \"content\": \"15 degrees\") or list of nested content blocks (e.g. \"content\": [{\"type\": \"text\", \"text\": \"15 degrees\"}]\\). \n",
+ "* `status` (optional): Set to **success** or **error** based on the tool execution results.\n",
+ "\n",
+ "Here's an example of what a properly formatted `toolResult` message looks like: "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```json\n",
+ "{\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": \"tooluse_kZJMlvQmRJ6eAyJE5GIl7Q\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"json\": {\n",
+ " \"song\": \"Elemental Hotel\",\n",
+ " \"artist\": \"8 Storey Hike\"\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's do this now for our Wikipedia search example. We need to form a properly constructed tool response message to send our Wikipedia search result back to Claude:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "tool_response = {\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"text\": wiki_result\n",
+ " }\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "# Notice the long wikipedia article content!\n",
+ "tool_response"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, we need to add our `tool_response` message to our messages list: "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "messages.append(tool_response)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "messages"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Our `messages` list now looks like this: \n",
+ "\n",
+ "* User: Who won the 2024 Masters Tournament?\n",
+ "* Assistant: I want to use the `get_article` tool with `search_term` \"2024 Masters Tournament\"\n",
+ "* User: Here's the tool result that contains the Wikipedia article you asked for\n",
+ "\n",
+ "Here's a diagram that illustrates this.\n",
+ "\n",
+ "\n",
+ "\n",
+ "Note that the initial `id` matches the `tool_use_id` in our follow up user message\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 6. Claude uses the tool result to formulate a response: (API response)\n",
+ "\n",
+ "Finally, we can use our updated `messages` list and send a new request to Claude:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 1000},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ "}\n",
+ "\n",
+ "follow_up_response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "follow_up_response['output']['message']['content'][0]['text']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude now has the information needed to answer the initial question and responds back with:\n",
+ "\n",
+ "> 'According to the information provided, Scottie Scheffler won the 2024 Masters Tournament.According to the information provided, Scottie Scheffler won the 2024 Masters Tournament...'\n",
+ "\n",
+ "We have now completed all 4 steps of the process! "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Improving the code\n",
+ "\n",
+ "At a bare minimum, we probably want to put all the above code into a reusable function so we can try it out a few times:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def answer_question(question):\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": question}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " if(response['stopReason'] == \"tool_use\"):\n",
+ " tool_use = response['output']['message']['content'][-1]\n",
+ " tool_id = tool_use['toolUse']['toolUseId']\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_inputs = tool_use['toolUse']['input']\n",
+ " #Add Claude's tool use call to messages:\n",
+ " messages.append({\"role\": \"assistant\", \"content\": response['output']['message']['content']})\n",
+ "\n",
+ " if tool_name == \"get_article\":\n",
+ " search_term = tool_inputs[\"search_term\"]\n",
+ " print(f\"Claude wants to get an article for: {search_term}\")\n",
+ " wiki_result = get_article(search_term) #get wikipedia article content\n",
+ " #construct our tool_result message\n",
+ " tool_response = {\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\"text\": wiki_result}\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " }\n",
+ " messages.append(tool_response)\n",
+ " #respond back to Claude\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " print(\"Claude's final answer:\")\n",
+ " print(response['output']['message']['content'][0]['text'])\n",
+ "\n",
+ " else:\n",
+ " print(\"Claude did not call our tool\")\n",
+ " print(response['output']['message']['content'][0]['text'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "answer_question(\"Who won the 2024 F1 Australian Grand Prix\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "answer_question(\"Who stars in the movie Challengers?\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "#Let's try an example that Claude should NOT need our tool to answer:\n",
+ "answer_question(\"Who wrote the book 'The Life of Pi'\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Notice that Claude called our Wikipedia tool to help answer this last question, even though Claude already knows the answer. \"Life of Pi\" was published in 2001, long before Claude's training cutoff!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Improving our prompt\n",
+ "\n",
+ "As we saw in a previous lesson, sometimes Claude is overly eager to use tools. An easy wasy to fix this is through the system prompt.\n",
+ "\n",
+ "\n",
+ "We could add a system prompt that looks something like this:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "system_prompt = \"\"\"\n",
+ " You will be asked a question by the user. \n",
+ " If answering the question requires data you were not trained on, you can use the get_article tool to get the contents of a recent wikipedia article about the topic. \n",
+ " If you can answer the question without needing to get more information, please do so. \n",
+ " Only call the tool when needed. \n",
+ " \"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's update our function to use this new system prompt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def answer_question(question):\n",
+ " system_prompt = \"\"\"\n",
+ " You will be asked a question by the user. \n",
+ " If answering the question requires data you were not trained on, you must use the get_article tool to get the contents of a recent wikipedia article about the topic. \n",
+ " If you can answer the question without needing to get more information, please do so. \n",
+ " Only call the tool when needed. \n",
+ " \"\"\"\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": question}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " if(response['stopReason'] == \"tool_use\"):\n",
+ " tool_use = response['output']['message']['content'][-1]\n",
+ " tool_id = tool_use['toolUse']['toolUseId']\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_inputs = tool_use['toolUse']['input']\n",
+ " #Add Claude's tool use call to messages:\n",
+ " messages.append({\"role\": \"assistant\", \"content\": response['output']['message']['content']})\n",
+ "\n",
+ " if tool_name == \"get_article\":\n",
+ " search_term = tool_inputs[\"search_term\"]\n",
+ " print(f\"Claude wants to get an article for: {search_term}\")\n",
+ " wiki_result = get_article(search_term) #get wikipedia article content\n",
+ " #construct our tool_result message\n",
+ " tool_response = {\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\"text\": wiki_result}\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " }\n",
+ " messages.append(tool_response)\n",
+ " #respond back to Claude\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 4096},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " print(\"Claude's final answer:\")\n",
+ " print(response['output']['message']['content'][0]['text'])\n",
+ "\n",
+ " else:\n",
+ " print(\"Claude did not call our tool\")\n",
+ " print(response['output']['message']['content'][0]['text'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's try asking the same question:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "answer_question(\"Who wrote the book The Life of Pi\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It worked! Claude did not use our tool when it wasn't needed. Let's make sure it still works when answering questions that do require recent knowledge:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "answer_question(\"Who wrote the score for the movie Challengers?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It's working as intended in both situations! Now let's work on getting Claude's response to be a little more succinct. It's great that Claude is explaining HOW it came up with the correct answer, but it's a little verbose. Let's do a little basic prompt engineering to fix that. \n",
+ "\n",
+ "Let's try this:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "prompt = f\"\"\"\n",
+ " Answer the following question Who wrote the movie Poor Things?\n",
+ " When you can answer the question, keep your answer as short as possible and enclose it in tags\n",
+ " \"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's our function updated with the new prompt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def answer_question(question):\n",
+ " system_prompt = \"\"\"\n",
+ " You will be asked a question by the user. \n",
+ " If answering the question requires data you were not trained on, you must use the get_article tool to get the contents of a recent wikipedia article about the topic. \n",
+ " If you can answer the question without needing to get more information, please do so. \n",
+ " Only call the tool when needed.\n",
+ " \"\"\"\n",
+ " prompt = f\"\"\"\n",
+ " Answer the following question {question}\n",
+ " When you can answer the question, keep your answer as short as possible and enclose it in tags\n",
+ " \"\"\"\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"additionalModelRequestFields\": {\"max_tokens\": 4096},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " if(response['stopReason'] == \"tool_use\"):\n",
+ " tool_use = response['output']['message']['content'][-1]\n",
+ " tool_id = tool_use['toolUse']['toolUseId']\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_inputs = tool_use['toolUse']['input']\n",
+ " #Add Claude's tool use call to messages:\n",
+ " messages.append({\"role\": \"assistant\", \"content\": response['output']['message']['content']})\n",
+ "\n",
+ " if tool_name == \"get_article\":\n",
+ " search_term = tool_inputs[\"search_term\"]\n",
+ " print(f\"Claude wants to get an article for: {search_term}\")\n",
+ " wiki_result = get_article(search_term) #get wikipedia article content\n",
+ " #construct our tool_result message\n",
+ " tool_response = {\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\"text\": wiki_result}\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " }\n",
+ " messages.append(tool_response)\n",
+ " #respond back to Claude\n",
+ " converse_api_params = {\n",
+ " \"modelId\": \"anthropic.claude-3-sonnet-20240229-v1:0\",\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"additionalModelRequestFields\": {\"max_tokens\": 4096},\n",
+ " \"toolConfig\": toolConfig #The toolConfig which contains our article_search_tool details\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " print(\"Claude's final answer:\")\n",
+ " print(response['output']['message']['content'][0]['text'])\n",
+ "\n",
+ " else:\n",
+ " print(\"Claude did not call our tool\")\n",
+ " print(response['output']['message']['content'][0]['text'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "answer_question(\"Who wrote the score for the film Challengers?\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "answer_question(\"Who won the 2024 F1 Australian Grand Prix?\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "answer_question(\"How many legs does an octopus have?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Much better! Claude is now responding with answers without a bunch of additional \"thinking\" and explanation about how it arrived at the answer."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercise\n",
+ "\n",
+ "Can you update this code so that it fulfills the following requirements:\n",
+ "* Claude might not get enough information from the first Wikipedia page we respond with. We haven't handled that situation yet. Imagine we ask Claude \"How many Oscars does Christopher Nolan have? Does he have more than the number of Emmy's that Ben Stiller has?\" Claude would need to search Christopher Nolan's Wikipedia page AND Ben Stiller's page, likely one after another. Our code currently does not allow this, so let's build in that functionality! **Hint: use a loop!** \n",
+ "* Extract the answer from the `` tags Claude currently responds with so that you only print out the actual answer content.\n",
+ "* Can you turn this into a full command-line chatbot that continuously asks a user to enter a query and then responds with the answer over and over until a user quits the program? The output could look something like this: \n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a screenshot of an example conversation session: \n",
+ "\n",
+ ""
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "conda_pytorch_p310",
+ "language": "python",
+ "name": "conda_pytorch_p310"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/AmazonBedrock/10_2_4_Tool_Choice.ipynb b/AmazonBedrock/10_2_4_Tool_Choice.ipynb
new file mode 100755
index 0000000..3ea62c9
--- /dev/null
+++ b/AmazonBedrock/10_2_4_Tool_Choice.ipynb
@@ -0,0 +1,759 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Appendix 10.2.4: Tool choice"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The Claude API supports a parameter called `tool_choice` that allows you to specify how you want Claude to call tools. In this notebook, we'll take a look at how it works and when to use it.\n",
+ "\n",
+ "When working with the `tool_choice` parameter, we have three possible options: \n",
+ "\n",
+ "* `auto` allows Claude to decide whether to call any provided tools or not.\n",
+ "* `any` tells Claude that it must use one of the provided tools, but doesn't force a particular tool.\n",
+ "* `tool` allows us to force Claude to always use a particular tool.\n",
+ "\n",
+ "\n",
+ "This diagram illustrates how each option works: \n",
+ "\n",
+ "\n",
+ "\n",
+ "Let's take a look at each option in detail. We'll start by importing the Anthropic SDK:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "%pip install -qU pip\n",
+ "%pip install -qUr requirements.txt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import boto3\n",
+ "import json\n",
+ "from datetime import datetime\n",
+ "from botocore.exceptions import ClientError\n",
+ "\n",
+ "session = boto3.Session()\n",
+ "region = session.region_name"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
+ "#modelId = 'anthropic.claude-3-haiku-20240307-v1:0'\n",
+ "\n",
+ "print(f'Using modelId: {modelId}')\n",
+ "print(f'Using region: ', {region})\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Auto\n",
+ "\n",
+ "Setting `tool_choice` to `auto` allows the model to automatically decide whether to use tools or not. This is the default behavior when working with tools if you don't use the `tool_choice` parameter at all.\n",
+ "\n",
+ "To demonstrate this, we're going to provide Claude with a fake web search tool. We will ask Claude questions, some of which would require calling the web search tool and others which Claude should be able to answer on its own.\n",
+ "\n",
+ "Let's start by defining a tool called `web_search`. Please note, to keep this demo simple, we're not actually searching the web here.\n",
+ "\n",
+ "We also set `toolChoice` to `auto`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def web_search(topic):\n",
+ " print(f\"pretending to search the web for {topic}\")\n",
+ "\n",
+ "toolConfig = {'tools': [],\n",
+ " \"toolChoice\": {\n",
+ " \"auto\":{},\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "toolConfig['tools'].append({\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"web_search\",\n",
+ " \"description\": \"A tool to retrieve up to date information on a given topic by searching the web. Only search the web for queries that you can not confidently answer.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"topic\": {\"type\": \"string\", \"description\": \"The topic to search the web for\"}\n",
+ " },\n",
+ " \"required\": [\"topic\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " })"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, we write a function that accepts a `user_query` and passes it along to Claude, along with the `web_search_tool`. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's the complete function:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from datetime import date\n",
+ "\n",
+ "def chat_with_web_search(user_query):\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": user_query}]}]\n",
+ "\n",
+ " system_prompt=f\"\"\"\n",
+ " Answer as many questions as you can using your existing knowledge. \n",
+ " Only search the web for queries that you can not confidently answer.\n",
+ " Today's date is {date.today().strftime(\"%B %d %Y\")}\n",
+ " If you think a user's question involves something in the future that hasn't happened yet, use the search tool.\n",
+ " \"\"\"\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 1000},\n",
+ " \"toolConfig\":toolConfig\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " stop_reason = response['stopReason']\n",
+ "\n",
+ " if stop_reason == \"end_turn\":\n",
+ " print(\"Claude did NOT call a tool\")\n",
+ " print(f\"Assistant: {stop_reason}\")\n",
+ " elif stop_reason == \"tool_use\":\n",
+ " print(\"Claude wants to use a tool\")\n",
+ " print(stop_reason)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's start with a question Claude should be able to answer without using the tool:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "chat_with_web_search(\"What color is the sky?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "When we ask \"What color is the sky?\", Claude does not use the tool. Let's try asking something that Claude should use the web search tool to answer:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "chat_with_web_search(\"Who won the 2024 Miami Grand Prix?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "When we ask \"Who won the 2024 Miami Grand Prix?\", Claude uses the web search tool! \n",
+ "\n",
+ "Let's try a few more examples:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Claude should NOT need to use the tool for this:\n",
+ "chat_with_web_search(\"Who won the Superbowl in 2022?\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Claude SHOULD use the tool for this:\n",
+ "chat_with_web_search(\"Who won the Superbowl in 2024?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Your prompt matters!\n",
+ "\n",
+ "When working with `toolChoice` set to `auto`, it's important that you spend time to write a detailed prompt. Often, Claude can be over-eager to call tools. Writing a detailed prompt helps Claude determine when to call a tool and when not to. In the above example, we included specific instructions in the system prompt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "system_prompt=f\"\"\"\n",
+ " Answer as many questions as you can using your existing knowledge.\n",
+ " Only search the web for queries that you can not confidently answer.\n",
+ " Today's date is {date.today().strftime(\"%B %d %Y\")}\n",
+ " If you think a user's question involves something in the future that hasn't happened yet, use the search tool.\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Forcing a specific tool\n",
+ "\n",
+ "We can force Claude to use a particular tool using `toolChoice`. In the example below, we've defined two simple tools: \n",
+ "* `print_sentiment_scores` - a tool that \"tricks\" Claude into generating well-structured JSON output containing sentiment analysis data. For more info on this approach, see [Extracting Structured JSON using Claude and Tool Use](https://github.com/anthropics/anthropic-cookbook/blob/main/tool_use/extracting_structured_json.ipynb) in the Anthropic Cookbook.\n",
+ "* `calculator` - a very simple calculator tool that takes two numbers and adds them together .\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Our goal is to write a function called `analyze_tweet_sentiment` that takes in a tweet and uses Claude to print a basic sentiment analysis of that tweet. Eventually we will \"force\" Claude to use the `print_sentiment_scores` tool, but we'll start by showing what happens when we **do not** force the tool use. \n",
+ "\n",
+ "In this first \"bad\" version of the `analyze_tweet_sentiment` function, we provide Claude with both tools. For the sake of comparison, we'll start by setting `toolChoice` to `auto`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create our toolConfig\n",
+ "toolConfig = {'tools': [],\n",
+ " \"toolChoice\": {\n",
+ " \"auto\":{},\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "# append our print_sentiment_scores tool\n",
+ "toolConfig['tools'].append({\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"print_sentiment_scores\",\n",
+ " \"description\": \"Prints the sentiment scores of a given tweet or piece of text.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"positive_score\": {\"type\": \"number\",\"description\": \"The positive sentiment score, ranging from 0.0 to 1.0.\"},\n",
+ " \"negative_score\": {\"type\": \"number\",\"description\": \"The negative sentiment score, ranging from 0.0 to 1.0.\"},\n",
+ " \"neutral_score\": {\"type\": \"number\",\"description\": \"The neutral sentiment score, ranging from 0.0 to 1.0.\"}\n",
+ " },\n",
+ " \"required\": [\"positive_score\", \"negative_score\", \"neutral_score\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " })\n",
+ "\n",
+ "# Append our Calculator tool\n",
+ "toolConfig['tools'].append({\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"calculator\",\n",
+ " \"description\": \"Adds two numbers\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"num1\": {\"type\": \"number\", \"description\": \"first number to add\"},\n",
+ " \"num2\": {\"type\": \"number\", \"description\": \"second number to add\"}\n",
+ " },\n",
+ " \"required\": [\"num1\", \"num2\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " })"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Please note that we are deliberately not providing Claude with a well-written prompt, to make it easier to see the impact of forcing the use of a particular tool."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def analyze_tweet_sentiment(query):\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": query}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 1000},\n",
+ " \"toolConfig\":toolConfig,\n",
+ " }\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " print(response)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's see what happens when we call the function with the tweet `Holy cow, I just made the most incredible meal!`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "analyze_tweet_sentiment(\"Holy cow, I just made the most incredible meal!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude does not call our `print_sentiment_scores` tool and instead responds directly with:\n",
+ "> \"That's great to hear! I don't actually have the capability to assess sentiment from text, but it sounds like you're really excited and proud of the incredible meal you made\n",
+ "\n",
+ "Next, let's imagine someone tweets this: `I love my cats! I had four and just adopted 2 more! Guess how many I have now?`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "analyze_tweet_sentiment(\"I love my cats! I had four and just adopted 2 more! Guess how many I have now?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude wants to call the calculator tool:\n",
+ "\n",
+ "> {'toolUse': {'toolUseId': 'tooluse_oyzX9vToT468sAwe_A99EA', **'name': 'calculator', 'input': {'num1': 4, 'num2': 2}**}}]}}, 'stopReason': 'tool_use'{'toolUse': {'toolUseId': 'tooluse_oyzX9vToT468sAwe_A99EA', 'name': 'calculator', 'input': {'num1': 4, 'num2': 2}}}]}}, 'stopReason': 'tool_use'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Clearly, this current implementation is not doing what we want (mostly because we set it up to fail). \n",
+ "\n",
+ "So let's force Claude to **always** use the `print_sentiment_scores` tool by updating `toolChoice`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "toolConfig['toolChoice'] = {\n",
+ " \"tool\": {\n",
+ " \"name\": \"print_sentiment_scores\"}\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In addition to setting `type` to `tool`, we must provide a particular tool name."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def analyze_tweet_sentiment(query):\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": query}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 1000},\n",
+ " \"toolConfig\":toolConfig,\n",
+ " }\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " print(response)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now if we try prompting Claude with the same prompts from earlier, it's always going to call the `print_sentiment_scores` tool:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "analyze_tweet_sentiment(\"Holy cow, I just made the most incredible meal!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude calls our `print_sentiment_scores` tool:\n",
+ "\n",
+ "> [{'toolUse': {'toolUseId': 'tooluse_EZnn27PHRXWfo7JR8FWkDw', **'name': 'print_sentiment_scores',** 'input': {'positive_score': 0.9, 'negative_score': 0.1, 'neutral_score': 0.0}}}][{'toolUse': {'toolUseId': 'tooluse_EZnn27PHRXWfo7JR8FWkDw', 'name': 'print_sentiment_scores', 'input': {'positive_score': 0.9, 'negative_score': 0.1, 'neutral_score': 0.0}}}]\n",
+ "\n",
+ "Even if we try to trip up Claude with a \"Math-y\" tweet, it still always calls the `print_sentiment_scores` tool:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "analyze_tweet_sentiment(\"I love my cats! I had four and just adopted 2 more! Guess how many I have now?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Even though we're forcing Claude to call our `print_sentiment_scores` tool, we should still employ some basic prompt engineering to give Claude better task context:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def analyze_tweet_sentiment(query):\n",
+ " prompt = f\"\"\"\n",
+ " Analyze the sentiment in the following tweet:\n",
+ " {query}\"\"\"\n",
+ "\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 1000},\n",
+ " \"toolConfig\":toolConfig,\n",
+ " }\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " print(response)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Any\n",
+ "\n",
+ "The final option for `toolChoice` is `any`, which allows us to tell Claude, \"You must call a tool, but you can pick which one.\" Imagine we want to create a SMS chatbot using Claude. The only way for this chatbot to actually \"communicate\" with a user is via SMS text message. \n",
+ "\n",
+ "In the example below, we make a very simple text-messaging assistant that has access to two tools:\n",
+ "* `send_text_to_user` - sends a text message to a user.\n",
+ "* `get_customer_info` - looks up customer data based on a username.\n",
+ "\n",
+ "The idea is to create a chatbot that always calls one of these tools and never responds with a non-tool response. In all situations, Claude should either respond back by trying to send a text message or calling `get_customer_info` to get more customer information. To ensure this, we set `toolChoice` to `any`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "toolConfig = {'tools': [],\n",
+ " \"toolChoice\": {\n",
+ " \"any\":{},\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "toolConfig['tools'].append({\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"send_text_to_user\",\n",
+ " \"description\": \"Sends a text message to a user\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"text\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The piece of text to be sent to the user via text message\"}\n",
+ " },\n",
+ " \"required\": [\"text\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " })\n",
+ "\n",
+ "toolConfig['tools'].append({\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"get_customer_info\",\n",
+ " \"description\": \"gets information on a customer based on the customer's username. Response includes email, username, and previous purchases. Only call this tool once a user has provided you with their username\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"username\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The username of the user in question. \"}\n",
+ " },\n",
+ " \"required\": [\"username\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " })"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "#toolConfig # Optional uncomment to see the updated toolConfig"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def send_text_to_user(text):\n",
+ " # Sends a text to the user\n",
+ " # We'll just print out the text to keep things simple:\n",
+ " print(f\"TEXT MESSAGE SENT: {text}\")\n",
+ "\n",
+ "def get_customer_info(username):\n",
+ " return {\n",
+ " \"username\": username,\n",
+ " \"email\": f\"{username}@email.com\",\n",
+ " \"purchases\": [\n",
+ " {\"id\": 1, \"product\": \"computer mouse\"},\n",
+ " {\"id\": 2, \"product\": \"screen protector\"},\n",
+ " {\"id\": 3, \"product\": \"usb charging cable\"},\n",
+ " ]\n",
+ " }\n",
+ "\n",
+ "system_prompt = \"\"\"\n",
+ "All your communication with a user is done via text message.\n",
+ "Only call tools when you have enough information to accurately call them. \n",
+ "Do not call the get_customer_info tool until a user has provided you with their username. This is important.\n",
+ "If you do not know a user's username, simply ask a user for their username.\n",
+ "\"\"\"\n",
+ "\n",
+ "def sms_chatbot(user_message):\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": user_message}]}]\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"temperature\": 0.0, \"maxTokens\": 1000},\n",
+ " \"toolConfig\":toolConfig,\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " if(response['stopReason'] == \"tool_use\"):\n",
+ " tool_use = response['output']['message']['content'][-1]\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_inputs = tool_use['toolUse']['input']\n",
+ " print(f\"=======Claude Wants To Call The {tool_name} Tool=======\")\n",
+ " if tool_name == \"send_text_to_user\":\n",
+ " send_text_to_user(tool_inputs[\"text\"])\n",
+ " elif tool_name == \"get_customer_info\":\n",
+ " print(get_customer_info(tool_inputs[\"username\"]))\n",
+ " else:\n",
+ " print(\"Oh dear, that tool doesn't exist!\")\n",
+ " \n",
+ " else:\n",
+ " print(\"No tool was called. This shouldn't happen!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's start simple:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sms_chatbot(\"Hey there! How are you?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude responds back by calling the `send_text_to_user` tool.\n",
+ "\n",
+ "Next, we'll ask Claude something a bit trickier:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sms_chatbot(\"I need help looking up an order\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude wants to send a text message, asking a user to provide their username.\n",
+ "\n",
+ "Now, let's see what happens when we provide Claude with our username:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sms_chatbot(\"I need help looking up an order. My username is jenny76\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude calls the `get_customer_info` tool, just as we hoped! \n",
+ "\n",
+ "Even if we send Claude a gibberish message, it will still call one of our tools:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sms_chatbot(\"askdj aksjdh asjkdbhas kjdhas 1+1 ajsdh\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "conda_pytorch_p310",
+ "language": "python",
+ "name": "conda_pytorch_p310"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/AmazonBedrock/10_2_5_Chatbot_with_Multiple_Tools.ipynb b/AmazonBedrock/10_2_5_Chatbot_with_Multiple_Tools.ipynb
new file mode 100755
index 0000000..a2cefd2
--- /dev/null
+++ b/AmazonBedrock/10_2_5_Chatbot_with_Multiple_Tools.ipynb
@@ -0,0 +1,1355 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Appendix 10.2.5: Tool use with multiple tools\n",
+ "\n",
+ "Now we're going to take our tool use to another level! We're going to provide Claude with a suite of tools it can select from. Our goal is to build a simple customer support chatbot for a fictional electronics company called TechNova. It will have access to simple tools including: \n",
+ "\n",
+ "* `get_user` to look up user details by email, username, or phone number\n",
+ "* `get_order_by_id` to look up an order directly by its order ID\n",
+ "* `get_customer_orders` to look up all the orders belonging to a customer\n",
+ "* `cancel_order` cancels an order given a specific order ID\n",
+ "\n",
+ "This chatbot will be quite limited, but it demonstrates some key pieces of working with multiple tools. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's an image showcasing an example interaction with the chatbot.\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's another interaction with the chatbot where we've explicitly printed out a message any time Claude uses a tool, to make it easier to understand what's happening behind the scenes: \n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a diagram showing the flow of information for a potential single chat message:\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**important note: this chatbot is extremely simple and allows anyone to cancel an order as long as they have the username or email of the user who placed the order. This implementation is for educational purposes and should not be integrated into a real codebase without alteration!**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Our fake database\n",
+ "Before we start working with Claude, we'll begin by defining a very simple `FakeDatabase` class that will hold some fake customers and orders, as well as providing methods for us to interact with the data. In the real world, the chatbot would presumably be connected to one or more *actual* databases."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "class FakeDatabase:\n",
+ " def __init__(self):\n",
+ " self.customers = [\n",
+ " {\"id\": \"1213210\", \"name\": \"John Doe\", \"email\": \"john@gmail.com\", \"phone\": \"123-456-7890\", \"username\": \"johndoe\"},\n",
+ " {\"id\": \"2837622\", \"name\": \"Priya Patel\", \"email\": \"priya@candy.com\", \"phone\": \"987-654-3210\", \"username\": \"priya123\"},\n",
+ " {\"id\": \"3924156\", \"name\": \"Liam Nguyen\", \"email\": \"lnguyen@yahoo.com\", \"phone\": \"555-123-4567\", \"username\": \"liamn\"},\n",
+ " {\"id\": \"4782901\", \"name\": \"Aaliyah Davis\", \"email\": \"aaliyahd@hotmail.com\", \"phone\": \"111-222-3333\", \"username\": \"adavis\"},\n",
+ " {\"id\": \"5190753\", \"name\": \"Hiroshi Nakamura\", \"email\": \"hiroshi@gmail.com\", \"phone\": \"444-555-6666\", \"username\": \"hiroshin\"},\n",
+ " {\"id\": \"6824095\", \"name\": \"Fatima Ahmed\", \"email\": \"fatimaa@outlook.com\", \"phone\": \"777-888-9999\", \"username\": \"fatimaahmed\"},\n",
+ " {\"id\": \"7135680\", \"name\": \"Alejandro Rodriguez\", \"email\": \"arodriguez@protonmail.com\", \"phone\": \"222-333-4444\", \"username\": \"alexr\"},\n",
+ " {\"id\": \"8259147\", \"name\": \"Megan Anderson\", \"email\": \"megana@gmail.com\", \"phone\": \"666-777-8888\", \"username\": \"manderson\"},\n",
+ " {\"id\": \"9603481\", \"name\": \"Kwame Osei\", \"email\": \"kwameo@yahoo.com\", \"phone\": \"999-000-1111\", \"username\": \"kwameo\"},\n",
+ " {\"id\": \"1057426\", \"name\": \"Mei Lin\", \"email\": \"meilin@gmail.com\", \"phone\": \"333-444-5555\", \"username\": \"mlin\"}\n",
+ " ]\n",
+ "\n",
+ " self.orders = [\n",
+ " {\"id\": \"24601\", \"customer_id\": \"1213210\", \"product\": \"Wireless Headphones\", \"quantity\": 1, \"price\": 79.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"13579\", \"customer_id\": \"1213210\", \"product\": \"Smartphone Case\", \"quantity\": 2, \"price\": 19.99, \"status\": \"Processing\"},\n",
+ " {\"id\": \"97531\", \"customer_id\": \"2837622\", \"product\": \"Bluetooth Speaker\", \"quantity\": 1, \"price\": \"49.99\", \"status\": \"Shipped\"}, \n",
+ " {\"id\": \"86420\", \"customer_id\": \"3924156\", \"product\": \"Fitness Tracker\", \"quantity\": 1, \"price\": 129.99, \"status\": \"Delivered\"},\n",
+ " {\"id\": \"54321\", \"customer_id\": \"4782901\", \"product\": \"Laptop Sleeve\", \"quantity\": 3, \"price\": 24.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"19283\", \"customer_id\": \"5190753\", \"product\": \"Wireless Mouse\", \"quantity\": 1, \"price\": 34.99, \"status\": \"Processing\"},\n",
+ " {\"id\": \"74651\", \"customer_id\": \"6824095\", \"product\": \"Gaming Keyboard\", \"quantity\": 1, \"price\": 89.99, \"status\": \"Delivered\"},\n",
+ " {\"id\": \"30298\", \"customer_id\": \"7135680\", \"product\": \"Portable Charger\", \"quantity\": 2, \"price\": 29.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"47652\", \"customer_id\": \"8259147\", \"product\": \"Smartwatch\", \"quantity\": 1, \"price\": 199.99, \"status\": \"Processing\"},\n",
+ " {\"id\": \"61984\", \"customer_id\": \"9603481\", \"product\": \"Noise-Cancelling Headphones\", \"quantity\": 1, \"price\": 149.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"58243\", \"customer_id\": \"1057426\", \"product\": \"Wireless Earbuds\", \"quantity\": 2, \"price\": 99.99, \"status\": \"Delivered\"},\n",
+ " {\"id\": \"90357\", \"customer_id\": \"1213210\", \"product\": \"Smartphone Case\", \"quantity\": 1, \"price\": 19.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"28164\", \"customer_id\": \"2837622\", \"product\": \"Wireless Headphones\", \"quantity\": 2, \"price\": 79.99, \"status\": \"Processing\"}\n",
+ " ]\n",
+ "\n",
+ " def get_user(self, key, value):\n",
+ " if key in {\"email\", \"phone\", \"username\"}:\n",
+ " for customer in self.customers:\n",
+ " if customer[key] == value:\n",
+ " return customer\n",
+ " return f\"Couldn't find a user with {key} of {value}\"\n",
+ " else:\n",
+ " raise ValueError(f\"Invalid key: {key}\")\n",
+ "\n",
+ " return None\n",
+ "\n",
+ " def get_order_by_id(self, order_id):\n",
+ " for order in self.orders:\n",
+ " if order[\"id\"] == order_id:\n",
+ " return order\n",
+ " return None\n",
+ "\n",
+ " def get_customer_orders(self, customer_id):\n",
+ " return [order for order in self.orders if order[\"customer_id\"] == customer_id]\n",
+ "\n",
+ " def cancel_order(self, order_id):\n",
+ " order = self.get_order_by_id(order_id)\n",
+ " if order:\n",
+ " if order[\"status\"] == \"Processing\":\n",
+ " order[\"status\"] = \"Cancelled\"\n",
+ " return \"Cancelled the order\"\n",
+ " else:\n",
+ " return \"Order has already shipped. Can't cancel it.\"\n",
+ " return \"Can't find that order!\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We'll create an instance of the `FakeDatabase`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db = FakeDatabase()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's make sure our `get_user` method works as intended. It's expecting us to pass in a `key` that is one of: \n",
+ "\n",
+ "* \"email\"\n",
+ "* \"username\"\n",
+ "* \"phone\" \n",
+ "\n",
+ "It also expects a corresponding `value` that it will use to perform a basic search, hopefully returning the matching user."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db.get_user(\"email\", \"john@gmail.com\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db.get_user(\"username\", \"adavis\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db.get_user(\"phone\", \"666-777-8888\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also get a list of all orders that belong to a particular customer by calling `get_customer_orders` and passing in a customer ID:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db.get_customer_orders(\"1213210\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db.get_customer_orders(\"9603481\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We also can look up a single order directly if we have the order ID:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "db.get_order_by_id('24601')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Lastly, we can use the `cancel_order` method to cancel an order. Orders can only be cancelled if they are \"processing\". We can't cancel an order that has already shipped! The method expects us to pass in an order_id of the order we want to cancel."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "#Let's look up an order that has a status of processing:\n",
+ "db.get_order_by_id(\"47652\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "#Now let's cancel it! \n",
+ "db.cancel_order(\"47652\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "# It's status should now be \"Cancelled\"\n",
+ "db.get_order_by_id(\"47652\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Writing our tools\n",
+ "\n",
+ "Now that we've tested our (very) simple fake database functionality, let's write JSON schemas that define the structure of the tools. Let's take a look at a very simple tool that corresponds to our `get_order_by_id` method:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "tool1 = {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"get_order_by_id\",\n",
+ " \"description\": \"Retrieves the details of a specific order based on the order ID. Returns the order ID, product name, quantity, price, and order status.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"order_id\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The unique identifier for the order.\"}\n",
+ " },\n",
+ " \"required\": [\"order_id\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As always, we include a name, a description, and an overview of the inputs. In this case, there is a single input, `order_id`, and it is required. \n",
+ "\n",
+ "Now let's take a look at a more complex tool that corresponds to the `get_user` method. Recall that this method has two arguments:\n",
+ "\n",
+ "1. A `key` argument that is one of the following strings:\n",
+ " * \"email\"\n",
+ " * \"username\"\n",
+ " * \"phone\" \n",
+ "2. A `value` argument which is the term we'll be using to search (the actual email, phone number, or username)\n",
+ "\n",
+ "Here's the corresponding tool definition:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "tool2 = {\n",
+ " \"toolSpec\": {\n",
+ " \"name\": \"get_user\",\n",
+ " \"description\": \"Looks up a user by email, phone, or username.\",\n",
+ " \"inputSchema\": {\n",
+ " \"json\": {\n",
+ " \"type\": \"object\",\n",
+ " \"properties\": {\n",
+ " \"key\": {\n",
+ " \"type\": \"string\",\n",
+ " \"enum\": [\"email\", \"phone\", \"username\"],\n",
+ " \"description\": \"The attribute to search for a user by (email, phone, or username).\"},\n",
+ " \"value\": {\n",
+ " \"type\": \"string\",\n",
+ " \"description\": \"The value to match for the specified attribute.\"}\n",
+ " },\n",
+ " \"required\": [\"key\", \"value\"]\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Pay special attention to the way we define the set of possible valid options for `key` using `enum` in the schema."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We still have two more tools to write, but to save time, we'll just provide you the complete list of tools ready for us to use. (You're welcome to try defining them youself first as an exercise!)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "toolConfig = {\n",
+ " 'tools': [\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'get_user',\n",
+ " 'description': 'Looks up a user by email, phone, or username.',\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'key': {\n",
+ " 'type': 'string',\n",
+ " 'enum': ['email', 'phone', 'username'],\n",
+ " 'description': 'The attribute to search for a user by (email, phone, or username).'\n",
+ " },\n",
+ " 'value': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The value to match for the specified attribute.'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['key', 'value']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'get_order_by_id',\n",
+ " 'description': 'Retrieves the details of a specific order based on the order ID. Returns the order ID, product name, quantity, price, and order status.',\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'order_id': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The unique identifier for the order.'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['order_id']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'get_customer_orders',\n",
+ " 'description': \"Retrieves the list of orders belonging to a user based on a user's customer id.\",\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'customer_id': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The customer_id belonging to the user'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['customer_id']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'cancel_order',\n",
+ " 'description': \"Cancels an order based on a provided order_id. Only orders that are 'processing' can be cancelled\",\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'order_id': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The order_id pertaining to a particular order'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['order_id']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ],\n",
+ " 'toolChoice': {\n",
+ " 'auto': {}\n",
+ " }\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Giving our tools to Claude\n",
+ "\n",
+ "Next up, we need to do a few things: \n",
+ "1. Tell Claude about our tools and send the user's chat message to Claude.\n",
+ "2. Handle the response we get back from Claude:\n",
+ " * If Claude doesn't want to use a tool:\n",
+ " * Print Claude's output to the user.\n",
+ " * Ask the user for their next message.\n",
+ " * If Claude does want to use a tool\n",
+ " * Verify that Claude called one of the appropriate tools.\n",
+ " * Execute the underlying function, like `get_user` or `cancel_order`.\n",
+ " * Send Claude the result of running the tool."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Eventually, the goal is to write a command line script that will create an interactive chatbot that will run in a loop. But to keep things simple, we'll start by writing the basic code linearly. We'll end by creating an interactive chatbot script."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We start with a function that can translate Claude's tool use response into an actual method call on our `db`: "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "def process_tool_call(tool_name, tool_input):\n",
+ " if tool_name == \"get_user\":\n",
+ " return db.get_user(tool_input[\"key\"], tool_input[\"value\"])\n",
+ " elif tool_name == \"get_order_by_id\":\n",
+ " return db.get_order_by_id(tool_input[\"order_id\"])\n",
+ " elif tool_name == \"get_customer_orders\":\n",
+ " return db.get_customer_orders(tool_input[\"customer_id\"])\n",
+ " elif tool_name == \"cancel_order\":\n",
+ " return db.cancel_order(tool_input[\"order_id\"])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's start with a simple demo that shows Claude can decide which tool to use when presented with a list of multiple tools. We'll ask Claude `Can you look up my orders? My email is john@gmail.com` and see what happens!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import boto3\n",
+ "import json\n",
+ "from datetime import datetime\n",
+ "from botocore.exceptions import ClientError\n",
+ "\n",
+ "session = boto3.Session()\n",
+ "region = session.region_name\n",
+ "\n",
+ "modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
+ "\n",
+ "print(f'Using modelId: {modelId}')\n",
+ "print('Using region: ', region)\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "messages = [{\"role\": \"user\", \"content\": [{\"text\": \"Can you look up my orders? My email is john@gmail.com\"}]}]\n",
+ "\n",
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"maxTokens\": 4096},\n",
+ " \"toolConfig\":toolConfig,\n",
+ "}\n",
+ "\n",
+ "response = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "print(response['output']['message']['content'][-1])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude wants to use the `get_user` tool.\n",
+ "\n",
+ "Now we'll write the basic logic to update our messages list, call the appropriate tool, and update our messages list again with the tool results."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "# Update messages to include Claude's response\n",
+ "messages.append(\n",
+ " {\"role\": \"assistant\", \"content\": response['output']['message']['content']}\n",
+ ")\n",
+ "\n",
+ "tool_use = response['output']['message']['content'][-1]\n",
+ "tool_id = tool_use['toolUse']['toolUseId']\n",
+ "tool_name = tool_use['toolUse']['name']\n",
+ "tool_input = tool_use['toolUse']['input']\n",
+ "\n",
+ "#If Claude stops because it wants to use a tool:\n",
+ "if response['stopReason'] == \"tool_use\":\n",
+ " tool_use = response['output']['message']['content'][-1] #Naive approach assumes only 1 tool is called at a time\n",
+ " tool_id = tool_use['toolUse']['toolUseId']\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_input = tool_use['toolUse']['input']\n",
+ "\n",
+ " print(f\"Claude wants to use the {tool_name} tool\")\n",
+ " print(f\"Tool Input:\")\n",
+ " print(json.dumps(tool_input, indent=2))\n",
+ "\n",
+ " #Actually run the underlying tool functionality on our db\n",
+ " tool_result = process_tool_call(tool_name, tool_input)\n",
+ "\n",
+ " print(f\"\\nTool Result:\")\n",
+ " print(json.dumps(tool_result, indent=2))\n",
+ "\n",
+ " #Add our tool_result message:\n",
+ " messages.append({\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\"text\": str(tool_result)}\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " })\n",
+ "\n",
+ "else: \n",
+ " #If Claude does NOT want to use a tool, just print out the text reponse\n",
+ " print(\"\\nTechNova Support:\" + f\"response['output']['message']['content'][0]['text']\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This is what our messages list looks like now:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "messages"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we'll send a second request to Claude using the updated messages list:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"maxTokens\": 4096},\n",
+ " \"toolConfig\":toolConfig,\n",
+ "}\n",
+ "\n",
+ "response2 = bedrock_client.converse(**converse_api_params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "response2['output']['message']['content'][-1]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now that Claude has the result of the `get_user` tool, including the user's ID, it wants to call `get_customer_orders` to look up the orders that correspond to this particular customer. It's picking the right tool for the job. **Note:** there are many potential issues and places Claude could go wrong here, but this is a start!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Writing an interactive script\n",
+ "\n",
+ "It's a lot easier to interact with this chatbot via an interactive command line script. \n",
+ "\n",
+ "Here's all of the code from above combined into a single function that starts a loop-based chat session (you'll probably want to run this as its own script from the command line):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import boto3\n",
+ "import json\n",
+ "from datetime import datetime\n",
+ "from botocore.exceptions import ClientError\n",
+ "\n",
+ "session = boto3.Session()\n",
+ "region = session.region_name\n",
+ "\n",
+ "modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
+ "\n",
+ "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)\n",
+ "\n",
+ "class FakeDatabase:\n",
+ " def __init__(self):\n",
+ " self.customers = [\n",
+ " {\"id\": \"1213210\", \"name\": \"John Doe\", \"email\": \"john@gmail.com\", \"phone\": \"123-456-7890\", \"username\": \"johndoe\"},\n",
+ " {\"id\": \"2837622\", \"name\": \"Priya Patel\", \"email\": \"priya@candy.com\", \"phone\": \"987-654-3210\", \"username\": \"priya123\"},\n",
+ " {\"id\": \"3924156\", \"name\": \"Liam Nguyen\", \"email\": \"lnguyen@yahoo.com\", \"phone\": \"555-123-4567\", \"username\": \"liamn\"},\n",
+ " {\"id\": \"4782901\", \"name\": \"Aaliyah Davis\", \"email\": \"aaliyahd@hotmail.com\", \"phone\": \"111-222-3333\", \"username\": \"adavis\"},\n",
+ " {\"id\": \"5190753\", \"name\": \"Hiroshi Nakamura\", \"email\": \"hiroshi@gmail.com\", \"phone\": \"444-555-6666\", \"username\": \"hiroshin\"},\n",
+ " {\"id\": \"6824095\", \"name\": \"Fatima Ahmed\", \"email\": \"fatimaa@outlook.com\", \"phone\": \"777-888-9999\", \"username\": \"fatimaahmed\"},\n",
+ " {\"id\": \"7135680\", \"name\": \"Alejandro Rodriguez\", \"email\": \"arodriguez@protonmail.com\", \"phone\": \"222-333-4444\", \"username\": \"alexr\"},\n",
+ " {\"id\": \"8259147\", \"name\": \"Megan Anderson\", \"email\": \"megana@gmail.com\", \"phone\": \"666-777-8888\", \"username\": \"manderson\"},\n",
+ " {\"id\": \"9603481\", \"name\": \"Kwame Osei\", \"email\": \"kwameo@yahoo.com\", \"phone\": \"999-000-1111\", \"username\": \"kwameo\"},\n",
+ " {\"id\": \"1057426\", \"name\": \"Mei Lin\", \"email\": \"meilin@gmail.com\", \"phone\": \"333-444-5555\", \"username\": \"mlin\"}\n",
+ " ]\n",
+ "\n",
+ " self.orders = [\n",
+ " {\"id\": \"24601\", \"customer_id\": \"1213210\", \"product\": \"Wireless Headphones\", \"quantity\": 1, \"price\": 79.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"13579\", \"customer_id\": \"1213210\", \"product\": \"Smartphone Case\", \"quantity\": 2, \"price\": 19.99, \"status\": \"Processing\"},\n",
+ " {\"id\": \"97531\", \"customer_id\": \"2837622\", \"product\": \"Bluetooth Speaker\", \"quantity\": 1, \"price\": \"49.99\", \"status\": \"Shipped\"}, \n",
+ " {\"id\": \"86420\", \"customer_id\": \"3924156\", \"product\": \"Fitness Tracker\", \"quantity\": 1, \"price\": 129.99, \"status\": \"Delivered\"},\n",
+ " {\"id\": \"54321\", \"customer_id\": \"4782901\", \"product\": \"Laptop Sleeve\", \"quantity\": 3, \"price\": 24.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"19283\", \"customer_id\": \"5190753\", \"product\": \"Wireless Mouse\", \"quantity\": 1, \"price\": 34.99, \"status\": \"Processing\"},\n",
+ " {\"id\": \"74651\", \"customer_id\": \"6824095\", \"product\": \"Gaming Keyboard\", \"quantity\": 1, \"price\": 89.99, \"status\": \"Delivered\"},\n",
+ " {\"id\": \"30298\", \"customer_id\": \"7135680\", \"product\": \"Portable Charger\", \"quantity\": 2, \"price\": 29.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"47652\", \"customer_id\": \"8259147\", \"product\": \"Smartwatch\", \"quantity\": 1, \"price\": 199.99, \"status\": \"Processing\"},\n",
+ " {\"id\": \"61984\", \"customer_id\": \"9603481\", \"product\": \"Noise-Cancelling Headphones\", \"quantity\": 1, \"price\": 149.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"58243\", \"customer_id\": \"1057426\", \"product\": \"Wireless Earbuds\", \"quantity\": 2, \"price\": 99.99, \"status\": \"Delivered\"},\n",
+ " {\"id\": \"90357\", \"customer_id\": \"1213210\", \"product\": \"Smartphone Case\", \"quantity\": 1, \"price\": 19.99, \"status\": \"Shipped\"},\n",
+ " {\"id\": \"28164\", \"customer_id\": \"2837622\", \"product\": \"Wireless Headphones\", \"quantity\": 2, \"price\": 79.99, \"status\": \"Processing\"}\n",
+ " ]\n",
+ "\n",
+ " def get_user(self, key, value):\n",
+ " if key in {\"email\", \"phone\", \"username\"}:\n",
+ " for customer in self.customers:\n",
+ " if customer[key] == value:\n",
+ " return customer\n",
+ " return f\"Couldn't find a user with {key} of {value}\"\n",
+ " else:\n",
+ " raise ValueError(f\"Invalid key: {key}\")\n",
+ " \n",
+ " return None\n",
+ "\n",
+ " def get_order_by_id(self, order_id):\n",
+ " for order in self.orders:\n",
+ " if order[\"id\"] == order_id:\n",
+ " return order\n",
+ " return None\n",
+ " \n",
+ " def get_customer_orders(self, customer_id):\n",
+ " return [order for order in self.orders if order[\"customer_id\"] == customer_id]\n",
+ "\n",
+ " def cancel_order(self, order_id):\n",
+ " order = self.get_order_by_id(order_id)\n",
+ " if order:\n",
+ " if order[\"status\"] == \"Processing\":\n",
+ " order[\"status\"] = \"Cancelled\"\n",
+ " return \"Cancelled the order\"\n",
+ " else:\n",
+ " return \"Order has already shipped. Can't cancel it.\"\n",
+ " return \"Can't find that order!\"\n",
+ "\n",
+ "toolConfig = {\n",
+ " 'tools': [\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'get_user',\n",
+ " 'description': 'Looks up a user by email, phone, or username.',\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'key': {\n",
+ " 'type': 'string',\n",
+ " 'enum': ['email', 'phone', 'username'],\n",
+ " 'description': 'The attribute to search for a user by (email, phone, or username).'\n",
+ " },\n",
+ " 'value': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The value to match for the specified attribute.'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['key', 'value']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'get_order_by_id',\n",
+ " 'description': 'Retrieves the details of a specific order based on the order ID. Returns the order ID, product name, quantity, price, and order status.',\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'order_id': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The unique identifier for the order.'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['order_id']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'get_customer_orders',\n",
+ " 'description': \"Retrieves the list of orders belonging to a user based on a user's customer id.\",\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'customer_id': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The customer_id belonging to the user'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['customer_id']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " },\n",
+ " {\n",
+ " 'toolSpec': {\n",
+ " 'name': 'cancel_order',\n",
+ " 'description': \"Cancels an order based on a provided order_id. Only orders that are 'processing' can be cancelled\",\n",
+ " 'inputSchema': {\n",
+ " 'json': {\n",
+ " 'type': 'object',\n",
+ " 'properties': {\n",
+ " 'order_id': {\n",
+ " 'type': 'string',\n",
+ " 'description': 'The order_id pertaining to a particular order'\n",
+ " }\n",
+ " },\n",
+ " 'required': ['order_id']\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " ],\n",
+ " 'toolChoice': {\n",
+ " 'auto': {}\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "db = FakeDatabase()\n",
+ "\n",
+ "def process_tool_call(tool_name, tool_input):\n",
+ " if tool_name == \"get_user\":\n",
+ " return db.get_user(tool_input[\"key\"], tool_input[\"value\"])\n",
+ " elif tool_name == \"get_order_by_id\":\n",
+ " return db.get_order_by_id(tool_input[\"order_id\"])\n",
+ " elif tool_name == \"get_customer_orders\":\n",
+ " return db.get_customer_orders(tool_input[\"customer_id\"])\n",
+ " elif tool_name == \"cancel_order\":\n",
+ " return db.cancel_order(tool_input[\"order_id\"])\n",
+ "\n",
+ "def simple_chat():\n",
+ " user_message = input(\"\\nUser: \")\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": user_message}]}]\n",
+ " #messages = [{\"role\": \"user\", \"content\": user_message}]\n",
+ " while True:\n",
+ " #If the last message is from the assistant, get another input from the user\n",
+ " if messages[-1].get(\"role\") == \"assistant\":\n",
+ " user_message = input(\"\\nUser: \")\n",
+ " messages.append({\"role\": \"user\", \"content\": [{\"text\": user_message}]})\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"maxTokens\": 4096},\n",
+ " \"toolConfig\":toolConfig,\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " messages.append({\"role\": \"assistant\", \"content\": response['output']['message']['content']})\n",
+ "\n",
+ " #If Claude stops because it wants to use a tool:\n",
+ " if response['stopReason'] == \"tool_use\":\n",
+ " tool_use = response['output']['message']['content'][-1] #Naive approach assumes only 1 tool is called at a time\n",
+ " tool_id = tool_use['toolUse']['toolUseId']\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_input = tool_use['toolUse']['input']\n",
+ "\n",
+ " print(f\"Claude wants to use the {tool_name} tool\")\n",
+ " print(f\"Tool Input:\")\n",
+ " print(json.dumps(tool_input, indent=2))\n",
+ "\n",
+ " #Actually run the underlying tool functionality on our db\n",
+ " tool_result = process_tool_call(tool_name, tool_input)\n",
+ "\n",
+ " print(f\"\\nTool Result:\")\n",
+ " print(json.dumps(tool_result, indent=2))\n",
+ "\n",
+ " #Add our tool_result message:\n",
+ " messages.append({\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\"text\": str(tool_result)}\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " })\n",
+ "\n",
+ " else: \n",
+ " #If Claude does NOT want to use a tool, just print out the text reponse\n",
+ " print(\"\\nTechNova Support:\" + f\"{response['output']['message']['content'][0]['text']}\")\n",
+ "\n",
+ "# Start the chat!!\n",
+ "# simple_chat()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's an example conversation:\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As you can see, the chatbot is calling the correct tools when needed, but the actual chat responses are not ideal. We probably don't want a customer-facing chatbot telling users about the specific tools it's going to call!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Prompt enhancements\n",
+ "\n",
+ "We can improve the chat experience by providing our chatbot with a solid system prompt. One of the first things we should do is give Claude some context and tell it that it's acting as a customer service assistant for TechNova.\n",
+ "\n",
+ "Here's a start for our system prompt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "system_prompt = \"\"\"\n",
+ "You are a customer support chat bot for an online retailer called TechNova. \n",
+ "Your job is to help users look up their account, orders, and cancel orders.\n",
+ "Be helpful and brief in your responses.\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Don't forget to pass this prompt into the `system` parameter when making requests to Claude!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a sample conversation after adding in the above system prompt details:\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Notice that the assistant knows it is a support bot for TechNova, and it no longer tells the user about its tools. It might also be worth explicitly telling Claude not to reference tools at all.\n",
+ "\n",
+ "**Note:** The `=======Claude wants to use the cancel_order_tool=======` lines are logging we added to the script, not Claude's actual outputs!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "If you play with this script enough, you'll likely notice other issues. One very obvious and very problematic issue is illustrated by the following exchange: \n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The screenshot above shows the entire conversation. The user asks for help canceling an order and states that they don't know the order ID. Claude should follow up and ask for the customer's email, phone number, or username to look up the customer and then find the matching orders. Instead, Claude just decides to call the `get_user` tool without actually knowing any information about the user. Claude made up an email address and tried to use it, but of course didn't find a matching customer.\n",
+ "\n",
+ "To prevent this, we'll update the system prompt to include language along the lines of:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "system_prompt = \"\"\"\n",
+ "You are a customer support chat bot for an online retailer called TechNova. \n",
+ "Your job is to help users look up their account, orders, and cancel orders.\n",
+ "Be helpful and brief in your responses.\n",
+ "You have access to a set of tools, but only use them when needed. \n",
+ "If you do not have enough information to use a tool correctly, ask a user follow up questions to get the required inputs.\n",
+ "Do not call any of the tools unless you have the required data from a user. \n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a screenshot of a conversation with the assistant that uses the updated system prompt:\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Much better!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "attachments": {
+ "conversation7.png": {
+ "image/png": "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MC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTA4MjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yNzM2PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6VXNlckNvbW1lbnQ+U2NyZWVuc2hvdDwvZXhpZjpVc2VyQ29tbWVudD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CgIHbDIAAAAcaURPVAAAAAIAAAAAAAACHQAAACgAAAIdAAACHQABq7w5EpFoAABAAElEQVR4AezdC7xd04E/8CUTEuqZiKhWxCMolf6RTlszWoZO/y0hxDBVRKr405Sgod6vMNJpGtpKSuv9DlHj0b9+mvxNyxhCvZMgEeodggSVCpV/157Ze/bZOefec+/Z595z47s/n/bsx9prr/3d6+xzT/zO2iutv/76y4KJAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBcJrCTA2kXSDkOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJAICLDqCAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAl0qIMDapdwORoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgIMCqDxAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECHSpgABrl3I7GAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgACrPkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINClAgKsXcrtYAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgKs+gABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECXCgiwdim3gxEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAiw6gMECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJdKiDA2qXcDkaAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDAqg8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAh0qYAAa5dyOxgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIAAqz5AgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQpQICrF3K7WAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQICrPoAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAlwoIsHYpt4MRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgIsOoDBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECXSogwNql3A5GgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAgwKoPECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIdKmAAGuXcjsYAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQICAAKs+QIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0KUCAqxdyu1gBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECAqz6AAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJcKCLB2KbeDESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQICLDqAwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAl0qIMDapdwORoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgIMCqDxAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECHSpgABrl3I7GAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAgACrPkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINClAgKsXcrtYAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgKs+gABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECXCgiwdim3gxEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAiw6gMECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJdKiDA2qXcDkaAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQICDAqg8QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAh0qYAAa5dyOxgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgIAAqz5AgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQpQICrF3K7WAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQICrPpAywhMnDgxa8uNN94Y7rvvvmy5p85ccMEFYdVVV02aP3369DB16tSeeiraTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEShNoKMB6zDHHhI022ihrzNlnnx3eeOONbLk4M2jQoHDsscdmq+++++4wbdq0bNlMawmcdtppoV+/fkmjPvjggzBu3Lg2Gzhw4MBw4oknZmXmz58ffvKTn2TL7c3cfvvtWZEYXh0/fny23FNnbr311tCrV6+k+fPmzQtjx47tqafSUu2eMGFC6NOnT9KmRYsWhTPOOKOl2qcxBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINC2QEMB1iuvvDILOMbDHHnkkeH555+vecSRI0eG0aNHZ9sfeuihEEOSptYUuOWWW0Lv3r2Txi1btiwMHz68zYYOGTIkTJo0KSuzcOHCcPDBB2fL7c20YoB18uTJYZVVVkmaPnPmzHDxxRe3dxoV2wVYKzhKW8j3laVLl4a99967tLpVRIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLNFxBgbb5xjz2CAGsIt912W1hppZWSazhnzpx2R6EtXmwB1qJIOcsCrOU4qoUAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLdJSDA2l3yPeC4XR1gveKKK7IRX6dPnx4uu+yyblcSYO32S1C1AQKsVVmsJECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQI8REGDtMZeq6xva1QHWrj/D9o8owNq+UXeUEGDtDnXHJECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQHkCAqzlWa5wNQmwhiDA2prdWoC1Na+LVhEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBegZYPsO6///5hiy22CAMGDAhrrrlm+Mtf/hLefvvtsGjRovDggw+Gf/u3f6v3XJNyn/nMZ8J2220Xttxyy7DhhhuGjz76KLz44oth1qxZ4Z577gkvvfRS3fWNHDkyKxsfeb948eJkediwYWGvvfYK6623XlhttdXCO++8E1599dUwderUMHv27GyfajM777xzcp75ba+//nq4995786u6ZL6ZAdahQ4eG/v371zyPZ599Njz33HM1tzdjQ/56pvWPHj06nQ2vvfZauOOOO7Ll/Mwf//jHpD/m18X5W2+9NfTq1StZPW/evDB27NhkftSoUSH2k7XWWivpgy+88EJ45JFHwrRp05Lt9f5fq/fnMtuXNxFgzWuYJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQM8TaNkAawz4jRgxIqy88srtqsbg6XnnndduucmTJ4dBgwbVLLds2bJwww03hKuvvrpmmXTDpz71qXDRRReli2HGjBlh0qRJ4dJLL02Cq9mGwsxDDz0UTjvttMLa/1nMB/PStW+88UaIHl09NTPAmq+72nndd999Yfz48dU2NW1dNft6DxbDtmPGjFmueDHAOmHChBD7Ya1+/fLLL4fDDjtsuXqqrWj1/lxm+4rnn79WS5cuDXvvvXexiGUCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQaGGBlgywfvvb3+5QIK1WeDB133HHHcOxxx5bMzSYlktf8yNlpuuKr8UAawzRbrvttuETn/hEsWjFchzFM55frSkfzEvLCLCmEs19rWZf7xFr9cF8gDWO7htHne3bt2+b1b7yyivh0EMPrVmm1ftzM9pXxMhfKwHWoo5lAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItL5ASwZY8+G0SLh48eJw//33h1dffTUJ/2200UZhww03DBtssEEiXCs8GDcOHDgw/PKXvwwrrbRSUjb+30cffRSeeuqpMH/+/KS+IUOGLDcya3yU+2WXXZbtU5wpBlhjnemj4mPZDz74ILz55pvhvffeC/369Qtrrrlm0gYB1v+SPPPMM8Maa6yRsUa7zTbbLFvujhFYjznmmORaZY3460wMJadTvJax31SbHn/88TB16tTlNuUDrPmNsR8888wzSZ/Zeuutw+qrr57fHGJb5s6dW7EuLrR6f25W+4oQ+XuEAGtRxzIBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaX6DlAqwHHHBA+Od//udMLgYDTzzxxGw5PxPDcnGkyrfeeitceOGF+U3Z/Pnnn18RjIzBwVjfggULsjJxZpdddglHH310FkKNgdQDDzwwCc9WFPzvhWKANS3z4YcfhgsuuCDcdddd6arkdd111w3HH398ElQ88sgjK7blF/LBvHR9K4zAGtuybNmytEk1X/NB4YULF4aDDz64Ztnihvy5d0eAtdieuHzbbbdl4ec5c+aEcePGVStWc10xwBoNL7/88hAD0vnpZz/7WRg8eHC26rHHHgsnnXRStpzOtHp/blb70vNPX/N9RYA1VfFKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBniPQcgHWs846K2y33XaZYAwMxuBgZ6Zhw4aFM844I9v1z3/+c9hnn32y5eJMMTx77733hnPPPbdYLFmuFmCNo67GQG0MbnZ2ygfz0jpaJcCatqfeVwHWEIoB1lrB3GJ/qjZSb6v352a2r9jn8u+T999/P4wcObJYxDIBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItLBAywVYY+A0BuHS6eabbw6XXnpputih14kTJ4Ytttgi22fChAnh7rvvzparzdx0002hb9++yaZqIcJ0n2LgMK5vpK1pvflgXrpOgDWV6PrXskdgHTVqVIjXs9p03XXXhTXWWCPZ9N5774V99923olir9+dmtq8C4q8L+etSzapY3jIBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItJZAywVYY8Dvn/7pnzKlOLriOeecEx566KFsXb0zV111VVhnnXWy4vHR7fER7umUf9x9r169ktV77LFHWHvttZP5Dz/8MIwYMSItXvFaDLC2VbZix3YWhg4dGtZcc82KUm+++WaYPXt2xbquWLjllltC7969s0Nde+212Xy1mQ033DDsuOOO2SYjsFaOwNreCMC//OUvw/rrr5/4VetPrd6fm9m+rFP990y+b7711lvhwAMPLBaxTIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQItLNByAdZBgwaFCy+8MOTDpdFvyZIl4dlnnw0PP/xweOCBB8K8efPaZc2H3NotXKNArREziwHWjoY1axyupVbn/WLwd/jw4W22b8iQIWHSpElZmY6a5Eefve+++8L48eOzurprJj/S55w5c8K4ceM61JRbb701pOHotkb0jZWef/75YbPNNkvqr+advx4dakSucDP7czPblzuFZDY/UvLLL78cDjvssGIRywQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQwgItF2CNVkceeWT4xje+0SbbBx98kIxKGkN/r7/+etWy+UBk1QJ1rIxtef7555crWQywPvXUU+G4445brlxPXpEPJFYLVBbPTYC1KFI5Auv8+fPDUUcdtXyh/17TXoC11ftzM9tXRLv66quzkZJjmH3s2LHFIpYJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoIUFGgqwXnLJJWHgwIHZ6dUKe6YFRo4cGUaPHp0uhgcffDCcccYZ2XJ+ZrfddgsHH3xwWHXVVfOrl5uPj1o/77zzQhyxMz/FkVwnT56crYqB1yeeeCJbrnfmRz/6UVi8ePFyxYsB1rvvvjtMmDBhuXI9eYUAawhljsDaXtCyrQBrq/fnZrev+D765S9/GdZff/1k9SOPPBJOOeWUYhHLBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINDCAg0FWC+99NKw3nrrZac3ZsyY8Nxzz2XLxZligPWee+5JwqfFcvnloUOHhl133TVsvvnmSWCtd+/e+c3J/Pvvvx9i3cUpPyLkO++8E775zW8Wi3R6uRhgnTFjRpg0aVKn62vFHQVYWyfAGvtHq/fnZravFd8f2kSAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECnRdoKMA6ZcqUsOGGG2ZHj4/xjqNM1pr23XffcNBBB2WbOxP63H777cMhhxwS4oiP+emqq64KN9xwQ35VmDZtWujTp0+yLo7Autdee1Vsb2RBgHV5vSFDhlSEeBcuXJiMort8yepr8gHIOKLu+PHjqxfswrWtMgJrPOVW78/NbF8XXnKHIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEuEGgowJp/5Hls68knnxweffTRms0ePXp0xUipMRx40UUX1Szf1objjz8+fPnLX86KVAs8FkeI3X333bPyjc40K8AaQ5vFUWYfeOCBJLzYaJs7ur8RWCtHYJ07d2445phjOsR46623hl69eiX7xHB3DHnXmvLvp2XLloXhw4dXFG31/tzM9lVAWCBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBHi/QUIB13Lhx4Stf+UqGcO2114b4v1rT2WefHbbddtts8wUXXBB++9vfZssdmenfv3+44oorsl3mzJkTYnvyU/F499xzTzjvvPPyRTo936wAa34U0rRxb7zxRhg1alS62GWvAqwh/OpXvworr7xyYv7aa6+Fb3/72x3yLzPA2ur9uZnt6xC6wgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQ8gINBVjjCJGHH354dpJvv/122H///bPl/MygQYPCT37yk4rRRQ855JCwYMGCfLEQy8V6Fi1aVLG+uPDVr341HH300dnqO+64I0yZMiVbjjMxZPrzn/88rLTSSsn6OKrlYYcdFl555ZWKctUW9tprryS8WG1bXCfAurzMkCFDwqRJk7INCxcuDAcffHC23N5MPrxbbUTd9vZvxvarr746rL322knVH330Udhjjz06dJgyA6yt3p+b2b48+siRI8Nuu+2WXxWuueaaMGPGjIp1FggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgdQUaCrDG05o6dWpYbbXVsjNcvHhxOPXUU8P8+fOzdX/7t38bTjrppIrw6nPPPRfGjBmTlUln4qism266aYjbr7/++hBHTS1On/vc58KZZ55ZUd9ZZ50VZs6cWSwavv/974eddtopWx9DiLHNMZhYnGIAb/To0WHYsGFJ3fGR7tOnTy8WS5YFWJdnWREDrLEPbLbZZtnJvvrqq2HChAlh7ty52bq2ZsoMsMbjtHp/blb78sann356+PznP59flbynr7zyyop1FggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgdQUaDrDusMMOSTi1eIoxKLpkyZIk3JqOgJqWidvi6Kuvv/56uip7/elPfxo23njjbDmWfeedd8Kbb74Z4vy6664b1lprrWx7nGlvpM9p06aFPn36VOzz4YcfhnfffTfE1969e4fVV1+9IhAbCwuw3pKZxNFr44i7bU31BFhj8DeO0tqrV6+KqmIfyV+jeK2XLl1aUSYuPPnkk+GUU05Zbn2zVmy99dZJYLVa/bHvpNOcOXPCiSeemC5mr2UHWGPFrd6fm9G+DPSvMwKseQ3zBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6JkCDQdY42mffPLJ4Utf+lJdAjEIedVVVyUjJlbboRhgrVYmvy6GHGMY9q233sqvrphfZ511wtlnnx0GDx5csb69BQHW8gOscXTbM844oz36mttfeOGFcMQRR9Tc3owNp512WoijCLc11RpRuBkB1lbvz81oX95egDWvYZ4AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQI9U6CUAGs89W222SaMGzcu9OvXr6bE/PnzwznnnBMWLFhQs8wuu+wS9txzzzBo0KBs9M9qheMInf/xH/9Rc3TMavvEeg866KCKkT6L5WK9sZ0zZswIt912W3Fztty/f/9wxRVXZMuxfBxZtNEpHrM4Yu0bb7wRRo0a1WjVHd7/lls6FmD99Kc/HX7+859nx3n55ZfDYYcdli3HmZ4YYI3t3nXXXcOIESPCBhtsEFZeeeXlrtFTTz0VjjvuuFi0YupsgDWO7hqP19bU6v25zPblHaoF5qdOnRquvPLKfDHzBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINDCAqUFWNNzHDhwYNhqq63C5ptvnjwmfsmSJeHpp58Os2bNCosXL06L1fUaH0kf64mhwb59+yahwVdffTUJmD744IN11VGr0Be/+MWknbHeOCrsSy+9FOIomo899litXawn0LICrd6fW719LXthNYwAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIrqEDpAdYV1MlpESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIlCQgwFoSpGoIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTqExBgrc9JKQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZIEBFhLglQNAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAfQICrPU5KUWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFCSgABrSZCqIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqE9AgLU+J6UIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRKEhBgLQlSNQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAvUJCLDW56QUAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBASQICrCVBqoYAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKA+AQHW+pyUIkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQKElAgLUkSNUQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUJyDAWp+TUgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAiUJCLCWBKkaAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB+gQEWOtzUooAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAkAQHWkiBVQ4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUJ+AAGt9TkoRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiUJCDAWhKkaggQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoTEGCtz0kpAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBkgQEWEuCVA0BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEB9AgKs9TkpRYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUJKAAGtJkKohQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCoT0CAtT4npQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBEoSEGAtCVI1BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC9QkIsNbnpBQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBJAgKsJUGqhgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoD4BAdb6nJQiQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoSUCAtSRI1RAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECNQnIMBan5NSBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECJQkIsJYEqRoCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIH6BARY63NSigABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoCQBAdaSIFVDgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQn4AAa31OShEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECJQkIMBaEqRqCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE6hMQYK3PSSkCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGSBARYS4JUDQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQH0CAqz1OSlFgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQkoAAa0mQqiFAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEKhPQIC1PielCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEShIQYC0JUjUECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQL1CQiw1uekFAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQEkCAqwlQaqGAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgPgEB1vqclCJAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEChJQIC1JEjVECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI1CcgwFqfk1IECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIlCQiwlgSpGgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgfoEBFjrc1KKAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgJAEB1pIgVUOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFCfgABrfU5KESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIlCQgwFoSpGoIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTqExBgrc9JKQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZIEBFhLglQNAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAfQICrPU5KUWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFCSgABrSZCqIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqE9AgLU+p6zUBRdcEFZdddVkefr06WHq1KnZNjMECBAgUL9AV95PJ06cmDXsxhtvDPfdd1+23FUzn/nMZ8IxxxyTHe6iiy4Kf/jDH7LlMmda4XzLPB91ESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIrHgCnQqw7rDDDmHfffctTePCCy8Mc+fOLa2+ZlZ06623hl69eiWHmDdvXhg7dmyHD/e9730vDBgwoGK/GKh6/PHHK9YVFwYNGhS+853vZKuffvrpcPXVV2fLZsoV+MpXvhL22Wef0L9//7D66qtn1/3DDz8MS5YsCc8//3y46667wp133lnugdVG4GMiUMb9tF6q22+/PSsaw6vjx4/PlrtqZscddwwnnHBCdrg77rgjTJkyJVsuc6YVzrfM81EXAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDAiifQqQBrDGB+7WtfK01jwoQJ4e677y6tvmZWVEbg6pZbbgm9e/euaOYrr7wSDj300Ip1xYVDDjkk7LXXXtnqevbJCpupW2Dw4MHhBz/4Qfj0pz9d1z7Lli0LP/zhD3tMH67rpD4mhSZPnhxWWWWV5GxnzpwZLr744o/JmZdzmo36lXE/rfdMWiHQKcBa79VSjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBA4OMgIMDawatcRuCqWoA1NiOOzDdr1qyaLRJgrUlT2oaBAweG+FjvYsC4vQPE4GPsG6aeJXDbbbeFlVZaKWn0nDlzwrhx43rWCXRzaxv1K+N+Wi+BAGvXjzhb77VRjgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBA4OMp0KkA6/Dhw8OIESNqiq299tqhT58+2fY//elP4d13382WizMTJ04Ms2fPLq5uyeUyAle1AqzPPfdcGDNmTM3zFmCtSVPahquuuiqss846FfXNnTs3/Od//md4/vnnk22bb7552HjjjcOmm26ahR8FWCvIesxCowHMHnOiTWpoo35l3E/rPbUrrrgiC6ZPnz49XHbZZfXuWlq5rhyBtRXOtzQ4FREgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECKyQAp0KsLYncfrpp4fPf/7zWbHrrrsuXHPNNdlyT54pI3BVK8AaXY466qgwf/78qkQCrFVZSlu52267hSOOOCKr76OPPgrHHXdciAHWWtMPfvCDsMMOO4Sf/OQnIYbiTD1LoNEAZs862/Jb26hfGffT8s+qeTV2ZYC1eWehZgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLlCAiwdtCxjMBVWwHWp556KglNVmuWAGs1lfLWnXPOOeFzn/tcVuHPfvazcOedd2bLZlY8gUYDmCueSMfOqFG/Mu6nHWtx95YWYO1ef0cnQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBoLYGWD7B+5jOfCdttt13Ycsstw4YbbhjiqJgvvvhimDVrVrjnnnvCSy+91GHRgQMHhu233z5sscUWYfDgwWHdddcNS5YsCa+99lqYN29euPTSS2vWWStwNWrUqDBs2LCw1lprJW184YUXwiOPPBKmTZu2XF3FAOvSpUvDKquskpWLQdUFCxZky+lMZwKsX//618PWW28dNtlkk7DaaquFRYsWhWeeeSY89thj4Xe/+11a9XKv22yzTdh8882z9dXOI9uYmxk0aFDF6Lu19hswYECII57GdvXr1y9x+8tf/hJefvnlZMTTxx9/PDz44IO5mps/e/3114fVV189OdCyZcvC8OHDGz7orrvuGvr06ZPU89BDD4VXXnmlZp3RPPrF6cMPPwy/+c1vlis7cuTIbN3TTz8dolPcZ6eddkreJ7EvR8N4fX//+9+H559/Pitfbabs+orH6Gz/K9YTl/NtjaPdLl68OCkW33d77bVXWG+99ZI+/s4774RXX301TJ06NcyePTurKr9/unL06NHpbPL+v+OOO7Ll/Mwf//jHuvrjzjvvHNZcc838ruH1118P9957b8W6Vl+I98gDDzwwxPvYDTfckDS3GX5l3E+rWQ4dOjT079+/2qZk3bPPPhuee+65mtvTDfEekN6bH3jggez91JH7fVpXfO1ogDX26169emVV1Lqftur5Zg3/60z8cUAcrTp+HsXPydi34j0+fg698cYbyX1s0003TXaJ7+H8/T+OjB0/Jy+55JJ8leYJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgR6uEBLB1gnT56cBfqqOceQYQxXXX311dU2V1139NFHh69+9atVt6UrY71PPvlkGDduXLoqey0GriZMmBBiO1deeeWsTH4mhgkPO+yw/KpQDLDefPPNYe+9987KxODrKaecki2nMx0JsMag1HHHHRd69+6d7r7c67vvvhtOOumkMH/+/OW2FY8Vg31TpkxZrlxxxaRJk8KQIUOy1aeeemp4+OGHs+UYgov/K4b8sgK5mRgqju2bO3dubm3zZuN1SMNqMSi9xx57NHywYn8ZO3ZszTrPP//8sNlmmyXbawVob7/99mz/GFJ94oknwv7775+tK87cdNNN4fLLLy+uzpbLri+tuNH+l9aTvn7qU58KF110UboYZsyYEWJfi2HzGFytNcXQ8GmnnZZszp9rrfK11sew45gxY2ptztZXO0YM58XAY0+Y/vf//t/JvWiDDTZImpu/F1U7t3rPqZZf8f3RmftptTYU77HFMvfdd18YP358cfVyy2W3ryMB1l/+8pdh/fXXz9r05z//OXz3u9+t+uOGVj3ftPHnnntuiCHbalO8151++ukh3hvjjxni9Kc//Snst99+WfErr7wy2RbLxuD+ddddVxFwzQqaIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6FECLRlgjSGfY489tmYotCgcR01tKxgYy8dg4JlnnpmM/Fbcv9bykUcemY24l5bJB5ri6K9xlL++ffumm6u+xlE3Dz300GxbMWx0wgknJEHNOCpdnGJIJ45+GEdLzU/FUGmx3rTsMcccE3bZZZd0sc3XeKxf/OIXIZ5Xfoptueaaa7JVsS0HHHBAtlxrJu/z/vvvV4yaGfeZOHFiMvJtrf2L62P7LrvsshDDpc2e4vmm1yAe6+STTw6PPvpoQ4fNe7TXTzsaYI2+6eiubTVy5syZ4ayzzqpaJB9KLKO+eJAy+l+xscUAaxx9edtttw2f+MQnikUrluOoyt/+9reTdflzrShUx0KtAGZx12rHaPUAa7SN95svfOELy91zuzLA2tn7afEaxOXiPbZYpjMB1jLaV2+ANYbO42jK6fTee++F+Hm0cOHCdFXFa6ueb2xk/Hz55Cc/WdHe4kIccTr+aCD9AUGtAGt+v1jm3//93+v6YUV+P/MECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKtI9ByAdb46Oo48txKK62UKcVgy1NPPZWMFBrDonGEz/RR62mh+GjlGHSsNd14441h1VVXrdj85ptvhvho8BhOi4+032ijjUIMc6WPbG4vwJqvLAblnnnmmWTf+Ijk9FH0aZkY6ktHEi2GjWKANR47Hi+d/vM//zOcc8456WLyWk+AdbvttlsurBhH7osjysYgXTy/GObNj8xaa7TRiy++OKQjMcYGHH744SGGuGpN8XHbsUw6xZDheeedly4mr/kAazxufNT7ggULksdJxxBTPF4MJhaDmUcddVTVkWIrKm9wId+2WFV0iyPhRrvOTs0MsObbFEf6nTNnTuIW+98666yT35wEh++6666KdXGhWuAyru9sfWX2v9iOdCoGWGPfSd+nscwHH3wQ4vs5Bv3iKI5xhN94D8kHWON7MB3hMa039rV0ivvG+0y16fHHHw9Tp06ttqliXTXPVg2wxhGG99xzzxDvubWm/Hu4GX7590e+DR25n+b3S+fjjxXWWGONdDHpK+noxnFlZwKsWWV/nels++oJsF511VUV79+33347HHHEEWHx4sX5JlTMt+r5xlHAd95554q2RrvZs2cn6z772c9WBHXTgsUAa/GzKC0XX+OPHOIo4nE09nvvvTe/yTwBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgECLC7RcgDU/CmW0i2GXE088cbnHJscRRo8++ugsxBYDbXEUwWohnxgM/cY3vpFdihh4iSPcxdBrcYojcMbHGW+++eZJoPT555+vKFIMXNWq62c/+1kYPHhwtm983PtJJ52ULFcLsM6aNSsJ4KQjSlYLldYTYC0+djoGRL/zne9k7YgzMbAW25cP9OaDamnhkSNHhtGjR6eLYfr06SFen1rT5MmTK4LF1UKnZ599dmJ75513thk4juXy4cIYIIz9oJnTbrvtlgTFisd44YUXwu9///vw61//umr/KpbPL+f7S9kjsKbHqRbeLj6yO76P0pFI0/3ia7XAZSP1ldn/8u0sBljTbTH0fMEFF4RiODeOXnn88ccnQfJ8MDzdL3297bbbsrB8DACPGzcu3dSp12qerRRgjcH/gw8+OMSgcT7Enj/ZeO+JAcMYCHz44Yfzm5abb9Qv//6IlXfmfrpco2qsyF+bzgZYG21fWwHW+NkzZcqUJHydnsJbb72VfK6lyx15bYXzLX7WxXto/JzIT/FzcYcddsivCsUAa9y46667hhEjRiQ/9sj/wCW/Y/zRQbxXxxBwtDMRIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAi0tkBLBViHDRsWzjjjjEwshlH22WefbLk4Ex9p/8///M/Z6jj6Wgzu5acYZLv00kuzoGvcFo/x4IMP5ostNx8DNdVGcysGrmoFoYqBu3yAsBjqiSOwxgDrvvvuGw466KCsLTNmzAiTJk3KltsLsMbAZwx+plMclXKvvfZKFyte4yOd46Od06laYDZuywfU3n333QrvdN/0NV82jhq4//77p5s69XrzzTdnj5Ru61w6VXmNnX7+85+HT3/60zW2/teorHG0vxjyvP/++2uWSzfk+0szAqyx38T+U2269tprK8JwMSgWg9T5KR9yi+sbqa8Z/S9ta/H9FNfHPnHooYfWfKx6um9br/k+uyIHWGMYPY6QnH8sfdEljoQcA4bVgv3Fsulyo37590esszP307Qt7b3m+3qt4xTrKLt9tQKs/fv3T4Kd6Q8YYjvynxnFdtWz3N3nW/zhSFv3vyuvvLJidORqAdb8OcfPwn/4h38IMfRba4o/Pokh7N/97ne1ilhPgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQzQItFWAtPsJ9woQJ4e67726T6Kabbgp9+/ZNylQL/MRRJ/fee++sjpdeeqniMffZhjpnioGmUaNGhTjCYrXpuuuuyx5jHR9PHgOqcaoVYI3bYnisT58+cTbE0SXjiHPp1F6A9fvf/37Yaaed0uKh2qiq2ca/zhQfyxxHsvztb3+bL5KMuJp/9PbYsWNDDCIVp/32269ipMBqI+0V92lvuTiK7e67797eLg1vj4Goc845p2L03FqVxoD1jTfemISkapXJ95e2Alxx//zow3Gkxxg4LE75UFrcdvLJJ4dHH320WCxZPvzwwyvqqNYfyqyvGf0vPbFqAdYYcI7h9EamRgOYxWMXPeP27hqBNb5vYyB+6NChNUdbXbJkSRLUj2HnGGDt6NSoX/79EY/dmftpvW3OX5vOBlgbbV+1AGvsxxdeeGH2ORbP5+WXXw6HHXZYvadWtVx3n298b6633npZ29r64cg3v/nN8K1vfSsr216ANS04ZMiQ5IcSMTxfa0Th999/P/zHf/xHMirr66+/nu7qlQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoAUEWirAGh/7u84662Qsl19+efJI6XRF/rHBvXr1SlbvscceYe21107mi4HPuLL4KPq4XM/ImUmFVf4vH7hqb4TY/OPU821rK8A6evToEEdLTKcYELvooouSxfYCrD/60Y/Clltume4aaoVN0wLFEV9/9atfhUsuuSTdnLzGxzbHetKpWggyboujucZRXdMpPqZ84cKF6WKbr5tssknyWOj1118/e5x73CGGcTfYYINs364IsKYH23PPPZPRf/P9Md1WfH3qqafCcccdV1ydLOf7S9kB1hjMyveVYgNi2+N7Kp2efvrpcOyxx6aLyWs+5NZofc3of2ljiwHW/PspLdOZ10YDmMVjxrDommuuWbH6zTffDLNnz65Y1+yFH/7wh2Grrbaqepg42vKTTz4Zpk6d2u5I1FUryK1s1C///ujs/TTXnDZn8329MwHWMtpXDLDGz6L/9b/+V/aj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JZ9V8+bNq9jHAgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQM8TaLkAaySsNvpmDK68++67Ib727t07rL766hUj1MX9agVY47b4aPQNN9wwzlZM7733Xvjzn/+chLXiSIT5IE0rBFhjY4shsfQEqgVYi6NgpmXjeS5atCj0799/uXBoPaOvpvXUepRze48aj/vHcPAZZ5yRVpW8xusZR3Lt27dvEhoujgCZL9yVAdb8cWOYNAaqYt+I7cz3kbRcHDEx9ttq02233VYRFo71xYBsfI0h03yQON2/IwHWuE8M0L799tvhb/7mb5L3RrHOGIarFsrMh9zSYzdSX7P6X7MCrHH0xxhYrTbFvplOc+bMCSeeeGK6WPO1mmdPCrDmTyyOfj1//vyqPwpIyzXqV3aANfaTSZMmLfceje+HfCg+vl9i6L44xUfQ50ecLbt9O+64YzjhhBOyw7Y1GviZZ54Ztt9++6xs7I/f+c53klGS05Wtfr5bbrll+OEPf7jc9UjbX+u1GGCNI7e+8MILNe+xteqxngABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoLUFWjLAGh+hHEfhHDx4cIf02gqwxopOPfXU8IUvfKHuOlslwDpkyJAklFVseLUAayzz93//98lItjHo294UQ8EnnXRSElRrr2zcvv/++yf/K5aNI+fG8Fd7UzzWDjvs0F6xJFwWQ4Of+9znsrLdFWDNGlBjpr3w7g9+8IPkmtTYPVn9zDPPJIHWdDTQegKsMfgbR8Vt6zrHeuIoiPFR29WmfOCyjPriMZrR/5oVYI3tPe2000IcebStqdqotNXK5z3T7T01wJq2v73XRvzKDohWC8m31/789hiSPOKII7JVZbevIwHW2Ijrr78+CaSnDXrttdfCt7/97XSx6o8Cso11zDT7fGMT4udXDImvssoqNVsU31/xByTxsz9OxQBrzR1tIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6NECTQmwHn/88eHLX/5yBnPdddeFa665Jluud2bPPfcMBx10UMXIecV940h6cZTAGTNmhDjSZXtTHNEuhi3XWGONmkXffPPNcMstt4Sbb755uTKdDTTF0fNGjBiR1PerX/0qrLzyylndY8aMCTHA09ZUbQTZWgHWWE8caTU+mv6Tn/xk1WpjsPGJJ56oa1TJYgXFEUU7GjbaZ599wgEHHFAzePnss88moyCOGjUq/OM//mN2+N133z2bb9bMyJEjw8477xwGDRrU7qiBMfx1wQUX1BXcjY/JHj58eNVmx/571FFHVYy0m+8v+Z3yAcn4KO0YcDv99NOrvkfiyMJxFMfHH388X0XFfNn1pZWX3f9ifVdccUVaffJ+jyNtljXtuuuuyftzgw02SN6bxRFsn3rqqXDccce1e7jieyPusKIHWOM5dtavjPtpPH46tUqAtdb794tf/GLFCK9tjcAazymGP3/84x9XjNJ85ZVXhqlTpyan3Ornm16XGLSP75+NN944C+RGoxiav//++0McwTqeUzoCdzGom9bjlQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYMUSaEqAtRlEMfiz1VZbJY9wj+HLl156KQl9xhBfZ6c4uudnP/vZsNFGG4VFixYl9cVQ5/PPP9/ZKltyvxjaHTp0aGK3ePHi8PDDD4c4uml3T/GaxkdMx9E133nnnSTM9Nvf/ja89dZb3d205PjbbLNN2HDDDZMQ8IABA8L777+f9I0YNp43b16Ilh2Z1l577WTExNiPP/jgg+Scf//733eovxUDp3FE2zgNHDgw7LLLLkkwO4a/7r333rBgwYJ2m1d2fdUO2Kr9r1pbrSNAoPkC8QcCxc/ZfJh51qxZ4YQTTmh+QxyBAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgWwV6TIC1W5UcnECLCNQKnHa2eWXX19l22I8AgY+vQPwRw0UXXZQBxB8yxNGtTQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAiu2gADrin19nd0KJlB24LTs+lYwbqdDgEAXCPzLv/xLiCNep9OkSZPCjBkz0kWvBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECK6iAAOsKemGd1oopUHbgtOz6Vkx1Z0WAQGcFpk2bFubNmxeuv/768PDDDy9XzRFHHBF22223bP2iRYvCAQcckC2bIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQWHEFBFhX3GvrzFZAgbIDp2XXtwKSOyUCBBoQyN9j3n///fDmm2+GhQsXhjXWWCOsv/76oW/fvhW1n3XWWWHmzJkV6ywQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAismAICrCvmdXVWK6hAPgz22GOPhZNOOqmhMy27voYaY2cCBFY4gfw9pq2TW7ZsWfj1r38dpkyZ0lYx2wgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBFYgAQHWFehiOpUVXyAfBvvDH/4QTj/99IZOuuz6GmqMnQkQWOEEJk+eHDbYYIPQu3fvmucWR2U9++yzw9y5c2uWsYEAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDFExBgXfGuqTNagQWGDRsWevXqlZxhGY/ZLru+FZjeqREg0IDAJptsEoYMGRIGDBgQ+vXrFxYuXBhmzZoVHn300QZqtSsBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBPFhBg7clXT9sJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAj1QQIC1B140TSZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9GQBAdaefPW0nQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQAwUEWHvgRdNkAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBPFhBg7clXT9sJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAj1QQIC1B140TSZAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI9GSBlguwXnDBBWHVVVdNTKdPnx6mTp3ak321vYcJ6H/Nu2AXX3xxVvnll18e7r333mzZDAECzRU4+eSTw0YbbZQc5Mknnww//vGPm3tAtfdoge7oLz5/e3SX0fgWEuiO928Lnb6mEGiqwMSJE7P6b7zxxnDfffdly52d2W233cJWW20VPvWpT4XVVlutoprjjz8+LFq0qGJdWwvNaF9bx7ONAAECXSng+0JXajtWRwR8/nZES1n9RR9Y0QTK/D7TCjb+3miFq7BitKHZ9/tW//e/Vm/fitDL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16p3795mHxG/BObOnatWrVqlZs2aFSz3bN9t0KBBqmfPniaZllc9+eSTzT4iIAACIAACIAACIAAC5QRoiU3qM3Xr1s0c/Pbbb1WvXr3Mfm2IYECrNmgRZSgCAThcFUEL2WSoK/Y+Gx1cBQL5E4A9zZ857lj7COB7ce3TKUoEAlkI4H0/CzVcAwIgAAIgAAIgAAIg4IsAHFh9kUW+IFDHCDRr1qxk+VQqfsOGDcsoLFiwQE2ePLksHQl+CPCPEF999ZXasGGDWrdunWratKlq1aqVaty4ccmNx44dq5YtW1aShh0QAAEQAAEQAAEQAAGldt55Z3XLLbeoevXqqUaNGpUh+etf/6quv/76svRqTuB9yeeff16NHj26mosD2UGgxgjA4arG0Ge6cV2095lA4SIQqAECsKc1AB23rHUEeB8f34trnXpRIBBITIDbArzvJ8aGE0EABEAABEAABEAABDwRgAOrJ7DIFgTqGoHmzZuru+++O7bY69evV/379489BwdlCfCPEHE504xh5Fxcm5a8jSsvjoEACIAACIAACIBAWgK77rqruvXWW0Mvq62DPbwvWVvLGKpQJIKAMAE4XAkD9ZxdXbT3npEiexAQIwB7KoYSGdVhAryPH4cB34vj6OAYCFQ/AW4L8L5f/fpECUAABEAABEAABECg2gnAgbXaNQj5QaAgBOIcWDdv3qyWLFlS62akKgj6WDFotts2bdqoBg0aRJ5Hs7LSAMBrr70WeQ4OgAAIgAAIgAAIgEBdJxDm0PSvf/1LLV++XF133XW1Eg8f0HrmmWfUmDFjamU5USgQ8E0ADle+CcvmXxftvSxB5AYC/gjAnvpji5zrDgF8L647ukZJQSCOAN734+jgGAiAAAiAAAiAAAiAQN4E4MCaN3HcDwRqMYEf//jHJaX797//rWigG6HmCXTo0EF17NhR7bjjjqpFixZq3bp16sUXX1TPPfdczQsHCUAABEAABEAABECgSgjo/u4333wTOK5WidiZxezatauqX79+cP2yZcsy54MLQaCuE9hll13UfvvtZzA8+uijJo5IMQnUNXtfTC1AKhAoJwB7Ws4EKSCQlQC+F2clh+tAoHYQwPt+7dAjSgECIAACIAACIAACtYUAHFhriyZRDhAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCoEgJwYK0SRUFMEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEKgtBODAWls0iXKAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAQJUQgANrlSgKYoIACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIBAbSEAB9baokmUAwRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAASqhAAcWKtEURATBEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABGoLgVrvwHrjjTeqrbfeOtDXwoUL1Zw5c6pGdxMmTDCy3n///eqpp54y+0WJ9OzZU+27775ql112Udtss02JWBdeeKH6+OOPS9KwUz0EqqH+VQ9NSBpGIE/7jPocpoGaS4M+ao497pyNwD777KOGDRtmLr7tttvUM888Y/YRAQFOoEOHDurKK6/kSWXxKVOmqMWLF5elIwEEbAJ437KJ1Nw++i81x17qztL2WTo/qXIiHxAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCoJgK13oH1oYceUvXr1w90smrVKjV06NCq0c8jjzxiZCXn1UoD4ebkHCKdOnVSo0ePVs2aNYu82wUXXKBeeeWVyOM4UGwCRa5/xSYH6ZISyNM+oz4n1Uo+50Ef+XDGXeQI/PSnP1UjR440Gc6fP1+RAyICCIQRoH7y+PHjww6ZtJkzZ6p7773X7CMCAjYBvG/ZRGp+H/2XmteBqwTS9lk6P9fy4XoQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQqEYCcGAtsNaKPEA2d+5c1ahRo1h6cGCNxSNycPLkyaphw4ZBXsuWLVNTp04VyZcyKXL9EytkwTPyqV+JorvKBwdWCS1UZx5FtC+u9dm3Jooun+/y13T+cGCtaQ1U1/3h0FRsfVWLPcX7VrZ65FO/Rey/ZKNUd6+Sts/S+dVdzaDkIAACIAACIAAC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QAAEQAAEQAAEQAAEQMAbgap0YO3YsaOaOHGigfLhhx+qAQMGmP24SDU5sMaVI69jeTqw5lUm3AcEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQKBmCVSlAys5r5ITqw7jx49Xixcv1ruxWziwxuIpOwgH1jIkSAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEHAkUGMOrDvvvLM65ZRT1DvvvKNmz56duBitW7dWv//97835mzZtUieddJLZ55HjjjuO7wbx3/zmNyaNZm6dP3++2eeRt99+Wy1fvpwnBfGHHnpI1a9fP4ivWrVKDR06NIj3799fde3aVTVr1kx98803Qbn++c9/qrlz55blEZbQpUsX1bJly7BDQdqbb76p3nrrrcjj+kCvXr1Uw4YNg92nn35arV69OohnlS+tA2ufPn0MH7pxVPmLWt4A1n/+7b///qpbt26qU6dOgV6prlKd+Nvf/qbWr1+v2rZtq/bYY4/g7E8//bSkvgwaNEht3rxZ3XHHHTxLxEEABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABL4jkLsD6//8z/+ovn37qjZt2gQKICfPSy65JLEyxo0bpw488EBz/tSpUxU5lYaFRx55JCw5URo5iw4ZMqTsXNuBlWZ/nTx5stpqq63KzqWE9957T5111lmhx3jiAw88oBo0aMCTSuJPPfWUuvLKK0vSwnak5UvjwHr77berVq1aGbG+/PJLdc4556i1a9eaNB0panm1fFdddZUiJ9uw8O2336oxY8YEzsstWrQITvnXv/6lTjjhBHP6jBkzFB2jc1999VU1c+bMEgdXcyIiIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIFAHCeTiwLrLLrsEs60efPDBZY6eaRxYaXbTe+65R9WrVy9QFTlIHn/88ZFq8+3AumbNmmDW1MaNG0fKQAfef/99deaZZ8ae48OhU0K+pA6sd911l9phhx1MGT///HM1ePBgtW7dOpPGI0UtL8lIM/zSTL9x4euvvw5m2tWz3UY5sPI86Jy//vWvasqUKTwZcRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCocwS8OrAec8wx6thjj1U777xzJNgnn3xSXXPNNZHH+YELL7xQHXbYYSZpzpw5ima6jArDhg0LZsHkx/nsreRkuXLlSn7YxFesWKEofzvwGU75sQ8//FC9/vrrqn79+sGS89tuuy0/rEiW1157rSSN71xxxRWqadOmJony2XPPPc1+lhlYzcXfRbLKl8SB9e6771bNmzc3t/vkk0/UoEGD1KZNm0yaHSlqeYcPH66OOOKIEnGJ3UsvvRSkde7cucRRV59oO7DSzMB6lmF9jt7SrKxvvPGGmj17tlqyZIlOxhYEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAE6gwBcQfWtm3bqtNOO0396Ec/Ug0aNAgF+c033wQOgeTA9+yzz4aeE5bIZ+3csmWL6tOnT9hpsWkPP/ywmcH15ZdfViNGjIg93z5oO7CSMyLNPjp37tySUydNmqTat29v0p5//nk1evRos58kwmeQzerA6ipfnAMrzYhLs4lut912pjgbN24MZts1CSkiRSgvr2Mk+oIFC9TkyZNLSkF67NatW0ma7cBKB7t376569+6t2rVrZ+pcyUXf7dAswk888YQiJ2BihwACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACdYGAmAPrcccdp3r16hU6O6UGuXbt2sAh0Hb21MfjtjSjZ8+ePc0pf/nLX9RNN91k9pNGpB1YoxxLd9llF3XbbbcZsWgWzwEDBpj9JBEJh05X+aIcWFu2bBk4djZp0sQUJUsZzcXfRWq6vIMHD1Y9evQwIq1atUoNHTrU7PMIzfzbokULkxTmwGoOfhc5/fTT1X//938rcvqNCqtXrw5mZf3b3/4WdQrSQQAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQKBWEHByYKUl7k899VTVpUuXyNlWv/jii2CZ9Pvuu0+RA2vWMG/ePNWwYcPgcprB9ZhjjsmUlbQDa//+/dX69etDZZk5c6Zq2rRpcOzzzz9X/fr1Cz0vKlHCodNVvjAHVtLFLbfcoho3bmxEf++999RZZ51l9rNEarq8d955p9ppp52M6Jdffrlavny52eeRX//61+qkk04ySZUcWPWJHTt2VCeeeKI68MADI5+Zr776Sv39738PZmX96KOP9KXYggAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgECtIZDZgfXaa69V++67bygIcjB95ZVX1Jw5cyIdAEMvjEi0nQWjZhWNuLwkWdKBlZZ/P/7440vy5zu33367atWqVZD09ddfB8vJ8+OV4q4OnRLy2Q6sS5cuVQcccIBq1KiREf+tt95SQ4YMMftZIzVdXpoZWJdr8+bNqm/fvrFF4fImdWDlGR599NHq2GOPVW3btuXJJXGqr3wm35KD2AEBEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEACBKiWQ2YHVXkKdyk9LyD/66KOB46okD3KE3WabbYIsv/32W3XaaadFznpa6b6SDqxU3gEDBkTe8oYbblA0Sy0FkrtXr16R54Yd4A6SSZ12H3roIVW/fv0gOwn5bAfWMDmlnCxrury8bnz88cfq5JNPDiuuSXvggQfMLKpZHFhNRt9Fzj77bPX//t//U9tttx1PVv/85z/VJZdcUpKGHRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCodgKiDqwbN25UixYtUv+fvTMB22M6G/+RhkTQEELEHoLYukiV/HHxof0qqK32rWpprImIiK2E2kkpiaXEltqKLqJVyUfLp8S+RCyxVOyN2Hfl757PmZ7nvDPzzHKf553nze9c1/vOzJmZ+zn379xnmTP3nHPZZZepcfnv//7vhtk9H3/8cXPkkUeWlu86Kc6YMcOMGjWqkCzXQfS5554zhxxySOr9ne3AqpG+PA6sAmD06NFm+vTpqSzynKjqwFpF30UXXdRcfvnlcTJnzZplhg0bFh8n7fzud78zPXv2jE5VcWBdYokljMwy/P/+3/8z888/f8NP4cDagIMDCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEOgiBEo7sJ5wwglm7bXXTsQgs43KsvI33nijuf322xOvyRt55ZVXmkUWWSS+/IADDjAvvvhifFx0R9OBdebMmWb48OGpSehsB1aN9KU5sH700UcNzpYff/yx2X777VNZ5DlR1YG1ir7LLrusGT9+fJzM559/3hx88MHxcdJOVQdW4bX55pubxRdfPEl8NGuv/IbrWJt4IZEQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAIE2I1DagVX0lJkjd999d7PeeuuZHj16JKr+2WefmQcffNBcffXVRhwMi4R11123Yfl0cYo96KCDiojocC0OrP9BksfBNsmBVRheeOGF5tprrzULLLBALPCpp54yI0eOjI+L7nSmA6uk1f392bNnm7322itThZtuusnMO++80TV5Z2AdPHiw2XHHHc0qq6xiunXrlij/vffeM7fddpu59NJLE88TCQEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQaHcClRxYXeU33nhj85Of/MTITJZp4Z133jH/8z//Yy655JK0SxriL774YrPkkkvGcWPGjDGPPfZYfFxmBwfW/1Ar48B6zz33mJNOOikSsuqqq5ozzjjDzDPPPLHQiRMnmhtuuCE+LrLjOpC6v5Ml449//GPsCFplBlb5Ddch9cMPPzQ77LBD1k83OLxmObCKDe+yyy6Ro3fPnj0TZX7xxRdmxowZ5qqrrqps44k/QCQEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQKBGBNQcWK1Oiy66qNltt92MzNyZ5qz35ZdfmlmzZkUOgzLTZFIYNGhQ5Bxpz73xxhtm7733toelt64D6zPPPGNGjBhRSJamw2SzH+5sh05Jnz8D6+TJk82ECRPipP/sZz8z22yzTXwsjpgyS+6LL74Yx+Xd6Wx9J02aZHr37h0nV2YXfuutt+Jjd+e73/2uGTt2bByV5MC68847m80228wsvvji8XX+jjh133rrreaKK67wT3EMAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhDosgTUHVhdUuL8KLNYLr/88g2zdLrX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AAQgAIF6ElB3YB0/fryZb775Im2nTZtmLrroonpqXpNU4cCKA2tNTJFkQKDWBHCgqXX2kDgIVCag7XCqLS9LQRxYs+hwrt0J0P62ew6SfghAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQjUm4C6A+uf/vQnM88880Raz5gxw4waNareBDo5dTiw4sDaySbIz0OgLQjgQNMW2UQiIVCJQN++fRvuX2ONNczIkSPjuCIzsMpN2vLihHg7OLB6QDjsUgRof7tUdqIMBCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABGpHAAfWTs4SHFjDObBefvnlpnv37lEOT5kyxUycOLGTc5ufhwAEyhLAgaYsOe6DQPsS+O53v2vGjh0bK1DUgTW+8esdbXlWPv0NS4JtVyRA+9sVcxWdIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIFAfAjiwdnJe4MAazoG1k7OWn4cABBQJ4ECjCBNREGgTAtoOp9ry2gQjyYRAJQK0v5XwcTMEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEINCEAA6sTQCFPo0DKw6soW0M+RDoCgRwoOkKuYgOEChGQNvhVFteMW24GgLtSYD2tz3zjVRDAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAoF0IVHJg3W677Tro+dOf/jSOe+ONN8zkyZPjY3fnn//8p7n//vvdqLbdX2KJJczaa69tVlllFbP88subxRZbzHz00UdG9J85c6a59NJLU3VLc2Ddc889zeDBg03v3r3NF198YWbNmmUefvhhc8MNN6TKSjoxaNAgIw4bq666qllmmWUiWS+99JKZPn26ueuuu8zLL7+cdFtmXBV9N9hgAzN69OhYvtjHhAkT4mN/Z5tttjHdunWLo9P0X2uttcyiiy4aX+fvPP/88+aFF17wozscb7nllma++eaL4u+77z7z4osvRvsa+fGtb33LDBkyxKy++upRvkqeShn429/+Zt58802z7LLLmhVXXDH6vffee69TysePfvSjKH0DBgwwvXr1Mm+//bZ59tlnzaOPPhqlswMwLyIkP++nKh327dvXDB061Iieffr0ifLj3//+t3nllVfMM888Yx577LFc/NtFXwurav5aObJ16/8pU6aYd955Jzot9ZaU28UXXzyyIbHl1157zVx33XXmiSeecEU07EsZXm+99cxqq60WlWWpp6QM3nHHHVH5KONAo1n/aevboHxND+psL6GQVWnfbJraqX7R0NfqrVnerExth1MNefQ3bO6U27ZT+SinYfJdda5PaX+T84xYCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCECgNQQqObDefPPNpVMpzoQHHXRQ6fvrcuOhhx5qNttss8zkfPnll+bJJ580o0aN6nCd78B62mmnmfHjx5t55523w7USIQ52++23X+I5P1LkiFNkWpB0XXvtteaqq65Ku6RDfFV9iziw/uY3vzH9+vWL0/Dxxx+bAw880Lz++utxnN35/e9/b7p3724PO2zvuecec9JJJ3WI9yNC5cfJJ59sxEEgKUg+/OIXvzDDhw+PnCnlmg8++MDsuOOOSZcHiZN8GTlyZCbD999/3xx11FHmueeeS01DKH6pP1jwhDghyt83v/nNpneKE7roKw6taaHu+tp0a+WvlbfUUkuZCy+80B6aqVOnmnHjxkXO+uK4mhYefPBBc9xxx3U4/ctf/tKIg3dSkPIh5w844IBC5UOz/tPWN0nPOsXV3V5CsaravrVb/VJVXzcfNMubK1fD4VRbHv0Nl2j+/XYrH/k1y76y7vUp7W92/nEWAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhAITwAH1pKMV1ppJXPCCSdEMzfmFSEOWHZGT3uP6wAns6HKLKI9e/a0pxO3r776qtl3330Tz0mkvCw/7LDDUp1g/RtlllhxnswKWvpK2vLMwHrZZZdFM9naNH344YeRA9vs2bNtVMM2hEOJVn5cfPHFZskll2xIr3/w+eefR7Pj2tlfW+nAOmLECLPJJpv4SUo8FmdC0UfsNimEsOek3ykbd9ZZZ0UzJee9X/SdOHGiufHGGxNvqbu+kmjN/LUQfIdOmc35O9/5jllggQXsJYlbmZV67733bjh3ySWXGJkFMitIPsgMudZJPat8hKj/NPXN0rMO5+puLyEYabVv7VK/aOkreRGivLl5PLc4sM4N/Y12KR+u/VXdr3t9SvtbNYe5HwIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQ0CBQyYFVXszK8ttuECcmG8Tp8KmnnrKHDVtZoluWlG7XcP3115v555+/Iflz5swx//znP6Ol6mWJ1OWWW86I41O3bt2i65o5sLrCxNFLlm6Xe2XJ+QUXXNA9HTmlJc0MKY5gMnPpPPPME1//xRdfRPkgM2eKc+zAgQM7zMx6ww03RI568U3ejpa+eRxYr7zySrPIIovEKXj33XfNsGHD4iXK4xPOjjgTL7TQQnGMcBMnHRvKzMBq75Vt2fyQWU033nhjV1Qkyy6lvsYaazQ46toLsxz07DUaW985SGTKTLcyY/Cbb74Z2a9wtI6Dcl7saauttpLdDsF16HRPluXnytDYdx1oRA9Z2l5m9J01a5YRJ+L+/ftHjpg9evRo+LlDDjkkcebZuuurnb8Wiu/QKSxtPSfXfPbZZ0bqQ2kDpI2QGW+lTvIdWI844giz4YYbWrHRVmaZnjFjhpE8WHPNNRM/EkgrH6HqPy19GxSt4UHd7SUUMq32rV3qFy19Q5U3N599m7z66qvNpEmT3EsK7WvIo79RCHl8cbuUjzjBFXd8WxNxVfpXNjla7RHtryXKFgIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQ6GwClRxYkxL/pz/9KXaeFCekUaNGJV3W1nHiiLr55pvHOsjsgDJjqDiB+qF3797R8vArr7xyNINo1gyscm+arPPOO88sv/zysfhHH300Wt48jvh651e/+lWD46Y4jI0ZMyZy0nOvlRk3Zflg63QmDmi77757opOopr5ZDqzCasKECQ3Lu7/11ltRuty0592/+eab40vLOrBWzQ9/ZthbbrnFyFLLbpBl6ocMGeJGmTQHvYaLFA7E2blfv36xJHHo3GeffeJj2REnJbE/12FbZtw89dRTG66TA9+hsyq/Dj9QMeLEE080Uhb/8pe/ZDpsy3WuM7443Es58kPd9dXOX6u/70Bj48UJ+JxzzjG33367jYq2iy22mBFnGXHEl/rEBr98iGPd5Zdfbk9H21NOOSVyZHUj08pHiPpPfldLX1eHOu7X3V5CMNNs39qhftHUN1R5c/PZdwKsgwOrmz67T3/DkkjftkP5SE998TN1r09pf4vnKXdAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAJhCODAWpCrOGJdeumlseOn3H788ceb+++/P1OSOCjefffdHa7xHeDSHC19Byp/JkMRPHjw4P/P3p3Ay1HV+QI/4QFhlX3LSMAIGFafAyPKRx38gDoCQQIMKgRQdjBCICKyIyAQFlmEICiyyzKAOIhPB/ighscDZBmBgBA2AxEEwiKbLAOPf89UWV23+97bt6vv7Zv7rc8Haz99zvdUVbef/O6pWl2yD4mRnrbddttstcd80qRJ6Stf+Uq+Pep33HHH5euxUHV7mwVYl1lmmVqws/gK8kZtrKtcHytVBEra6Y9yUOiRRx5JU6ZMaVjriy66qG4042YBvYYnD3BjBDQjUJJNMWrmxIkTs9W6+UorrZR+9KMf5duajcJa5fWcf9gQLVxzzTVpwQUXrH16M5tubm8n+jfrivLzKLaH0e67756ef/757LBe5+X7I0YljpBro+mnP/1pXbC90f3RiedfVpcq2puV1a3zbr9eOuFW9fdbK3UciudLle3t5P1WdBxJAdZ5+fdGsU/7szwU90d/6tXfY7r9eer7t7896TgCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAZDQIC1ReVddtklbb311vlZc+bMSXvuuWe+3upCOQC38847117d3qicGHls8cUXr+2KV3Nvt912dYcVX88aO6ZNm5ZmzJhRd0x55aqrrkoLLbRQbXOjwGjV7W0UYI2gwllnnZXXIyoTrxHfY489ytVtab2KAGs7/RFB5+WXXz6vc29B569+9atphx12yI9tFNDLd1a08K1vfSttvPHGeWnNRlXNDjj33HPTmDFjstXaSJs33HBDvh4LVV7PdQUPwUp51OMtttiiRy26ub2d6N8MoFGgM+7juOb7O5XvjyOOOCLdfffdDU8vP4ca3R+deP5llamivVlZ3Trv9uulE27l66rd7/NW6jgUz5cq29vJ+63oOJICrPPy741in/ZneSjuj/7Uq7/HdPvz1Pdvf3vScQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIDIaAAGuLyuVXi8f67bff3mIpfz+8GIDra8TU4utI41XdW2211d8Len/p4osvTksttVS+7YILLkjxCvdsGjVqVLaYjyC75ZZbpiWXXLK2vVGZVbe3HGANu//9v/93Gj16dF63J554Ik2ePDlfH+hCuwHWdvvj6quvztv11ltv1QWfG7WpWN9GAb1G57Sz7eSTT07jx4/Pi4jRYWOU2GZTBKZ32mmnfPfPfvazdN555+XrsVDl9VxXcAdXxo0bl1ZZZZW04oorpuI9EuHeYmC3rwBru9dL1U3sRP9mdSwHOhs9O7Jjm82L4fkq7o9OPP+yulfR3qysbp13+/XSCbeqv98a1bGbni9VtreT91vRcaQEWNv9/uj23xvFPi0ud9P9UaxXu8vd/jz1/dtuDzufAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEqBQRYW9SM16jH69SzqVGoLdvXn3kx8NdoBNRiGaeddlpabbXVapsimDphwoTi7nTttdem+eefv25bqyvlEcCqbm85wNqoftddd10655xzGu1qaVsxENrs1bzlAqvsj2hHFoh86aWX0qRJk8ofV7de7L/BCLCWR+Dq61recMMN0+GHH57X+Y477khHH310vh4LVfrVFVzxSox4GwHwRRddtN8l77jjjunFF1+sO76b29uJ/s0aXw50Pv/88+lrX/tatrtf81bvj6J1o/ujeP/0qwINDio//7JDqmhvVla3zrv9eumEW9Xfb1kdu/X5UmV7O3m/ZY4xHykB1nZ//7X6PC32X6PnabEPql7u1vujynZ2+/O01evF92+VV4eyCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoCwiwlkX6WC+OWvTuu++mGMG0nan4j8KPPfZY2nfffZsW11eAtRjYbFpIHzv22WefNHv27PyoqtvbnwBrfPhBBx2UZs6cmddjIAtFj4EEWNvpj2WWWSZdeOGFebWffPLJtPfee+frjRaK1oMRKCl+Xn+u5bFjx6bp06fnVW80Um6V13P+QRUuxGhvJ510Uj4ybitFf/3rX0/PPfdc3Snd3N5O9G/W+HKg86GHHkpTp07Ndvc5X2KJJdKll16aH/fUU0+lvfbaK19vtFAcYbDR/VG83xud359t5edfdk677c3K6eZ5N18vnXJrtc191aPbny9VtreT91vReaQEWOf13xvRp91+fxSvu3aXW73X+vP7KqtTu99Hvn8zSXMCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBLpFQIC1xZ4ojlr15ptvpm222abFEuoPLwbg4vXt8Rr3ZlNvAdbyP36//fbb6f77729WVNPt8drTl19+Od9fdXubBVjfeOONtPDCC+ef29frdPMDe1koBmwGEmCtsj8ef/zx9M1vfrOX2qZUDDw0Cuj1evIAdhb7ttGIvo2KLJo2GjGuquu50We3uy1CGzEq2ujRo+uKimtt7ty5KUbJff311/N948ePT4svvni+3leAtZ3rJf+QChc60b9Z9coBmhkzZqRp06Zlu/ucr7rqqunMM8/Mj+tPwPvyyy9Piy22WO2c8v3RqedfVsF225uV083zbr5eOuVWbHO73+fD4flSVXs7fb8V+3ukBFjb+f4o90c3/t4YDvdH8bprd7l4r1X1+yqrU7vfR75/M0lzAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgS6RUCAtcWeKIao+vuP0r19RJWBv2K48JVXXknxmtZ2p6rb2yjAGq8yPeecc9IVV1xR90r3Vkd1LLe16DHYAdaoS/Hz+/OK9Z/97GdpgQUWqDWjHNArt62K9Vb7drXVVksRos6mWbNmpf333z9brc2rvJ7rCq5gJQLEX/jCF/KSIrAW7YnwZaMpAplrr712vmu4BVg70b8ZRjlAc9NNN6VTTz01292vefH+eOaZZ9Juu+3W63nXXHNNWnDBBWvHNLo/iuVV9fzLKlRFe7OyunXe7ddLJ9xabXNvdRgOz5cq29vJ+63oLMD63xq9/QFTHFHsj278vTEc7o/iddfucqv3Wn9+X2V1quL7qHi9+P7NZM0JECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBgqAQHWFuXjFeox2lU27bjjjunFF1/MVlueVxn4K75iO0ZgnThxYsv1KZ9QdXvLAdZisDRGvIzXu48aNSqvxvnnn5+iXQOZiv9AX/yc3sqqsj+KgdQY2XO77bbr7aPrAiiNAnq9njyAneeee24aM2ZMfuYWW2yRLzda+MxnPpO+/e1v57tuueWWdMIJJ+TrsVClX13BFazEK+tjFLiYIny+3377pXhtc7MpRmtdfvnl893DLcDaif7NMKoI0BRHqPvrX/+att9++6z4hvMIumfPhkb3Ryeef1lFqmhvVla3zrv9eumEW5Xfb8Ph+VJlezt5vxX7uhxgjWDgJZdcUjykpeWqy8s+3O+NTKLxfDjcH41rPrCt3f48Henfv/H/41ZZZZUenRsj8d933309tttAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBnBToaYG00QmOrzYlQ0+qrr153Wrzyu5XXVded3ObKoYcemj75yU/mpUTILUYGHOhUZeCvHLjrK5DYnzpX3d5ygPX6669PZ599dl6VXXfdtS54++6776bJkyen2bNn58f0d2GoAyXFwEbUubewczlU0yig19929/e44447Lq233nr54cccc0y6/fbb8/Xywp577pkmTJiQb24UJKryes4/qKKFYt1eeOGFtNNOO/VacnHEzzhwuAVYO9G/GVgVgc7iCHVxn2+55ZZZ8T3m5VdkN7o/OvH8yypSRXuzsorzbvp+6/brpehW1XKV32/D4flSZXs7eb8V+zd+/xVHd/6P//iPdMYZZxQPaWm56vKyD/d7I5NoPB8O90fjmg9sa7c/T0f692/8/46VV165R+fOnTs37bzzzj2220CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQGcFKg+wFkedfPbZZ9Muu+zSVgvKIcAoLEZPLAbp2vqAFk/edttt09e+9rX8rP6MrJkf3GCh+I/6jzzySJoyZUqDo/57U1+vkI0A4sc+9rH8/EYjZOY7+7lQdXv7CrBGtcojV7388stphx126GeN/37YUAdKyq+gv/HGG2uvrP97Df++VD62UUDv70dXs/SNb3wjffGLX8wLe+ihh9LUqVPz9fLCZZddlhZffPF8c9R5xowZ+XosVHk91xVcwUpxBM+nn3467b777k1LLV/3ceBwC7B2on8zsCoCneUAyTnnnJOijxpNhxxySNpoo43yXY3uj048/7IPrKK9WVnFeTd9v3X79VJ0q2q5fJ+3830+HJ4vVba3k/dbuX+L3+UxOuLBBx9cPqSl9arLiw8vljkUI76Xf0N02++N4XB/tHQR9XFwtz9PR/r3b7n9WXcKsGYS5gQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQGV6DyAGu82nXJJZestaKvUfX609RuCvhk9S2+Oje2lUcRzY4rzuMfs88666ziptpylYG/CFn98Ic/zF+zHUHfPfbYI0VYr69p4sSJKcLHjaYq29ufAOtSSy2Vzj///DT//PPn1bnjjjvS0Ucfna/3Z2GoAyXjxo2rGynunXfeqQWUn3jiibrqr7322umEE07I+y12Ngro1Z1UwcoKK6yQzjvvvLykuF722muvNGfOnHxbtvCZz3wmffvb385W05tvvpm22WabfD1bqPJ6zsqsan7FFVekRRddtFZc9MVWW23VtOjyNR8HDrcAayf6NwOrItD5uc99Lu23335Zken555+v++OAfMf7C8U/jIjtje6PTj3/4vOqaG+UU5666fut26+Xsl1V6+V7faDf58Pl+VJVezt5v5X7tnj/9/XsLp/baL3q8uIz/N5oJP33bcPl/vh7jdtb6vbn6Uj//hVgbe/6djYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBqgUqD7AWRwmNyj7zzDMpRoaaNWvWgOreTQGfrAGbbrppj5FSH3744XTAAQdkh+TzDTbYoBb8W2SRRdI+++yTZs+ene+LhaoDf9/61rfSxhtvnH9GhIivvPLKFMHi8hQBlAjlRR0jLBp9F6N2lacq29ufAGt8/iabbJL233//uqqccsop6eabb67b1tvKUAdKom7Tp09P8frzbIrwTYww+8tf/rK2afPNN0977rlnmm+++bJDavNGAb26AypaOf7449O6666bl/b222/Xrtfi/Rr9H0HDUaNG5cfFNXXRRRfl69lC1ddzVm4V8x/84AfpQx/6UF5UBIknT56cr8fCWmutlWJkwdGjR9dtj5XhFmCNOlfdv1FmTFUFOouhpij30UcfrQu1xh9DRNCkOPJvHNfs/ujE8y8+r6r2RlnFqdu+37r9einaVbVc1ffbcHm+VNXe8O/U/Vbu25NOOimtueaa+eYXX3wxnXnmmen222/Pt7WyUHV58dl+b/TeA8Pl/ui9Fa3t7fbn6Uj+/hVgbe1adjQBAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBTgtUHmCN0SQjsNpoivBeNj344IP9eg1stwV8svo3+8fPeAXx3/72t1rYb4kllqgLJg5GgDXqVx5hLbaF/auvvlqbR1h1scUWqxvhNI5pFmCNfVW1t78B1vjM7373u2n99dePxdoUbdhtt91qIzVm2yJYduqpp9Y5x74IWxZDiBHkfeutt7LT8vkf//jHdNhhh+XrVQcwx48fn0488cQe9cs/sMlCs4Bek8MHvLk8SlhWUFzHL730UlpmmWXqHGN/s9FXY1/VflFmVVMEtY866qi64uKaipD9QgstlCJkHv81m4ZjgLXq/s1sqgp0ll9pHuXHvfrKK6/U7plycDX7/N7uj048/6pqb1b/bN5t32/dfr1kblXPq/h+G07Plyram/VBJ+63rOxsHtflj3/847o/osj2ZfMYQXzChAnZaq/zgZbn90avrL3uHE73R68NaWFntz9PR/L3b7Nn4Ny5c9POO+/cQi87lAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBKgQqD7BGpY444oj08Y9/vNf6NRr9sNEJ1157bY+gZW8BukZldGrb4YcfnjbccMN+Fz9YAdalllqqNorkqquu2u+6xYG9BVhjfxXtbSXAGp95+eWX18K2sRzTs88+m3bZZZf/Xnn/fxuFIvKd/Vh48skn0957750f2YkA5uqrr14LdS+44IL555QX4n6IwHP0XUy9BfTK57a7/qlPfao2kl4Em/uaIgR9yCGHpMcee6zhoZ3wa/hBA9wYdd9oo436PDvCzhGy/+hHP5ofOxwDrFH5Kvs3w6gy0BnPxc022ywruuE87ocIqEXwPqbe7o9OPP+qbG+xgd34/dbt10vRr8rlKr7fhtPzpYr2hn8n7rdG/RphuwiWFUcCLx+3xRZblDc1XR9IeX5vNOXs147hdH/0q0H9OKjbn6cj9ftXgLUfF69DCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAyiQEcCrFH/eE3tVlttlcaMGZMWWGCBHqGDhx56KE2dOrXXpkbwL0bXLE/NXl9ePm4w1mOE0HiNbrORAqMOL7zwQoqg0jXXXNOjSgMN/MXIkeHb2/SlL30p7bTTTj1G0CyeE6MdRhjxpptuStddd11xV8Pldtv7iU98om7E0+uvv742umvDD3t/Y1wD3//+9+uun3h1fVwDMXVLoKSv/lh22WVr13u8wj4L4WWjf8ZrkM8///xam7IRQMtB3VpjO/g/MdLqCSeckFZaaaWGnxLhwfvvv7/PUZM7eT03rNgANkZwadKkST2C8VlRjz/+eO0ajbDU5z//+WxzahSOGg7tjQZU1b8ZRpR34YUXZqu150ejZ3V+QB8Lm2++edp9990b9km8LnzfffdNp59+elp66aVrJfUWYM0+qsrnX9XtjTp28/dbt18vWR9XPW/3+y3qM5yeL1W0N+uDKu+3rMzyfNy4cWm//farfU9l35XFYxo9o4v7y8utluf3Rlmw9fXhdH+03rrGZ3T783Qkfv+eeeaZqdEf+RmBtfE1bCsBAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBTgt0LMBaRcX33HPPHq+E7ZbRVxu1L0ZrXGedddIqq6xSe/16jKoZob/Zs2c3OnxQt0VwdK211qq9Kj3CiHPmzElRv3vvvXfA9ejm9g64UYN04tixY3tcF8Uw5MyZM9NBBx00SLWp/5gINa233nq1a+Xll19O99xzT2000vqjhv9a3BPjx49PMbpmvLL+mWeeSTfccEOKwOS8PHVz/0agLPol/iDgz3/+c79C9f3pq048//rzub0dM1y+37r5eunNt9197X6/DbfnS7vtLXp34/1WrN9IW+7G3xvD7f6o6prp5ufpSPr+rao/lUOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQDUCXR1gbfSKx4svvjhdccUV1bReKQS6RKD8ivIIUsaIkyYCBOZNAd9v82a/ahWBbhfwe6Pbe0j9CBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMLIEujrAeu2119a9UvqNN95I//qv/zqyekhrR4TA8ccfn9Zdd928rfE69ptuuilft0CAwLwl4Ptt3upPrSEwXAT83hguPaWeBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQGBkCXRtgjdfdn3jiiXW98KMf/Sj9/Oc/r9tmhUC3C1x99dXpkUceSZdffnm65557elR37733Tptvvnm+/aWXXkqTJk3K1y0QIDBvCfh+m7f6U2sIdIuA3xvd0hPqQYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQL9FejaAOs+++yTNttss7wdr776avrKV76Sr1sgMFwEfvGLX+RVffPNN9MLL7yQnn/++bT44ounFVdcMS200EL5/lg4+uij0x133FG3zQoBAvOOgO+3eacvtYRANwn4vdFNvaEuBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQINAfga4NsG633Xbp85//fHrvvfdq/1122WXp5ptv7k+bHEOgqwSKgZLeKhbX+i9/+ct09tln93aYfQQIDHMB32/DvANVn0CXCvi90aUdo1oECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0FSgawOsTWtsB4FhJjB9+vQ0ZsyYNP/88zeteYzKeswxx6RZs2Y1PcYOAgQIECBAgEAzAb83msnYToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLdKiDA2q09o17znMC4cePS6quvnpZbbrm09NJLp+effz7NnDkz/eEPf5jn2qpBBAgQIECAwNAI+L0xNO4+lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaFxBgbd3MGQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm0ICLC2gedUAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB1gUEWFs3cwYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAbAgKsbeA5lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHUBAdbWzZxBgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQhoAAaxt4TiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGhdQIC1dTNnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItCEgwNoGnlMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaFxBgbd3MGQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm0ICLC2gedUAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB1gUEWFs3cwYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAbAgKsbeA5lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHUBAdbWzZxBgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQhoAAaxt4TiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGhdQIC1dTNnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItCEgwNoGnlMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaFxBgbd3MGQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm0ICLC2gedUAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB1gUEWFs3cwYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAbAgKsbeA5lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHUBAdbWzZxBgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQhoAAaxt4TiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGhdQIC1dTNnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItCEgwNoGnlMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaFxBgbd3MGQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm0ICLC2gedUAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB1gUEWFs3cwYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAbAgKsbeA5lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHUBAdbWzZxBgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQhoAAaxt4TiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGhdQIC1dTNnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItCEgwNoGnlMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaFxBgbd3MGQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm0ICLC2gedUAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB1gUEWFs3cwYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAbAgKsbeA5lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHUBAdbWzZxBgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQhoAAaxt4TiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGhdQIC1dTNnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItCEgwNoGnlMJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgRaFxBgbd3MGQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAm0ICLC2gedUAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB1gUEWFs3cwYBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAbAgKsbeA5lQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHUBAdbWzZxBgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQhoAAaxt4TiVAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEGhdQIC1dTNnECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQItCEgwNoGnlMJEOiswOmnn54WXnjh2ofceOON6corr+zsB7ZY+rhx49Kxxx7b61lnn312mjFjRq/H2EmAQN8C7re+jRwxMIFDDz00rbLKKrWT//jHP6bvf//7AyvIWQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEBLAm0FWPfff//8H/zjU4855pg0d+7cphUYO3ZsOuCAA/L9Eeq6+uqr83ULw0Ng++23TxtvvHFafvnl0/zzz59X+q233kqvvPJK+t3vfpfOO++8fLsFAgMV+Pd///c033zz1U5/5JFH0pQpUwZaVEfOW3vttdO0adN6Lfuyyy5Ll156aa/H2EmAQN8C7re+jRwxMIGLLrooLb300rWTX3vttfTlL395YAV1yVnbbLNN2mSTTWptWmSRRfLv0TfffLP2Oz3ae8stt3RJbVWDAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBEayQFsB1uI/+AfiPvvsk2bPnt3UM/5B/etf/3q+/+67705HHHFEvm6huwU++9nPpsmTJ6fRo0f3WdH33nsvnXzyyem3v/1tn8c6gEAzAQHWZjK2Exh5AgKsI6/PB6vFxd+zwznA+o1vfKMWXF1wwQX7pHvyySfT3nvv3edxDiBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAp0UEGDtpO48VHY5fNyfpl1wwQXpqquu6s+hjiHQUKDbA6xR6eWWW66u7uuss06aOnVqvs0IrDmFBQJtC7jf2iZUQAOBeSHAusIKK7Q8+v1DDz1U933VgMYmAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQUQEB1o7yzhuFb7TRRumQQw6pa0yMsPqnP/0pzZw5s/bfyiuvnNZcc83af9kIrQKsdWRWBiAwHAKs5Wb94z/+Yzr66KPzzQKsOYUFApULuN8qJx2RBc6LAdaXXnopRUD13nvvTS+88EJaa6210he+8IVUHp311FNPTTfddNOI7HeNJkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGhFxBgHfo+6PoaRBB12WWXzev5zjvvpEMPPbQWXM03FhbiFbYRkjj//PPTz372s8IeiwRaExBgbc3L0QRGmoAA60jr8c60d14KsL722mvp3HPPbRpKvfLKK9MiiyySQ952223p2GOPzdctECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBwRQQYB1M7WH4WRtuuGE6/PDD85pHePWAAw5Ijz32WL6t0cJSSy2VXnzxxUa7bCPQbwEB1n5TOZDAiBQQYB2R3V55o+eFAGugxB8P/frXv+7V54tf/GKKPzTKpr/85S9p1113zVbNCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDAoAp0fYB1++23Tx/5yEfScsstlz7wgQ+k//qv/0p//etfU7wa9c4770w///nPWwKL19xH4GX8+PEpXnv/7rvvpqeeeqo2mugtt9yS5syZ0+/yttlmm/zYG2+8Mb388su19Q022CBNnDgxLb/88rVRrl555ZX0zDPPpBj16oEHHsjPabTw2c9+ttbO4r7nnnsu3XrrrcVNg7b8k5/8pNaO7AN/+9vfppNOOilbHfA8+nPzzTdP48aNS0svvXRaYoklan375z//Oc2aNSvdd999tf7t6wMmTJiQvw7397//fZo9e3btlJ133jlFP0S50cdPPvlk+s///M909dVX91VkJfvXWGONtO666+ZlxQhn/b22itfVH/7wh/TII4/k5ZQXIoiy9tpr1xxjRLW4Lx599NHaK4Ojr/qaNt100zR69OjaYXfffXd6+umnm54S7Rk7dmxtfwSZ+wrJNC2ohR3NAqxV9W+Vz4OsWe0E6op9//DDD9fugzDfeOONa8+tGAk57pF4JfTvfve7/HrPPrtT86jDP/3TP9WKf/3111Ncz5MmTUof+9jHUlwLd911V+3eev7559NKK61Ue/6Fw3zzzZeiHZdcckntOdtX/TrRH319Zqv7V1hhhbT++uvXvpdWXXXV2ujUb7zxRnr22Wdr92o8M/uahtPzr4r2Zh6d6N927resXlXPh1P/Vtn2dr+PinUpPgur+H213nrrpU9+8pNprbXWSssss0zteRS/GX7zm9+kuXPnpoEEWKu8nqtub9GyvPzxj388HXHEEfnmeHbtsssu+boFAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwmAJdG2CNgNpWW22VFlhggT49Inh6wgkn9Hnc9OnT8wBeo4Pfe++9dMUVV9TCVo32F7f9wz/8QzrnnHPyTTfddFM69dRTUznwmR/wPwsREiwGB8r7f/GLX5Q31cIV4THYU4Qwv//979d9bIzSFaN1DXSKkEb8F2HkvqYIhR1yyCG1QGuzY8sBx2nTpqXo52bXTYT/9thjj2bFVbb9S1/6Utp9993z8mbOnJkOOuigfL3Zwg477JC++tWv5rsjYPPd7343X88WPv3pT6epU6em+eefP9vUY/7qq6/W/HobLbfsN2XKlB7lZBtOO+20tNpqq9VW416J8HCnp3L9quzfKp8HRYd2AnXF+z9Cqvfff3+KEH+z6aqrrkoXXHBBs92Vbf/6179eu2+jwAisxr25+OKL15UfQf3JkyfXXl2dhaKzA956663aiH+9BaQ71R9ZHaqY77fffulzn/tcr0XFvfHHP/4xHXjggT2OG27Pv3bbWwToVP+2c78V61fF8nDr3yraHGVU9X2U1afq31ff+9730kc/+tGs+Lp53K+xf5999qn9MU3sfO2119KXv/zluuPKK1Vez1W3t1zX8nr8Fok+y6b+/obOjjcnQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJVCnRlgDVGgtp666373c4nnniiFpxqdkL8Q3289r5ZqLF8Xox42VuQL44vBw4iABCjES666KLl4urW+xrpqhhgy06M0cGGIsAaYZwIrmVTX3XPjuttfsopp9RGLuztmOK+CJecf/756ZprriluzpeLAccY4TRGVltooYXy/Y0WIkRXDJc2OqaKbddee20eMI1RYLfccss+iy2OAhcHx3VYHoF1//33T5tsskmfZcUB4fejH/0ohVOjqejX13U/1AHWqvq3E8+Dom07gbri/f/mm2/mo+MWyy8v33HHHenoo48ub650vRhgHWjBzULcne6Pgda3eF4EtyNIHiM693eKQFw2InR2znB5/lXV3mh3p/u3nfst65eq5sOlf6tqb5RT5fdRVq8qf1+dd955KUYR7m2K78kY3T/7g5DeAqyduJ6rbG9v7Yx9G220Ue0PW4rHxR+GzJgxo7jJMgECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQGDSBrgywFkNcIfHyyy+n22+/PT3zzDO1cOIqq6ySVl555TRmzJgaVG8B1ggu/PjHP06jRo3KUSNM+NBDD6UYmTLCjquvvnqPkVnjVfMRnGw2lQMHUWa8Ljub3n777fTCCy+keN320ksvXRtxNOrQVwi03PYob6gCrBGejFfMZ1MVo3QVAz5hFn0aI7o++eSTtZEdo08jCFwewXHfffet9VdWl2xeDGBm22Iezo8++mitT9Zee+202GKLFXfXQjezZs2q21b1ylFHHZU22GCDvNgYKTNGzGw2ffCDH0w//OEP890vvvhi2nHHHfP1WCiHtWLb3/72t9qIj3GdxHUZ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nQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgS6QaCSAGs0JF5rfuCBBzYcpTNraITovve976W//OUv2aYe80022SR96UtfSmPHju01uBWhv//7f/9vmjZtWo8ymm2IcnfaaaceI1QWj49yo5433XRTipEpm00x0uWFF16Y747jTz311Hx9oAvl0TCjnLlz59aCcAMts8rzttlmm7TddtulRRddtGmxMSLhjBkzaiOwvvzyyz2Oi6DRpEmTmvbv448/ng477LBam4uvty+H/aLggQYcY+TXrbbaqkfdBmNDtP0rX/lK/lER1I17p5Uprr8TTjghrbTSSg1PizDO/fffnw4++OCG+8sb99xzz9RsRNW4H/bdd9/aiMRZgHWw/DrZv1U+D8qe2fq4ceNqr6yOfmo0unD5mi6Gje699950+eWXpyOPPLLhMyvus+9+97vpvvvuyz6uY/NigLU8ou/48ePTySefnH/2XnvtlZ566ql8/dprr83v9d5GGh6M/sgrNcCF9ddfvxYebzZyYxQbo4VHm6+55pqGnzKcnn9VtDdDGIz+bfV+y+pW5Xw49W9V7a76+6jq31ebb7552n333fPnULHd8cdP8f12+umn579fewuwZudWeT1X3d6sjjEvfqcIsBZlLBMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAtwhUFmDNGhQjdK611lppjTXWqL1O+Y033kgPP/xwmjlzZmoUZszOazRfffXVa+WMGTOm9or5eG12jEoYgbo777yz0Sn93vaJT3yiVs94dX2E/ebMmZOeeOKJFKExU98CETCOUXejv+M18xHaitBavMY8Apn9maIPIvwWo4/FK+ujb2+44YZeR9PtT7ndfkyMmBl+2RQBxbvuuitbbXkeIbP11luvdo/EPXbPPff0uw+KH7bkkkumeA123L9vv/12rU9+97vfpdmzZxcPmyeXu+V5UAwbxbMoRnSMKe6zCPdHcPLZZ59Nt956a69/CDDcO6lb+qM3xxgdep111kmrrLJKeumll2rfHxEa7+/9Mtyef+22t2g5HPq3WN+BLA+3/h1IGxudU9X3UaOy290WAefol3iO/vnPf+71j5Ra+ayRcD234uFYAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQikDlAdZWPtyxBEaawHLLLZfOP//8vNmvv/56bUTbfIOFES3QLMA6olE0ngABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBeVJAgHWe7FaN6laBE088sTbCaVa/66+/Pp199tnZqvkIFxBgHeEXgOYTIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQGEECAqwjqLM1degExo4dmyZNmpQ22mijvBLvvfdemjBhQr5ugYAAq2uAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGRIiDAOlJ6WjsHXWCFFVZIZ511Vho1alQaPXp0j8//zW9+k04++eQe220YuQICrCO377WcAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwEgTEGAdaT2uvYMm8MEPfjD98Ic/bPh59957bzrkkEMa7rNx5AoIsI7cvtdyAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAiNNQIB1pPW49g6aQKMA62uvvZbuvPPOdNJJJw1aPXzQ8BEoBljvuuuudOSRRw6fyqspAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEWhAQYG0By6EEWhX4+Mc/Xjvl3XffrQVXWz3f8SNLYIMNNkjzzTdfrdF33HHHyGq81hIgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYh74P1IAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMKIEBFhHVHdrLAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBg6AUEWIe+D9SAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCiBARYR1R3aywBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAYOgFBFiHvg/UgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAwogQEWEdUd2ssAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGDoBQRYW+yD008/PS288MK1s2688cZ05ZVXtliCwwkQIEAgBAbzeXrKKafk6P/2b/+Wbrvttnx9sBbWXHPNtP/+++cfd84556S77rorX69yoRvaW2V7lEWAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDDvCQwowLrRRhul7bbbrjKNs846K82aNauy8jpZ0L//+7+n+eabr/YRjzzySJoyZUrLH/fNb34zLbfccnXnRaDqvvvuq9tWXhk7dmzabbfd8s0PP/xwuuSSS/J1C9UK/PM//3Padttt0zLLLJMWW2yxvN/feeed9MYbb6TZs2enm2++Of3qV7+q9oOVRmCECFTxPO0v1S9+8Yv80AivHnvssfn6YC18+tOfTgcddFD+cddff306++yz8/UqF7qhvVW2R1kECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLznsCAAqwRwPzCF75Qmca0adPSjBkzKiuvkwVVEbi69tpr0/zzz19XzaeffjrtvvvuddvKK7vuumuaOHFivrk/5+QHW+i3wKqrrpq+853vpA9+8IP9Oue9995LJ5544rC5hvvVqBFy0PTp09OCCy5Ya+0dd9yRzj333BHS8mqa2a5fFc/T/rakGwKdAqz97S3HESBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIjAQBAdYWe7mKwFWjAGtUI0bmmzlzZtMaCbA2palsxworrJDitd7lgHFfHxDBx7g2TMNL4LrrrkujRo2qVfrBBx9MBx544PBqwBDXtl2/Kp6n/SUQYB38EWf72zeOI0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQGJkCAwqwTpgwIW211VZNxZZccsk0evTofP9rr72WXn311Xy9vHDKKaekBx54oLy5K9erCFw1C7A+8cQTafLkyU3bLcDalKayHRdffHFaaqml6sqbNWtW+n//7/+l2bNn1/atscYa6UMf+lD68Ic/nIcfBVjryIbNSrsBzGHT0A5VtF2/Kp6n/W3ahRdemAfTb7zxxnT++ef399TKjhvMEVi7ob2VwSmIAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgnhQYUIC1L4kjjzwy/dM//VN+2GWXXZYuvfTSfH04L1QRuGoWYA2XfffdNz322GMNiQRYG7JUtnHzzTdPe++9d17eu+++m6ZOnZoiwNps+s53vpM22mijdMYZZ6QIxZmGl0C7Aczh1drqa9uuXxXP0+pb1bkSBzPA2rlWKJkAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBANQICrC06VhG46i3A+tBDD9VCk42qJcDaSKW6bd/73vfSRz/60bzAM888M/3qV7/K1y3MewLtBjDnPZHWWtSuXxXP09ZqPLRHC7AOrb9PJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQ6C6Brg+wrrnmmukf//Ef0/jx49PKK6+cYlTMp556Ks2cOTPdcsstac6cOS2LrrDCCmn99ddPH/nIR9Kqq66all122fTGG2+kZ599Nj3yyCPpJz/5SdMymwWudt5557TBBhukJZZYolbHJ598Mv3nf/5nuvrqq3uUVQ6wvvXWW2nBBRfMj4ug6l/+8pd8PVsYSID1i1/8Ylp77bXTuHHj0iKLLJJeeuml9Oijj6Z77703/fa3v82K7jFfd9110xprrJFvb9SOfGdhYezYsXWj7zY7b7nllksx4mnUa+mll665/dd//Vf685//XBvx9L777kt33nlnoeTOL15++eVpscUWq33Qe++9lyZMmND2h2666aZp9OjRtXLuvvvu9PTTTzctM8zD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/HGLva2GfD/88EMvtLps2TJ7EeMIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACKRdIVYBVQ2q///3v/TCVhvguv/xyr6fRXI7aa52GqcIGu2dLXR4WGgpup2G8Bx54IDhbXASu8g2w6s7HjRsnhx9+eIl66IxgCHT//ffPePy3+l1xxRWyfv36Ett37NgxozfObOFKs/HAgQPlrLPOMpOyYcMGadKkiT+tPXC+9dZb/nRw5Omnn5ZatWp5s3P19hk8ZrpR0gFW7a23bdu28vjjj8urr74arH6J6WeffTajF0vt9W/27NkZ62nAt1mzZv68qF5x77vvPvnZz37mr5dvgHXjxo0ZAW2/gH+M2OFCnd+vX78S15IdctN14pSX5PmXVIDVDhjn6kFYfXINQU9dP60BVtMW7UH5ggsukJNOOkn22WcfM9t7/eCDD0SD0FFDXD8X99OougXn28cmzQHW/fbbT6ZOnZrRk+/ChQszeigNti1surzbG+y1W+/5Q4cOldWrV2dUV0Ou+j5n/1AjGGDVe2v9+vUzttNevP/zP/9T9IcYDAgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAALFKZCqAKsSXnPNNV6QynBqqExDgWGPttdQm4YaO3To4IV9tHc37eUtOJx66qlecMae//HHH8vVV19tz/LGtayRI0d6QS4NbAYf3ewicFWaAKuGH+1eTu0KBwOsuuzOO++UI444wl9t165dXnv08d5mUA/tOdQODKlxrscuN2zYUKZNm2aKyXj98ccfpUePHhnzghP333+/HHzwwf5sDTLp47HtQQOkGvKsUaOGPdsbTzrAqgHc9u3be/vavn2799h3DbqtW7cuoy4a4u3bt68fxtWFep5qQPTLL7/MWFd7qT399NP9ed9//72MGDEiI8QVFlLON8CqBYc5Pvnkk7Lvvvv6+416vLsdcjMrxykvqfMvqQCr3jNatWplmu6FsrU3SPt68RfmMRLmmfYAq92sX/ziF6KPalcTvT/kCrDG9XNxP7Xrn23cPjZpDrBqG0455RQZNmxYRnMmTJggb7zxRsa8bBNpaG8wwK8hVu1h9pVXXvGq3qlTJ+nfv79UrVo1oylRAVbdftGiRd571cqVKzO2YQIBBBBAAAEEEEAAAQQQQAABBBBA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AggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIhAgRYQ1CYhQACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCQnAAB1uRsKRkBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAIESAAGsICrMQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBJITIMCanC0lI4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgiECBBgDUFhFgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBAcgIEWJOzpWQEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgRABAqwhKMxCAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEhOgABrcraUjAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCAQIkCANQSFWQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACyQkQYE3OlpIRQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBEIECLCGoDALAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCA5AQKsydlSMgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBAiAAB1hAUZiGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIJCdAgDU5W0pGAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEAgRIMAagsIsBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIHkBAiwJmdLyQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACIQIEWENQmIUAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggkJwAAdbkbCkZAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCBEgABrCAqzEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSSEyDAmpwtJSOAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIhAgQYA1BYRYCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAQHICBFiTs6VkBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIEQAQKsISjFPKtly5Zy2223ZW3Cgw8+KPPnz8+6DgtzC1x//fXSvHlzb8Vly5bJPffck3sj1kAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAASHAWsFOgnbt2sn48eOztmrWrFkyc+bMrOuwMLfAjBkzpH79+t6K3333nZx33nm5N2INBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAgwFrRzgECrGV3RAmwlp01e0IAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEKhYAvTAWrGOp9eaRo0aZbTq8MMPl+HDh/vz6IHVp4g1QoA1Fh8bI4AAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIVGIBAqyV4OAfffTRMnbsWL+lBFh9ilgjBFhj8bExAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBAJRYgwFoJDj4B1mQOMgHWZFwpFQEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAoOILEGCt+MdYCLAmc5AJsCbjSqkIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIVXyCRAOv+++8vxxxzjBx66KHSokULadiwoXz//ffy1VdfycqVK+Wxxx7LKduoUSPp1KmTtGzZUurXry9169aVv//97/L555/LihUrZPHixfLuu+/mLKdLly5SvXp1b7133nlH1qxZ44337dtXOnTo4JW7Z88eWbt2rXzwwQcyZ86cnGUGV3DRXlPmYYcd5gVO27RpIwcddJBo3datWycfffSRvPnmm7J+/Xqzat6vaQ6wnnnmmdKuXTvvOO+zzz6ydetW+eSTT2TRokXypz/9Ke826oo9e/b013/99ddl27Zt3rQe5+7du0vjxo1F97F9+3bZsGGDzJ49W5YsWeJvExxp3769HH/88dK2bVtp0KCBdxz0HPrjH/8omzZtkkICrC6Pr+v2BtvPNAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJJCTgPsA4ZMkROO+20rPX96aefZNmyZTJixIgS62koT//bd999SywLztBQ7OjRo71Aa3CZmX7hhRekatWq3qSGZ8ePHy+TJ0+Wvfbay6yS8aoB2csvvzxjXraJuO21y9Z6NWvWzJ6VMa5uTz/9tDzxxBMZ83NNpDHA+qtf/UqGDx8u1apVi6z+t99+6x3fVatWRa5jFhx44IEyZcoUMynz5s2TiRMnemFpDa5GDe+9957cdNNNJRbffvvtcuSRR5aYrzP0OOjygQMHeuFqnffdd9/Jeeedp6ORg8vj67q9kZVmAQIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIJCDgLsLZq1UrGjBnj9Wiabz01AGh6RDXbTJgwweu51UznetUw4dSpU2Xu3Lmhq9oBVu29VHvSrFmzZui6ZuYXX3wh/fr1M5Ohr67aq4VrmPPqq6+ODNUGK6BB3KFDhwZnR06nLcA6bNgwOeWUUyLray/Q4/vwww+LHsdsQzDQqb3VHnXUUVKrVq1sm3m9Al9yySUZ6zz66KOivepmG7Re2iOwCeBmC7AmcXxdtjdbO1mGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCA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Agh8J5C3AFZXWwNZR40aJW+88Ya7iHGIAAGsBLCGNA0WWxJ47rnnpEKFCk5qK1eulGHDhllKmWQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSiBKwGsG7YsEH27dvnHK9y5cpSp04dp4dWN0DMzcju3bule/fu7izjEIHZs2dLpUqVnLULFy6UBx98MGTL8rl4zhwCWMtnzSanVASwJqcuyAkCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggUl4DVANbzzz+/hF6tWrWcXg1/+tOfpqx799135YYbbkhZxgwCpgABrKYG03EIEMAahyppIoAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAKlC8QewOpm4a677pLmzZu7s0IvrB4FEyECBLCGwLDYmgABrNYoSQgBBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQyEggbwGs9erVk9mzZ6dkLqjH1pQNvps5/vjj5eSTT3aCXxs0aCD79++Xjz/+WLQH19dee002btzo3yV0vnbt2vL//t//c9Jr1KiRfPbZZ7JkyRJ59tlnnX10/UknneTt//LLL3vT7kSHDh2katWqzuxbb70ln376qbuqxLhVq1bSsGFDZ/m+ffvkL3/5S4lt3AWtW7cWNQob1q5dK+vWrQtbHbi8e/fu3vKFCxfKjh07nPm2bdtKt27d5PDDD5fq1avLzp07ZdOmTTJv3jx57733vH2CJmzWh5b55z//ubRo0cIpu9brsmXL5G9/+5ts2bJFyiKA1TT74IMPZMWKFU4dtm/f3mk3hx56qHzyySfy9ttvyyuvvCLr168PYiqx7LDDDpNOnTpJkyZNpG7duqI9E//73/920lq9erVznDfeeKPEflELzLzmWr+55k/b+SmnnOJkd9euXfL6669Lz549nfNJ2/6bb74pTz/9tGzevFmOOuoop/3peV2xYkVR50ceecQ5r6PKq+tyaX+ml3uc3/zmN+6kfP755/LCCy948+bEv/71L0mnfnLJn3k8nTbzm2v9umlfcskl8pOf/ES0vg855BCnDX755Zeyfft2p3x//OMf3U3TGp955plOOubGX3zxhSxevNhcxDQCCCCA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AAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII5FWAAFaDmwBWA6NIJwlgLdKKp9gIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJ5FSCA1eAmgNXAKNJJAliLtOIpNgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAQF4FCGA1uAlgNTCKdJIA1iKteIqNAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCQVwECWA1uAlgNjCKdNANY33zzTRkxYkSRSlBsBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBOITIIDVsD366KOlVatW3pI///nP3jQTxSHQtm1bqVixolPYpUuXFkehKSUCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACeRYggDXP4BwOAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQKHYBAliLvQVQfgQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCDPAgSw5hmcwyGAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAALFLkAAa7G3AMqPAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAII5FmAANY8g3M4BOIUOPnkk6Vp06bOIVauXCkrVqyI83CkXUACF110kZPbr7/+Wl544YUCyjlZRQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgfIoQABreaxVylS0AgsWLJBKlSo55f/rX/8qd999d9FaUPAfBJo1ayYTJ070FkyYMEFefvllb54JBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCDfAgSw5ls8h+PddNNN0qhRIyeFVatWyR/+8IccUiv/u2qQnjs8+eST8vrrr7uzVsZJq48RI0bIKaec4pRt37590rVrVyvlLJZE4m4vZe04ZcoU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EEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBIpAgADWIqhkiogAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggkSYAA1iTVBnlBAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEikCAANYiqGSKiAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCRJgADWJNUGeUEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSKQIAA1iKoZIqIAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIJEmAANYk1QZ5QQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBIpAgADWIqhkiogAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggkSYAA1iTVBnlBAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEikCAANYiqGSKiAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCRJgADWJNUGeUEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSKQIAA1iKoZIqIAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIJEmAANYk1QZ5QQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBIpAgADWIqhkiogAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggkSYAA1iTVBnlBAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEikCAANYiqGSKiAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCRJgADWJNUGeUEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSKQIAA1iKoZIqIAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIJEmAANYk1QZ5QQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBIpAgADWIqhkiogAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggkSYAA1iTVBnlBAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEikCAANYiqGSKiAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCRJgADWJNUGeUEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSKQIAA1iKoZIqIAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIJEmAANYk1QZ5QQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBIpAgADWIqhkiogAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggkSYAA1iTVBnlBAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEikCAANYiqGSKiAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCRJgADWJNUGeUEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSKQIAA1iKoZIqIAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIJEmAANYk1QZ5QQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBIpAgADWIqhkiogAAggggAACCCCAAAIIIIAAAggggAACCCCA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AARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAATiELAOYG3fvj1VqVLFO+e7775LX375Zej5jzzySGrYsKG3f/fu3fS3v/2tRNlOnTpR5cqVvfy3336b1qxZ46V79OhBbdu2pZo1a9KPP/5Ia9eupffff59mzpxZoo5CGfXq1aM2bdrQz3/+c2rcuDHtv//+tGPHDtqwYQOtWLGCHnvsscAqzj777BL5l1xyic7j4+fMmaO3zcRnn31GCxcuNLNy0q1bt6Y6derk5Jkbq1atotWrV5tZkdKnn346tWzZkpo0aUJ77703bd26lT799FP68MMP6dVXXy1YRxr2KChEzAJJ7Wue5oADDqCOHTt63GrXru21u//7v/+jL774gpYvX06LFi3Ka0+zLn9aOuBUuj6/vEm2Jfi57G9JdPIf40K+sABWW//nyr+cd955nh9le9eoUYO4j3zzzTeen2F/9+yzz/qxOd02bbJs2TKvn/I156STTiLuJ+zruQ+z/3vttdf09SWqULb+VJ1Hyh6S/tlkp+SUur6p+rAGARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAAZOAdQBrWMCVeRKVvu+++6hp06be5k8//UQcfONf/PWNGjWKxo0bR3vttZe/qLfNwUiXX3554L6gzKuvvppOOeWUoF06j2X75JNPaNCgQTqPEy+88ELOdpwNDj7t169f6CGzZ8+mSpUqhe5/66236Pbbbw/d799xwgkn0MCBA/PW+d1339GQIUNo5cqV/sP1tmt76BMJJWzsyyJwEBf/cTBeoYWDnpkfB7TGWaQDTqXri6OLv6wkP5f9zS93km0X8rnqb9L+hQNqO3fuHOqXTZ5vvPEGjRw50sxyljZtwkGqH330EXGQbdgyY8YMeuKJJ8J263wpf6oqlLKHZHsx2Sk5o64LXd+i1oNyIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAAC5YtApgNY161b581KWrVq1bxW4VlfL7vssrxlOHB2+PDh3kyaeQsaO/v27ZszQ5/LAB+pgCYW/5prrqGTTz7Z0CQ8ycG6Dz/8MHEgVNBiBkhJ2iPoXDZ5Evbl8997773ejJJRZWF+jz/+OM2aNSvqId5MkCNGjNDlp06dSlOmTNHbcRNZCmCV5Oeyv8VlHFTehXyu+pukf+nZsyd17do1CElgXprBjaZNfvjhBz07eKBg/8lcsGABmf3RX1bSn6q6pewh2V5MdkrOqOs0bRxVJpQDARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARDIPoFMB7Ca+DZs2ECffvopVaxYkVq2bEn77ruvudsL2sw3E+YzzzxD1apVyzlm8+bN9NlnnxEH3/AnsBs1akQHHXSQdw4u6A9g5UAm/py8uRx99NF6c/v27bR06VK9bSb4k/PTp083s3LSHFxbvXp1ncd6qtlqOTPqDKz+YEY+9vvvv/dmlN20aZOnH9drzvb6448/0plnnslFSyxmgJS509YeZl0SaQn7shxmACZz+eqrr2j9+vW0du1a2r17NzVo0IDY5lWqVMkRu3///nlnsjUL+21UVgNYbfm57G+mPZKmXcjnqr9J+Rdm5Q903LZtG82fP9/rK/xjA/ajhxxyiNdXuDz713yzT3MZqcUvm6qXZ+pesmSJ12/5+lGrVi21y1tzv583b15OHm/4+yrn2fhTPp4XKXtIthcX7fnf2uI/CIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACAQTyHwAK89wyZ94njlzZo4GY8eOpcaNG+s8/lw0f849aOFA1A4dOuhdYXVygZo1a9LQoUPp8MMPLxHAqiswEs8//zxVqFDBy+EAqUGDBhl77ZJmMFbUANZHHnmE6tevr0/MAZiXXnqp3uZEvXr1iPmZAb1hn/n2B0iFsYtjjxxhBDYk7Xvbbbd5tn/ppZe8mVXDxONyZvAyByjfeOONYcVz8v1BcWUpgNU1P5f9LcdICTds5UuzvyXxLxdccAGde+65mk6+ds9+hmfG3rJlCz344IP6GJcJUyd1Hr528CzJ5nLHHXdQ69atdRYH5PPMsv5F2p/66ze3Tdmj+nvX7cW2PZv6IQ0CIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACfgKZD2ANC+ThmVIfeughrU9YANL+++9Pjz32mJ5VlQ8YNmwYLVy4UB8blGjXrh29+eabQbty8lwG+MQNaOKASg4gVMuu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AiAAAiAAAiAAAnkIiAaw5jkPdoEACIAACICAUwJhAaxOT4rKQQAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEEhFAAGsibDgIBEAABEAgawQQwJo1i0AeEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAgngADWcDbYAwIgAAIgUEQEEMBaRMaCqCAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAuWeAAJYy30TAAAQAAEQKBsEEMBaNuwILUAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABMoHAQSwlg87Q0sQAAEQKPMEEMBa5k0MBUEABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABMoQAQSwliFjQhUQAAEQKM8EzADWd955h4YOHVqecUB3EAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEMg0AQSwZto8EA4EQAAEQCAqgbZt21LFihW94gsWLIh6GMqBAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiUAgEEsJYCdJwSBEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABMozAQSwlmfrQ3cQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQKAUCCGAtBeg4JQiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiUZwIIYC3P1ofuIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIFAKBBDAWgrQcUoQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQKM8EEMBanq0P3UEABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABECgFAgggDUm9DFjxlC1atW8o+bOnUvTp0+PWUP04vfee68u/Mwzz9Bbb72lt9NKHHHEEXTNNdfo0z300EP0zjvv6G3JRBb0ldQHdYEACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACAQTKOoA1nbt2lH37t21Zs8++yzNmzdPb7tIPPfcc1SxYkWv6hUrVtCAAQNcnMar84UXXtB1c/Dq7bffrrfTSpxwwgk0ePBgfbo5c+bQ+PHj9bZkIgv6SuqDukAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABIIJFHUA66RJk6h27dpas759+9KaNWv0dlBi3LhxVLlyZW/XggULaMKECUHFQvMQwIoA1tDGgR0gAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAKRCBRtAGvbtm1p2LBhWsnVq1dTv3799HZY4vnnn6cKFSp4u5csWUKDBg0KKxqYjwBWBLAGNgxkggAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIRCZQtAGsf/7zn+nggw/Wit544420aNEivR2WKKYA1okTJ1KlSpU8VebOnUuPP/54mFrO8k844QQaPHiwrn/OHHcBrFnQVyuKBAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAgDMCRRnA2qxZMxo9erSGsmHDBurZs6fezpcopgDWfHqktS/NANa0dMJ5QAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAESpdAUQawcvAqB7GqZdSoUfT666+rzbxrBLDmxVNiJwJYSyBBBgiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAgCWBUgtgrVevHl144YW0du1amjZtWmQ1DjzwQHr44Yd1+W3bttH555+vt83E2WefbW566UsuuUTn8cytc+bM0dtm4rPPPqOFCxeaWV76ueeeo4oVK3rpFStW0IABA7x0jx49qG3btlSzZk368ccfPb3ef/99mjlzZok6gjJat25NderUCdrl5a1atYpWr14dul/t6NSpE1WuXNnbfPvtt2nNmjVeOql8cQNYu3TpovnwicP0z6q+Hqz//DvqqKOoXbt21LJlS8+u3Fa5Tbz66qu0adMmatiwIR122GFe6W+//TanvfTp04d27txJjz76qFkl0iAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAnsIpB7A+vvf/566du1KDRo08AzAQZ4333xzZGPcdtttdPTRR+vyEyZMIA4qDVpeeOGFoOxIeRws2q9fvxJl/QGsPPvruHHjaK+99ipRljO++OILuvzyywP3mZmzZ8+mSpUqmVk56bfeeotuv/32nLygDWn54gSwPvLII1S/fn0t1vfff09XXnklrV+/XuepRFb1VfLdcccdxEG2QctPP/1EQ4cO9YKXa9eu7RX517/+Reecc44uPmnSJOJ9XHbZsmU0derUnABXXRAJEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABECiHBFIJYD3ooIO82VaPPfbYEoGecQJYeXbTJ598kipUqOCZigMku3XrFmo21wGs69at82ZNrVq1aqgMvOPLL7+kyy67LG8ZFwGdEvJFDWB94oknaP/999c6bt++nfr27UsbN27UeWYiq/qyjDzDL8/0m2/ZvXu3N9Oumu02LIDVrIPL/OMf/6Dx48eb2UiDAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAQLkj4DSA9cwzz6SzzjqL6tWrFwr2jTfeoJEjR4buN3dcf/31dOKJJ+qs6dOnE890GbZcc8013iyY5n5z9lYOsly6dKm5W6cXLVpEXL9/MWc4Nfdt2LCBPv30U6pYsaL3yfl9993X3E0sy/Lly3PyzI3hw4dT9erVdRbX07RpU72dZAZWffCeRFL5ogSwTp48mWrVqqVP980331CfPn1o27ZtOs+fyKq+AwcOpN/+9rc54jK7xYsXe3mtWrXKCdRVBf0BrDwzsJplWJVRa56VdeXKlTRt2jR68803VTbWIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIAACIFBuCIgHsDZs2JAuvvhiOuaYY6hSpUqBIH/88UcvIJAD+N57773AMkGZ5qydu3btoi5dugQVy5v3/PPP6xlclyxZQoMGDcpb3r/TH8DKwYg8++jMmTNzio4dO5YaN26s8z788EMaMmSI3o6SMGeQTRrAaitfvgBWnhGXZxOtUaOGVmfLli3ebLs6I0YiC/qabYxFf/HFF2ncuHE5WrAd27Vrl5PnD2Dlne3bt6fOnTtTo0aNdJvLOWjPBs8i/NprrxEHATM7LCAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiBQHgiIBbCeffbZ1KlTp8DZKRXI9evXewGB/mBPtT/fmmf07Nixoy7y97//ne6//369HTUhHcAaFlh60EEH0UMPPaTF4lk8e/bsqbejJCQCOm3lCwtgrVOnjhfYuc8++2hVkuioD96TKG19+/btSx06dNAirVixggYMGKC3zQTP/Fu7dm2dFRTAqnfuSfTq1Yt+97vfEQf9hi1r1qzxZmV99dVXw4ogHwRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAATKBAGrAFb+xP1FF11ErVu3Dp1tdceOHd5n0p966iniANaky6xZs6hy5cre4TyD65lnnpmoKukA1h49etCmTZsCZZk6dSpVr17d27d9+3bq3r17YLmwTImATlv5ggJY2RYPPvggVa1aVYv+xRdf0OWXX663kyRKW9/HHnuM6tatq0UfNmwYLVy4UG+biT/+8Y90/vnn66xCAayqYLNmzei8886jo48+OrTP/PDDD/TPf/7Tm5X166+/VodiDQIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAIgAAJlhkDiANa77rqLWrRoEQiCA0w/+eQTmj59emgAYOCBIZn+YMGwWUVDDs/Jlgxg5c+/d+vWLad+c+ORRx6h+vXre1m7d+/2Pidv7i+U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KI1v1DlpbwPW/v37m/POOy/O4VdffWWGDRtmXn311dhPTsTI9dRTT60xyk4asMqOqn369KmJN2vWLPPPf/7TTJw4scafCwhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAQGcj0BQDVhfquuuua+TT6ssvv3xkAJhmwHryySebNddcM44mO3yK4aiGS+7s+s4770S7u77wwgu5xGPA2taAVcBtttlm5tBDD61heNZZZ5k777yzxq/eRXsbsErexowZY5Zddtk4m2LEKu3vlltuifwGDBhg9t13X9O1a9c4jJxkGbBK/CeeeCLabfXFF1+sicMFBCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCECgsxJougGrC3qfffYxL7/8spFPtVsnu6NeccUV8e6WX3zxhdluu+3sbe+j7J4pn39Pc2JsaN0zzzxjjj76aHsZH7UNWJdaailzzjnntDGI7NKli+nRo0ecruwWO2fOnPjansgn6N0dbLXzt9FGG5kRI0bY5MzkyekGrBLgxBNPNGuvvXYcVnjutddeZubMmbFf1cu78sorm9NPP71NfcQFyDhJGrDKzq0zZsww119/fUYMvCEAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAp2XQLsasKZhP+qoo8yGG24Y35o0aVK0e2XsoXBy3HHHGdkJtp6Tz8YfdNBBbYJoG4ius8465oQTTmiTTl4PMZLcf//94+Da+StiwCqZuPrqq838888f5+e9994ze+65Z3xd9fJKRldYYYXIyLl79+5xvpMn0j569+5tFlpooehW0oA1GZ5rCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABL4nUDkDVtcAc+7cuWbw4MHf51bxbPPNNzeDBg0yffv2NfPMM0+846tN4rnnnjPDhw+3l/HRzZ98El522sxyf/rTn8zyyy8f3ZbdSCW9pKuKQWdW/tZbb72aHV7r7cAqZRPjz7PPPruG5+WXX27EEFlc1csbZfLbf4ssskhU/z/84Q9jg1xh9M4775gHHnjAjB8/PipTr169oihJQ10rhyMEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACbQlUyoD1gAMOMFtuuWWcy9tuu82cd9558TUnEGgvAssuu6x5/fXXa5J3jZmfeuopM2LEiJr7XEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCCQTqBSBqw33nhjtBuqZPXrr782AwcOTM81vhBoZwJLLbWUueiii+Jc3H777ebcc8+NrzmBAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAIJtAZQxYt9tuO7PHHnvEOb3//vvN6NGj42tOIFAlAqeccopZY4014iydc8455o477oivOYEABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAgm0BlDFglixtssEGc0/vuuy8+5wQCzSRw/fXXmxdffNFcffXV5tFHH22T9P77728GDBgQ+3/wwQdmyJAh8TUnEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCNQnUCkD1vpZ5S4EmkPg5ptvjhP68ssvzaxZs8zMmTPNAgssYJZYYgnTs2fP+L6cjBo1ykybNq3GjwsIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEsglgwJrNhjudlIBrwFoPwTfffGNuueUWM3bs2HrBuAcBCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIBAggAGrAkgXEJgzJgxpm/fvqZbt26ZMGRX1pNOOsm88MILmWG4AQEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgEA6AQxY07ngCwHTv39/s8IKK5hFF13U9OnTx8ycOdM89dRT5vHHH4cOBCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAh4EMGD1gEdUCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgeIEMGAtzowYEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAAC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"
+ }
+ },
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## An Opus-specific problem\n",
+ "\n",
+ "When working with Opus and tools, the model often outputs its thoughts in `` or `` tags before actually responding to a user. You can see an example of this in the screenshot below: \n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This thinking process tends to lead to better results, but it obviously makes for a terrible user experience. We don't want to expose that thinking logic to a user! The easiest fix here is to explicitly ask the model output its user-facing response in a particular set of XML tags. We start by updating the system prompt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "system_prompt = \"\"\"\n",
+ "You are a customer support chat bot for an online retailer called TechNova. \n",
+ "Your job is to help users look up their account, orders, and cancel orders.\n",
+ "Be helpful and brief in your responses.\n",
+ "You have access to a set of tools, but only use them when needed. \n",
+ "If you do not have enough information to use a tool correctly, ask a user follow up questions to get the required inputs.\n",
+ "Do not call any of the tools unless you have the required data from a user. \n",
+ "\n",
+ "In each conversational turn, you will begin by thinking about your response. \n",
+ "Once you're done, you will write a user-facing response. \n",
+ "It's important to place all user-facing conversational responses in XML tags to make them easy to parse.\n",
+ "\"\"\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Take a look at an example conversation output: \n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Claude is now responding with `` tags around the actual user-facing response. All we need to do now is extract the content between those tags and make sure that's the only part of the response we actually print to the user. Here's an updated `start_chat` function that does exactly that!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import re\n",
+ "\n",
+ "def extract_reply(text):\n",
+ " pattern = r'(.*?)'\n",
+ " match = re.search(pattern, text, re.DOTALL)\n",
+ " if match:\n",
+ " return match.group(1)\n",
+ " else:\n",
+ " return None \n",
+ " \n",
+ "def simple_chat():\n",
+ " system_prompt = \"\"\"\n",
+ " You are a customer support chat bot for an online retailer called TechNova. \n",
+ " Your job is to help users look up their account, orders, and cancel orders.\n",
+ " Be helpful and brief in your responses.\n",
+ " You have access to a set of tools, but only use them when needed. \n",
+ " If you do not have enough information to use a tool correctly, ask a user follow up questions to get the required inputs.\n",
+ " Do not call any of the tools unless you have the required data from a user. \n",
+ "\n",
+ " In each conversational turn, you will begin by thinking about your response. \n",
+ " Once you're done, you will write a user-facing response. \n",
+ " It's important to place all user-facing conversational responses in XML tags to make them easy to parse.\n",
+ " \"\"\"\n",
+ "\n",
+ " user_message = input(\"\\nUser: \")\n",
+ " messages = [{\"role\": \"user\", \"content\": [{\"text\": user_message}]}]\n",
+ "\n",
+ " while True:\n",
+ " #If the last message is from the assistant, get another input from the user\n",
+ " if messages[-1].get(\"role\") == \"assistant\":\n",
+ " user_message = input(\"\\nUser: \")\n",
+ " messages.append({\"role\": \"user\", \"content\": [{\"text\": user_message}]})\n",
+ "\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"system\": [{\"text\": system_prompt}],\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": {\"maxTokens\": 4096},\n",
+ " \"toolConfig\":toolConfig,\n",
+ " }\n",
+ "\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ "\n",
+ " messages.append({\"role\": \"assistant\", \"content\": response['output']['message']['content']})\n",
+ "\n",
+ " #If Claude stops because it wants to use a tool:\n",
+ " if response['stopReason'] == \"tool_use\":\n",
+ " tool_use = response['output']['message']['content'][-1] #Naive approach assumes only 1 tool is called at a time\n",
+ " tool_id = tool_use['toolUse']['toolUseId']\n",
+ " tool_name = tool_use['toolUse']['name']\n",
+ " tool_input = tool_use['toolUse']['input']\n",
+ "\n",
+ " print(f\"======Claude wants to use the {tool_name} tool======\")\n",
+ "\n",
+ " #Actually run the underlying tool functionality on our db\n",
+ " tool_result = process_tool_call(tool_name, tool_input)\n",
+ "\n",
+ " #Add our tool_result message:\n",
+ " messages.append({\n",
+ " \"role\": \"user\",\n",
+ " \"content\": [\n",
+ " {\n",
+ " \"toolResult\": {\n",
+ " \"toolUseId\": tool_id,\n",
+ " \"content\": [\n",
+ " {\"text\": str(tool_result)}\n",
+ " ]\n",
+ " }\n",
+ " }\n",
+ " ]\n",
+ " })\n",
+ " else: \n",
+ " #If Claude does NOT want to use a tool, just print out the text reponse\n",
+ " model_reply = extract_reply({response['output']['message']['content'][0]['text']})\n",
+ " print(\"\\nTechNova Support: \" + f\"{model_reply}\" )\n",
+ "\n",
+ "\n",
+ "# Start the chat!!\n",
+ "# simple_chat()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here's a screenshot showing the impact of the above change: \n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Final version\n",
+ "\n",
+ "Here's a screenshot of a longer conversation with a version of this script that colorizes the output.\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Closing notes\n",
+ "\n",
+ "This is an educational demo made to illustrate the tool use workflow. This script and prompt are NOT ready for production. The assistant responds with things like \"You can find the order ID on the order confirmation email\" without actually knowing if that's true. In the real world, we would need to provide Claude with lots of background knowledge about our particular company (at a bare minimum). We also need to rigorously test the chatbot and make sure it behaves well in all situations. Also, it's probably a bad idea to make it so easy for anyone to cancel an order! It would be pretty easy to cancel a lot of people's orders if you had access to their email, username, or phone number. In the real world, we would probably want some form of authentication. Long story short: this is a demo and not a complete chatbot implementation!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exercise\n",
+ "\n",
+ "* Add functionality to our assistant (and underlying `FakeDatabase` class) that allows a user to update their email and phone number.\n",
+ "* Define a new tool called `get_user_info` that combines the functionality of `get_user` and `get_customer_orders`. This tool should take a user's email, phone, or username as input and return the user's information along with their order history all in one go.\n",
+ "* Add error handling and input validation!\n",
+ "\n",
+ "\n",
+ "#### Bonus\n",
+ "* Update the chatbot to use an ACTUAL database instead of our `FakeDatabase` class."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "conda_tensorflow2_p310",
+ "language": "python",
+ "name": "conda_tensorflow2_p310"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/AmazonBedrock/boto3/10_3_Appendix_Empirical_Performance_Eval.ipynb b/AmazonBedrock/10_3_Appendix_Empirical_Performance_Eval.ipynb
similarity index 87%
rename from AmazonBedrock/boto3/10_3_Appendix_Empirical_Performance_Eval.ipynb
rename to AmazonBedrock/10_3_Appendix_Empirical_Performance_Eval.ipynb
index b248d8e..01b68ec 100755
--- a/AmazonBedrock/boto3/10_3_Appendix_Empirical_Performance_Eval.ipynb
+++ b/AmazonBedrock/10_3_Appendix_Empirical_Performance_Eval.ipynb
@@ -38,13 +38,11 @@
"# Import boto3 and json\n",
"import boto3\n",
"import json\n",
- "\n",
+ "from botocore.exceptions import ClientError\n",
"# Store the model name and AWS region for later use\n",
- "MODEL_NAME = \"anthropic.claude-3-haiku-20240307-v1:0\"\n",
- "AWS_REGION = \"us-west-2\"\n",
"\n",
- "%store MODEL_NAME\n",
- "%store AWS_REGION"
+ "%store -r modelId\n",
+ "%store -r region"
]
},
{
@@ -59,7 +57,7 @@
"def build_input_prompt(review):\n",
" user_content = f\"\"\"Classify the sentiment of the following movie review as either 'positive' or 'negative' provide only one of those two choices:\n",
" {review}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Define the evaluation data\n",
"eval = [\n",
@@ -74,22 +72,32 @@
"]\n",
"\n",
"# Function to get completions from the model\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(messages):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": messages,\n",
- " \"temperature\": 0.5,\n",
- " \"top_p\": 1,\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')\n",
+ "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)\n",
+ "\n",
+ "def get_completion(messages, system_prompt=None):\n",
+ " inference_config = {\n",
+ " \"temperature\": 0.5,\n",
+ " \"maxTokens\": 200\n",
+ " }\n",
+ " additional_model_fields = {\n",
+ " \"top_p\": 1\n",
+ " }\n",
+ " converse_api_params = {\n",
+ " \"modelId\": modelId,\n",
+ " \"messages\": messages,\n",
+ " \"inferenceConfig\": inference_config,\n",
+ " \"additionalModelRequestFields\": additional_model_fields\n",
+ " }\n",
+ " if system_prompt:\n",
+ " converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
+ " try:\n",
+ " response = bedrock_client.converse(**converse_api_params)\n",
+ " text_content = response['output']['message']['content'][0]['text']\n",
+ " return text_content\n",
+ "\n",
+ " except ClientError as err:\n",
+ " message = err.response['Error']['Message']\n",
+ " print(f\"A client error occured: {message}\")\n",
"\n",
"# Get completions for each input\n",
"outputs = [get_completion(build_input_prompt(item[\"review\"])) for item in eval]\n",
@@ -128,7 +136,7 @@
"def build_input_prompt(topic):\n",
" user_content = f\"\"\"Write a short essay discussing the following topic:\n",
" {topic}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Define the evaluation data\n",
"eval = [\n",
@@ -176,7 +184,7 @@
"def build_input_prompt(text):\n",
" user_content = f\"\"\"Please summarize the main points of the following text:\n",
" {text}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Function to build the grader prompt for assessing summary quality\n",
"def build_grader_prompt(output, rubric):\n",
@@ -184,7 +192,7 @@
" {rubric}\n",
" {output}\n",
" Provide a score from 1-5, where 1 is poor and 5 is excellent.\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Define the evaluation data\n",
"eval = [\n",
@@ -225,14 +233,14 @@
"def build_input_prompt(claim):\n",
" user_content = f\"\"\"Determine if the following claim is true or false:\n",
" {claim}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Function to build the grader prompt for assessing fact-check accuracy\n",
"def build_grader_prompt(output, rubric):\n",
" user_content = f\"\"\"Based on the following rubric, assess whether the fact-check is correct:\n",
" {rubric}\n",
" {output}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Define the evaluation data\n",
"eval = [\n",
@@ -283,14 +291,14 @@
"def build_input_prompt(text):\n",
" user_content = f\"\"\"Analyze the tone of the following text:\n",
" {text}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Function to build the grader prompt for assessing tone analysis accuracy\n",
"def build_grader_prompt(output, rubric):\n",
" user_content = f\"\"\"Assess the accuracy of the following tone analysis based on this rubric:\n",
" {rubric}\n",
" {output}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
+ " return [{\"role\": \"user\", \"content\": [{\"text\": user_content}]}]\n",
"\n",
"# Define the evaluation data\n",
"eval = [\n",
@@ -334,7 +342,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.13"
+ "version": "3.10.14"
}
},
"nbformat": 4,
diff --git a/AmazonBedrock/boto3/10_4_Appendix_Search_and_Retrieval.ipynb b/AmazonBedrock/10_4_Appendix_Search_and_Retrieval.ipynb
similarity index 94%
rename from AmazonBedrock/boto3/10_4_Appendix_Search_and_Retrieval.ipynb
rename to AmazonBedrock/10_4_Appendix_Search_and_Retrieval.ipynb
index 4eb0159..8f12a3f 100755
--- a/AmazonBedrock/boto3/10_4_Appendix_Search_and_Retrieval.ipynb
+++ b/AmazonBedrock/10_4_Appendix_Search_and_Retrieval.ipynb
@@ -15,10 +15,14 @@
}
],
"metadata": {
+ "kernelspec": {
+ "display_name": "",
+ "name": ""
+ },
"language_info": {
"name": "python"
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/AmazonBedrock/CODE_OF_CONDUCT.md b/AmazonBedrock/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..5b627cf
--- /dev/null
+++ b/AmazonBedrock/CODE_OF_CONDUCT.md
@@ -0,0 +1,4 @@
+## Code of Conduct
+This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
+For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
+opensource-codeofconduct@amazon.com with any additional questions or comments.
diff --git a/AmazonBedrock/README.md b/AmazonBedrock/README.md
index ccb51c6..bc1dbb9 100644
--- a/AmazonBedrock/README.md
+++ b/AmazonBedrock/README.md
@@ -9,16 +9,17 @@ This course is intended to provide you with a comprehensive step-by-step underst
- Recognize common failure modes and learn the '80/20' techniques to address them
- Understand Claude's strengths and weaknesses
- Build strong prompts from scratch for common use cases
+- Use advanced techniques that leverage Claude's tool use / function calling capabilities
## Course structure and content
This course is structured to allow you many chances to practice writing and troubleshooting prompts yourself. The course is broken up into **9 chapters with accompanying exercises**, as well as an appendix of even more advanced methods. It is intended for you to **work through the course in chapter order**.
-**Each lesson has an "Example Playground" area** at the bottom where you are free to experiment with the examples in the lesson and see for yourself how changing prompts can change Claude's responses. There is also an [answer key](https://docs.google.com/spreadsheets/d/1jIxjzUWG-6xBVIa2ay6yDpLyeuOh_hR_ZB75a47KX_E/edit?usp=sharing). While this answer key is structured for 1P API requests, the solutions are the same.
+**Each lesson has an "Example Playground" area** at the bottom where you are free to experiment with the examples in the lesson and see for yourself how changing prompts can change Claude's responses.
-Note: This tutorial uses our smallest, fastest, and cheapest model, Claude 3 Haiku. Anthropic has [two other models](https://docs.anthropic.com/claude/docs/models-overview), Claude 3 Sonnet and Claude 3 Opus, which are more intelligent than Haiku, with Opus being the most intelligent.
+Note: This tutorial uses our smallest, fastest, and cheapest model, Claude 3 Haiku. Anthropic has [two other models](https://aws.amazon.com/bedrock/claude/), Claude 3 Sonnet and Claude 3 Opus, which are more intelligent than Haiku, with Opus being the most intelligent.
-When you are ready to begin, go to `01_Basic Prompt Structure` to proceed.
+When you are ready to begin, go to `00_Tutorial_How-To` to proceed.
## Table of Contents
@@ -53,5 +54,4 @@ Each chapter consists of a lesson and a set of exercises.
- **Appendix:** Beyond Standard Prompting
- Chaining Prompts
- Tool Use
- - Empriical Performance Evaluations
- Search & Retrieval
\ No newline at end of file
diff --git a/AmazonBedrock/anthropic/00_Tutorial_How-To.ipynb b/AmazonBedrock/anthropic/00_Tutorial_How-To.ipynb
deleted file mode 100755
index cf56243..0000000
--- a/AmazonBedrock/anthropic/00_Tutorial_How-To.ipynb
+++ /dev/null
@@ -1,185 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Tutorial How-To\n",
- "\n",
- "This tutorial requires this initial notebook to be run first so that the requirements and environment variables are stored for all notebooks in the workshop"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## How to get started\n",
- "\n",
- "1. Clone this repository to your local machine.\n",
- "\n",
- "2. Install the required dependencies by running the following command:\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Note: you may need to restart the kernel to use updated packages.\n",
- "Note: you may need to restart the kernel to use updated packages.\n"
- ]
- }
- ],
- "source": [
- "%pip install -qU pip\n",
- "%pip install -qr ../requirements.txt"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "3. Restart the kernel after installing dependencies"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# restart kernel\n",
- "from IPython.core.display import HTML\n",
- "HTML(\"\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Usage Notes & Tips 💡\n",
- "\n",
- "- This course uses Claude 3 Haiku with temperature 0. We will talk more about temperature later in the course. For now, it's enough to understand that these settings yield more deterministic results. All prompt engineering techniques in this course also apply to previous generation legacy Claude models such as Claude 2 and Claude Instant 1.2.\n",
- "\n",
- "- You can use `Shift + Enter` to execute the cell and move to the next one.\n",
- "\n",
- "- When you reach the bottom of a tutorial page, navigate to the next numbered file in the folder, or to the next numbered folder if you're finished with the content within that chapter file.\n",
- "\n",
- "### The Anthropic SDK & the Messages API\n",
- "We will be using the [Anthropic python SDK](https://docs.anthropic.com/claude/reference/claude-on-amazon-bedrock) and the [Messages API](https://docs.anthropic.com/claude/reference/messages_post) throughout this tutorial.\n",
- "\n",
- "Below is an example of what running a prompt will look like in this tutorial."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First, we set and store the model name and region."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import boto3\n",
- "session = boto3.Session() # create a boto3 session to dynamically get and set the region name\n",
- "AWS_REGION = session.region_name\n",
- "print(\"AWS Region:\", AWS_REGION)\n",
- "MODEL_NAME = \"anthropic.claude-3-haiku-20240307-v1:0\"\n",
- "\n",
- "%store MODEL_NAME\n",
- "%store AWS_REGION"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Then, we create `get_completion`, which is a helper function that sends a prompt to Claude and returns Claude's generated response. Run that cell now."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we will write out an example prompt for Claude and print Claude's output by running our `get_completion` helper function. Running the cell below will print out a response from Claude beneath it.\n",
- "\n",
- "Feel free to play around with the prompt string to elicit different responses from Claude."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "prompt = \"Hello, Claude!\"\n",
- "\n",
- "# Get Claude's response\n",
- "print(get_completion(prompt))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The `MODEL_NAME` and `AWS_REGION` variables defined earlier will be used throughout the tutorial. Just make sure to run the cells for each tutorial page from top to bottom."
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "py310",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.11.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/02_Being_Clear_and_Direct.ipynb b/AmazonBedrock/anthropic/02_Being_Clear_and_Direct.ipynb
deleted file mode 100755
index 42afdab..0000000
--- a/AmazonBedrock/anthropic/02_Being_Clear_and_Direct.ipynb
+++ /dev/null
@@ -1,399 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 2: Being Clear and Direct\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "**Claude responds best to clear and direct instructions.**\n",
- "\n",
- "Think of Claude like any other human that is new to the job. **Claude has no context** on what to do aside from what you literally tell it. Just as when you instruct a human for the first time on a task, the more you explain exactly what you want in a straightforward manner to Claude, the better and more accurate Claude's response will be.\"\t\t\t\t\n",
- "\t\t\t\t\n",
- "When in doubt, follow the **Golden Rule of Clear Prompting**:\n",
- "- Show your prompt to a colleague or friend and have them follow the instructions themselves to see if they can produce the result you want. If they're confused, Claude's confused.\t\t\t\t"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "Let's take a task like writing poetry. (Ignore any syllable mismatch - LLMs aren't great at counting syllables yet.)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Write a haiku about robots.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This haiku is nice enough, but users may want Claude to go directly into the poem without the \"Here is a haiku\" preamble.\n",
- "\n",
- "How do we achieve that? We **ask for it**!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Write a haiku about robots. Skip the preamble; go straight into the poem.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here's another example. Let's ask Claude who's the best basketball player of all time. You can see below that while Claude lists a few names, **it doesn't respond with a definitive \"best\"**."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the best basketball player of all time?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Can we get Claude to make up its mind and decide on a best player? Yes! Just ask!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the best basketball player of all time? Yes, there are differing opinions, but if you absolutely had to pick one player, who would it be?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 2.1 - Spanish](#exercise-21---spanish)\n",
- "- [Exercise 2.2 - One Player Only](#exercise-22---one-player-only)\n",
- "- [Exercise 2.3 - Write a Story](#exercise-23---write-a-story)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 2.1 - Spanish\n",
- "Modify the `SYSTEM_PROMPT` to make Claude output its answer in Spanish."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt - this is the only field you should chnage\n",
- "SYSTEM_PROMPT = \"[Replace this text]\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"Hello Claude, how are you?\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT, SYSTEM_PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return \"hola\" in text.lower()\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n--------------------------- GRADING ---------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_2_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 2.2 - One Player Only\n",
- "\n",
- "Modify the `PROMPT` so that Claude doesn't equivocate at all and responds with **ONLY** the name of one specific player, with **no other words or punctuation**. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt - this is the only field you should change\n",
- "PROMPT = \"[Replace this text]\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return text == \"Michael Jordan\"\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n--------------------------- GRADING ---------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_2_2_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 2.3 - Write a Story\n",
- "\n",
- "Modify the `PROMPT` so that Claude responds with as long a response as you can muster. If your answer is **over 800 words**, Claude's response will be graded as correct."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt - this is the only field you should change\n",
- "PROMPT = \"[Replace this text]\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " trimmed = text.strip()\n",
- " words = len(trimmed.split())\n",
- " return words >= 800\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n--------------------------- GRADING ---------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_2_3_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Write a haiku about robots.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Write a haiku about robots. Skip the preamble; go straight into the poem.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the best basketball player of all time?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the best basketball player of all time? Yes, there are differing opinions, but if you absolutely had to pick one player, who would it be?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/03_Assigning_Roles_Role_Prompting.ipynb b/AmazonBedrock/anthropic/03_Assigning_Roles_Role_Prompting.ipynb
deleted file mode 100755
index 6aff6b1..0000000
--- a/AmazonBedrock/anthropic/03_Assigning_Roles_Role_Prompting.ipynb
+++ /dev/null
@@ -1,331 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 3: Assigning Roles (Role Prompting)\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "Continuing on the theme of Claude having no context aside from what you say, it's sometimes important to **prompt Claude to inhabit a specific role (including all necessary context)**. This is also known as role prompting. The more detail to the role context, the better.\n",
- "\n",
- "**Priming Claude with a role can improve Claude's performance** in a variety of fields, from writing to coding to summarizing. It's like how humans can sometimes be helped when told to \"think like a ______\". Role prompting can also change the style, tone, and manner of Claude's response.\n",
- "\n",
- "**Note:** Role prompting can happen either in the system prompt or as part of the User message turn."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "In the example below, we see that without role prompting, Claude provides a **straightforward and non-stylized answer** when asked to give a single sentence perspective on skateboarding.\n",
- "\n",
- "However, when we prime Claude to inhabit the role of a cat, Claude's perspective changes, and thus **Claude's response tone, style, content adapts to the new role**. \n",
- "\n",
- "**Note:** A bonus technique you can use is to **provide Claude context on its intended audience**. Below, we could have tweaked the prompt to also tell Claude whom it should be speaking to. \"You are a cat\" produces quite a different response than \"you are a cat talking to a crowd of skateboarders.\n",
- "\n",
- "Here is the prompt without role prompting in the system prompt:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"In one sentence, what do you think about skateboarding?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here is the same user question, except with role prompting."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"You are a cat.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"In one sentence, what do you think about skateboarding?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can use role prompting as a way to get Claude to emulate certain styles in writing, speak in a certain voice, or guide the complexity of its answers. **Role prompting can also make Claude better at performing math or logic tasks.**\n",
- "\n",
- "For example, in the example below, there is a definitive correct answer, which is yes. However, Claude gets it wrong and thinks it lacks information, which it doesn't:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Jack is looking at Anne. Anne is looking at George. Jack is married, George is not, and we don’t know if Anne is married. Is a married person looking at an unmarried person?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now, what if we **prime Claude to act as a logic bot**? How will that change Claude's answer? \n",
- "\n",
- "It turns out that with this new role assignment, Claude gets it right. (Although notably not for all the right reasons)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"You are a logic bot designed to answer complex logic problems.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"Jack is looking at Anne. Anne is looking at George. Jack is married, George is not, and we don’t know if Anne is married. Is a married person looking at an unmarried person?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Note:** What you'll learn throughout this course is that there are **many prompt engineering techniques you can use to derive similar results**. Which techniques you use is up to you and your preference! We encourage you to **experiment to find your own prompt engineering style**.\n",
- "\n",
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 3.1 - Math Correction](#exercise-31---math-correction)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 3.1 - Math Correction\n",
- "In some instances, **Claude may struggle with mathematics**, even simple mathematics. Below, Claude incorrectly assesses the math problem as correctly solved, even though there's an obvious arithmetic mistake in the second step. Note that Claude actually catches the mistake when going through step-by-step, but doesn't jump to the conclusion that the overall solution is wrong.\n",
- "\n",
- "Modify the `PROMPT` and / or the `SYSTEM_PROMPT` to make Claude grade the solution as `incorrectly` solved, rather than correctly solved. \n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt - if you don't want to use a system prompt, you can leave this variable set to an empty string\n",
- "SYSTEM_PROMPT = \"\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"\"\"Is this equation solved correctly below?\n",
- "\n",
- "2x - 3 = 9\n",
- "2x = 6\n",
- "x = 3\"\"\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT, SYSTEM_PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " if \"incorrect\" in text or \"not correct\" in text.lower():\n",
- " return True\n",
- " else:\n",
- " return False\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n--------------------------- GRADING ---------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_3_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"In one sentence, what do you think about skateboarding?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"You are a cat.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"In one sentence, what do you think about skateboarding?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Jack is looking at Anne. Anne is looking at George. Jack is married, George is not, and we don’t know if Anne is married. Is a married person looking at an unmarried person?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"You are a logic bot designed to answer complex logic problems.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"Jack is looking at Anne. Anne is looking at George. Jack is married, George is not, and we don’t know if Anne is married. Is a married person looking at an unmarried person?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/04_Separating_Data_and_Instructions.ipynb b/AmazonBedrock/anthropic/04_Separating_Data_and_Instructions.ipynb
deleted file mode 100755
index 010a847..0000000
--- a/AmazonBedrock/anthropic/04_Separating_Data_and_Instructions.ipynb
+++ /dev/null
@@ -1,558 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 4: Separating Data and Instructions\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "Oftentimes, we don't want to write full prompts, but instead want **prompt templates that can be modified later with additional input data before submitting to Claude**. This might come in handy if you want Claude to do the same thing every time, but the data that Claude uses for its task might be different each time. \n",
- "\n",
- "Luckily, we can do this pretty easily by **separating the fixed skeleton of the prompt from variable user input, then substituting the user input into the prompt** before sending the full prompt to Claude. \n",
- "\n",
- "Below, we'll walk step by step through how to write a substitutable prompt template, as well as how to substitute in user input."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "In this first example, we're asking Claude to act as an animal noise generator. Notice that the full prompt submitted to Claude is just the `PROMPT_TEMPLATE` substituted with the input (in this case, \"Cow\"). Notice that the word \"Cow\" replaces the `ANIMAL` placeholder via an f-string when we print out the full prompt.\n",
- "\n",
- "**Note:** You don't have to call your placeholder variable anything in particular in practice. We called it `ANIMAL` in this example, but just as easily, we could have called it `CREATURE` or `A` (although it's generally good to have your variable names be specific and relevant so that your prompt template is easy to understand even without the substitution, just for user parseability). Just make sure that whatever you name your variable is what you use for the prompt template f-string."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Cow\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"I will tell you the name of an animal. Please respond with the noise that animal makes. {ANIMAL}\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Why would we want to separate and substitute inputs like this? Well, **prompt templates simplify repetitive tasks**. Let's say you build a prompt structure that invites third party users to submit content to the prompt (in this case the animal whose sound they want to generate). These third party users don't have to write or even see the full prompt. All they have to do is fill in variables.\n",
- "\n",
- "We do this substitution here using variables and f-strings, but you can also do it with the format() method.\n",
- "\n",
- "**Note:** Prompt templates can have as many variables as desired!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "When introducing substitution variables like this, it is very important to **make sure Claude knows where variables start and end** (vs. instructions or task descriptions). Let's look at an example where there is no separation between the instructions and the substitution variable.\n",
- "\n",
- "To our human eyes, it is very clear where the variable begins and ends in the prompt template below. However, in the fully substituted prompt, that delineation becomes unclear."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "EMAIL = \"Show up at 6am tomorrow because I'm the CEO and I say so.\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Yo Claude. {EMAIL} <----- Make this email more polite but don't change anything else about it.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here, **Claude thinks \"Yo Claude\" is part of the email it's supposed to rewrite**! You can tell because it begins its rewrite with \"Dear Claude\". To the human eye, it's clear, particularly in the prompt template where the email begins and ends, but it becomes much less clear in the prompt after substitution."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "How do we solve this? **Wrap the input in XML tags**! We did this below, and as you can see, there's no more \"Dear Claude\" in the output.\n",
- "\n",
- "[XML tags](https://docs.anthropic.com/claude/docs/use-xml-tags) are angle-bracket tags like ``. They come in pairs and consist of an opening tag, such as ``, and a closing tag marked by a `/`, such as ``. XML tags are used to wrap around content, like this: `content`.\n",
- "\n",
- "**Note:** While Claude can recognize and work with a wide range of separators and delimeters, we recommend that you **use specifically XML tags as separators** for Claude, as Claude was trained specifically to recognize XML tags as a prompt organizing mechanism. Outside of function calling, **there are no special sauce XML tags that Claude has been trained on that you should use to maximally boost your performance**. We have purposefully made Claude very malleable and customizable this way."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "EMAIL = \"Show up at 6am tomorrow because I'm the CEO and I say so.\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Yo Claude. {EMAIL} <----- Make this email more polite but don't change anything else about it.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's see another example of how XML tags can help us. \n",
- "\n",
- "In the following prompt, **Claude incorrectly interprets what part of the prompt is the instruction vs. the input**. It incorrectly considers `Each is about an animal, like rabbits` to be part of the list due to the formatting, when the user (the one filling out the `SENTENCES` variable) presumably did not want that."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "SENTENCES = \"\"\"- I like how cows sound\n",
- "- This sentence is about spiders\n",
- "- This sentence may appear to be about dogs but it's actually about pigs\"\"\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"\"\"Below is a list of sentences. Tell me the second item on the list.\n",
- "\n",
- "- Each is about an animal, like rabbits.\n",
- "{SENTENCES}\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To fix this, we just need to **surround the user input sentences in XML tags**. This shows Claude where the input data begins and ends despite the misleading hyphen before `Each is about an animal, like rabbits.`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "SENTENCES = \"\"\"- I like how cows sound\n",
- "- This sentence is about spiders\n",
- "- This sentence may appear to be about dogs but it's actually about pigs\"\"\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"\"\" Below is a list of sentences. Tell me the second item on the list.\n",
- "\n",
- "- Each is about an animal, like rabbits.\n",
- "\n",
- "{SENTENCES}\n",
- "\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Note:** In the incorrect version of the \"Each is about an animal\" prompt, we had to include the hyphen to get Claude to respond incorrectly in the way we wanted to for this example. This is an important lesson about prompting: **small details matter**! It's always worth it to **scrub your prompts for typos and grammatical errors**. Claude is sensitive to patterns (in its early years, before finetuning, it was a raw text-prediction tool), and it's more likely to make mistakes when you make mistakes, smarter when you sound smart, sillier when you sound silly, and so on.\n",
- "\n",
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 4.1 - Haiku Topic](#exercise-41---haiku-topic)\n",
- "- [Exercise 4.2 - Dog Question with Typos](#exercise-42---dog-question-with-typos)\n",
- "- [Exercise 4.3 - Dog Question Part 2](#exercise-42---dog-question-part-2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 4.1 - Haiku Topic\n",
- "Modify the `PROMPT` so that it's a template that will take in a variable called `TOPIC` and output a haiku about the topic. This exercise is just meant to test your understanding of the variable templating structure with f-strings."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "TOPIC = \"Pigs\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(\"pigs\", text.lower()) and re.search(\"haiku\", text.lower()))\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_4_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 4.2 - Dog Question with Typos\n",
- "Fix the `PROMPT` by adding XML tags so that Claude produces the right answer. \n",
- "\n",
- "Try not to change anything else about the prompt. The messy and mistake-ridden writing is intentional, so you can see how Claude reacts to such mistakes."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "QUESTION = \"ar cn brown?\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Hia its me i have a q about dogs jkaerjv {QUESTION} jklmvca tx it help me muhch much atx fst fst answer short short tx\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(\"brown\", text.lower()))\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_4_2_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 4.3 - Dog Question Part 2\n",
- "Fix the `PROMPT` **WITHOUT** adding XML tags. Instead, remove only one or two words from the prompt.\n",
- "\n",
- "Just as with the above exercises, try not to change anything else about the prompt. This will show you what kind of language Claude can parse and understand."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "QUESTION = \"ar cn brown?\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Hia its me i have a q about dogs jkaerjv {QUESTION} jklmvca tx it help me muhch much atx fst fst answer short short tx\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(\"brown\", text.lower()))\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_4_3_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Cow\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"I will tell you the name of an animal. Please respond with the noise that animal makes. {ANIMAL}\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "EMAIL = \"Show up at 6am tomorrow because I'm the CEO and I say so.\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Yo Claude. {EMAIL} <----- Make this email more polite but don't change anything else about it.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "EMAIL = \"Show up at 6am tomorrow because I'm the CEO and I say so.\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Yo Claude. {EMAIL} <----- Make this email more polite but don't change anything else about it.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "SENTENCES = \"\"\"- I like how cows sound\n",
- "- This sentence is about spiders\n",
- "- This sentence may appear to be about dogs but it's actually about pigs\"\"\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"\"\"Below is a list of sentences. Tell me the second item on the list.\n",
- "\n",
- "- Each is about an animal, like rabbits.\n",
- "{SENTENCES}\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "SENTENCES = \"\"\"- I like how cows sound\n",
- "- This sentence is about spiders\n",
- "- This sentence may appear to be about dogs but it's actually about pigs\"\"\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"\"\" Below is a list of sentences. Tell me the second item on the list.\n",
- "\n",
- "- Each is about an animal, like rabbits.\n",
- "\n",
- "{SENTENCES}\n",
- "\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/05_Formatting_Output_and_Speaking_for_Claude.ipynb b/AmazonBedrock/anthropic/05_Formatting_Output_and_Speaking_for_Claude.ipynb
deleted file mode 100755
index 54859ef..0000000
--- a/AmazonBedrock/anthropic/05_Formatting_Output_and_Speaking_for_Claude.ipynb
+++ /dev/null
@@ -1,528 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 5: Formatting Output and Speaking for Claude\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "**Claude can format its output in a wide variety of ways**. You just need to ask for it to do so!\n",
- "\n",
- "One of these ways is by using XML tags to separate out the response from any other superfluous text. You've already learned that you can use XML tags to make your prompt clearer and more parseable to Claude. It turns out, you can also ask Claude to **use XML tags to make its output clearer and more easily understandable** to humans."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "Remember the 'poem preamble problem' we solved in Chapter 2 by asking Claude to skip the preamble entirely? It turns out we can also achieve a similar outcome by **telling Claude to put the poem in XML tags**."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Rabbit\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Put it in tags.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Why is this something we'd want to do? Well, having the output in **XML tags allows the end user to reliably get the poem and only the poem by writing a short program to extract the content between XML tags**.\n",
- "\n",
- "An extension of this technique is to **put the first XML tag in the `assistant` turn. When you put text in the `assistant` turn, you're basically telling Claude that Claude has already said something, and that it should continue from that point onward. This technique is called \"speaking for Claude\" or \"prefilling Claude's response.\"\n",
- "\n",
- "Below, we've done this with the first `` XML tag. Notice how Claude continues directly from where we left off."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Cat\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Put it in tags.\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN:\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN:\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Claude also excels at using other output formatting styles, notably `JSON`. If you want to enforce JSON output (not deterministically, but close to it), you can also prefill Claude's response with the opening bracket, `{`}."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Cat\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Use JSON format with the keys as \\\"first_line\\\", \\\"second_line\\\", and \\\"third_line\\\".\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"{\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Below is an example of **multiple input variables in the same prompt AND output formatting specification, all done using XML tags**."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# First input variable\n",
- "EMAIL = \"Hi Zack, just pinging you for a quick update on that prompt you were supposed to write.\"\n",
- "\n",
- "# Second input variable\n",
- "ADJECTIVE = \"olde english\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Hey Claude. Here is an email: {EMAIL}. Make this email more {ADJECTIVE}. Write the new version in <{ADJECTIVE}_email> XML tags.\"\n",
- "\n",
- "# Prefill for Claude's response (now as an f-string with a variable)\n",
- "PREFILL = f\"<{ADJECTIVE}_email>\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Bonus lesson\n",
- "\n",
- "If you are calling Claude through the API, you can pass the closing XML tag to the `stop_sequences` parameter to get Claude to stop sampling once it emits your desired tag. This can save money and time-to-last-token by eliminating Claude's concluding remarks after it's already given you the answer you care about.\n",
- "\n",
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 5.1 - Steph Curry GOAT](#exercise-51---steph-curry-goat)\n",
- "- [Exercise 5.2 - Two Haikus](#exercise-52---two-haikus)\n",
- "- [Exercise 5.3 - Two Haikus, Two Animals](#exercise-53---two-haikus-two-animals)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 5.1 - Steph Curry GOAT\n",
- "Forced to make a choice, Claude designates Michael Jordan as the best basketball player of all time. Can we get Claude to pick someone else?\n",
- "\n",
- "Change the `PREFILL` variable to **compell Claude to make a detailed argument that the best basketball player of all time is Stephen Curry**. Try not to change anything except `PREFILL` as that is the focus of this exercise."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Who is the best basketball player of all time? Please choose one specific player.\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT, prefill=PREFILL)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(\"Warrior\", text))\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_5_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 5.2 - Two Haikus\n",
- "Modify the `PROMPT` below using XML tags so that Claude writes two haikus about the animal instead of just one. It should be clear where one poem ends and the other begins."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"cats\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Put it in tags.\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT, prefill=PREFILL)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(\n",
- " (re.search(\"cat\", text.lower()) and re.search(\"\", text))\n",
- " and (text.count(\"\\n\") + 1) > 5\n",
- " )\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_5_2_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 5.3 - Two Haikus, Two Animals\n",
- "Modify the `PROMPT` below so that **Claude produces two haikus about two different animals**. Use `{ANIMAL1}` as a stand-in for the first substitution, and `{ANIMAL2}` as a stand-in for the second substitution."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# First input variable\n",
- "ANIMAL1 = \"Cat\"\n",
- "\n",
- "# Second input variable\n",
- "ANIMAL2 = \"Dog\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL1}. Put it in tags.\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(\"tail\", text.lower()) and re.search(\"cat\", text.lower()) and re.search(\"\", text))\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_5_3_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Rabbit\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Put it in tags.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(PROMPT)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Cat\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Put it in tags.\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN:\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN:\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Variable content\n",
- "ANIMAL = \"Cat\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Please write a haiku about {ANIMAL}. Use JSON format with the keys as \\\"first_line\\\", \\\"second_line\\\", and \\\"third_line\\\".\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"{\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# First input variable\n",
- "EMAIL = \"Hi Zack, just pinging you for a quick update on that prompt you were supposed to write.\"\n",
- "\n",
- "# Second input variable\n",
- "ADJECTIVE = \"olde english\"\n",
- "\n",
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = f\"Hey Claude. Here is an email: {EMAIL}. Make this email more {ADJECTIVE}. Write the new version in <{ADJECTIVE}_email> XML tags.\"\n",
- "\n",
- "# Prefill for Claude's response (now as an f-string with a variable)\n",
- "PREFILL = f\"<{ADJECTIVE}_email>\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.12.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/06_Precognition_Thinking_Step_by_Step.ipynb b/AmazonBedrock/anthropic/06_Precognition_Thinking_Step_by_Step.ipynb
deleted file mode 100755
index c8bd5a8..0000000
--- a/AmazonBedrock/anthropic/06_Precognition_Thinking_Step_by_Step.ipynb
+++ /dev/null
@@ -1,508 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 6: Precognition (Thinking Step by Step)\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "If someone woke you up and immediately started asking you several complicated questions that you had to respond to right away, how would you do? Probably not as good as if you were given time to **think through your answer first**. \n",
- "\n",
- "Guess what? Claude is the same way.\n",
- "\n",
- "**Giving Claude time to think step by step sometimes makes Claude more accurate**, particularly for complex tasks. However, **thinking only counts when it's out loud**. You cannot ask Claude to think but output only the answer - in this case, no thinking has actually occurred."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "In the prompt below, it's clear to a human reader that the second sentence belies the first. But **Claude takes the word \"unrelated\" too literally**."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"Is this movie review sentiment positive or negative?\n",
- "\n",
- "This movie blew my mind with its freshness and originality. In totally unrelated news, I have been living under a rock since the year 1900.\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To improve Claude's response, let's **allow Claude to think things out first before answering**. We do that by literally spelling out the steps that Claude should take in order to process and think through its task. Along with a dash of role prompting, this empowers Claude to understand the review more deeply."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"You are a savvy reader of movie reviews.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"\"\"Is this review sentiment positive or negative? First, write the best arguments for each side in and XML tags, then answer.\n",
- "\n",
- "This movie blew my mind with its freshness and originality. In totally unrelated news, I have been living under a rock since 1900.\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Claude is sometimes sensitive to ordering**. This example is on the frontier of Claude's ability to understand nuanced text, and when we swap the order of the arguments from the previous example so that negative is first and positive is second, this changes Claude's overall assessment to positive.\n",
- "\n",
- "In most situations (but not all, confusingly enough), **Claude is more likely to choose the second of two options**, possibly because in its training data from the web, second options were more likely to be correct."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"Is this review sentiment negative or positive? First write the best arguments for each side in and XML tags, then answer.\n",
- "\n",
- "This movie blew my mind with its freshness and originality. Unrelatedly, I have been living under a rock since 1900.\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Letting Claude think can shift Claude's answer from incorrect to correct**. It's that simple in many cases where Claude makes mistakes!\n",
- "\n",
- "Let's go through an example where Claude's answer is incorrect to see how asking Claude to think can fix that."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Name a famous movie starring an actor who was born in the year 1956.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's fix this by asking Claude to think step by step, this time in `` tags."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Name a famous movie starring an actor who was born in the year 1956. First brainstorm about some actors and their birth years in tags, then give your answer.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 6.1 - Classifying Emails](#exercise-61---classifying-emails)\n",
- "- [Exercise 6.2 - Email Classification Formatting](#exercise-62---email-classification-formatting)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 6.1 - Classifying Emails\n",
- "In this exercise, we'll be instructing Claude to sort emails into the following categories:\t\t\t\t\t\t\t\t\t\t\n",
- "- (A) Pre-sale question\n",
- "- (B) Broken or defective item\n",
- "- (C) Billing question\n",
- "- (D) Other (please explain)\n",
- "\n",
- "For the first part of the exercise, change the `PROMPT` to **make Claude output the correct classification and ONLY the classification**. Your answer needs to **include the letter (A - D) of the correct choice, with the parentheses, as well as the name of the category**.\n",
- "\n",
- "Refer to the comments beside each email in the `EMAILS` list to know which category that email should be classified under."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = \"\"\"Please classify this email as either green or blue: {email}\"\"\"\n",
- "\n",
- "# Prefill for Claude's response, if any\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Variable content stored as a list\n",
- "EMAILS = [\n",
- " \"Hi -- My Mixmaster4000 is producing a strange noise when I operate it. It also smells a bit smoky and plasticky, like burning electronics. I need a replacement.\", # (B) Broken or defective item\n",
- " \"Can I use my Mixmaster 4000 to mix paint, or is it only meant for mixing food?\", # (A) Pre-sale question OR (D) Other (please explain)\n",
- " \"I HAVE BEEN WAITING 4 MONTHS FOR MY MONTHLY CHARGES TO END AFTER CANCELLING!! WTF IS GOING ON???\", # (C) Billing question\n",
- " \"How did I get here I am not good with computer. Halp.\" # (D) Other (please explain)\n",
- "]\n",
- "\n",
- "# Correct categorizations stored as a list of lists to accommodate the possibility of multiple correct categorizations per email\n",
- "ANSWERS = [\n",
- " [\"B\"],\n",
- " [\"A\",\"D\"],\n",
- " [\"C\"],\n",
- " [\"D\"]\n",
- "]\n",
- "\n",
- "# Dictionary of string values for each category to be used for regex grading\n",
- "REGEX_CATEGORIES = {\n",
- " \"A\": \"A\\) P\",\n",
- " \"B\": \"B\\) B\",\n",
- " \"C\": \"C\\) B\",\n",
- " \"D\": \"D\\) O\"\n",
- "}\n",
- "\n",
- "# Iterate through list of emails\n",
- "for i,email in enumerate(EMAILS):\n",
- " \n",
- " # Substitute the email text into the email placeholder variable\n",
- " formatted_prompt = PROMPT.format(email=email)\n",
- " \n",
- " # Get Claude's response\n",
- " response = get_completion(formatted_prompt, prefill=PREFILL)\n",
- "\n",
- " # Grade Claude's response\n",
- " grade = any([bool(re.search(REGEX_CATEGORIES[ans], response)) for ans in ANSWERS[i]])\n",
- " \n",
- " # Print Claude's response\n",
- " print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- " print(\"USER TURN\")\n",
- " print(formatted_prompt)\n",
- " print(\"\\nASSISTANT TURN\")\n",
- " print(PREFILL)\n",
- " print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- " print(response)\n",
- " print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- " print(\"This exercise has been correctly solved:\", grade, \"\\n\\n\\n\\n\\n\\n\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_6_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Still stuck? Run the cell below for an example solution.\t\t\t\t\t\t"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_6_1_solution)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 6.2 - Email Classification Formatting\n",
- "In this exercise, we're going to refine the output of the above prompt to yield an answer formatted exactly how we want it. \n",
- "\n",
- "Use your favorite output formatting technique to make Claude wrap JUST the letter of the correct classification in `` tags. For instance, the answer to the first email should contain the exact string `B`.\n",
- "\n",
- "Refer to the comments beside each email in the `EMAILS` list if you forget which letter category is correct for each email."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = \"\"\"Please classify this email as either green or blue: {email}\"\"\"\n",
- "\n",
- "# Prefill for Claude's response, if any\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Variable content stored as a list\n",
- "EMAILS = [\n",
- " \"Hi -- My Mixmaster4000 is producing a strange noise when I operate it. It also smells a bit smoky and plasticky, like burning electronics. I need a replacement.\", # (B) Broken or defective item\n",
- " \"Can I use my Mixmaster 4000 to mix paint, or is it only meant for mixing food?\", # (A) Pre-sale question OR (D) Other (please explain)\n",
- " \"I HAVE BEEN WAITING 4 MONTHS FOR MY MONTHLY CHARGES TO END AFTER CANCELLING!! WTF IS GOING ON???\", # (C) Billing question\n",
- " \"How did I get here I am not good with computer. Halp.\" # (D) Other (please explain)\n",
- "]\n",
- "\n",
- "# Correct categorizations stored as a list of lists to accommodate the possibility of multiple correct categorizations per email\n",
- "ANSWERS = [\n",
- " [\"B\"],\n",
- " [\"A\",\"D\"],\n",
- " [\"C\"],\n",
- " [\"D\"]\n",
- "]\n",
- "\n",
- "# Dictionary of string values for each category to be used for regex grading\n",
- "REGEX_CATEGORIES = {\n",
- " \"A\": \"A\",\n",
- " \"B\": \"B\",\n",
- " \"C\": \"C\",\n",
- " \"D\": \"D\"\n",
- "}\n",
- "\n",
- "# Iterate through list of emails\n",
- "for i,email in enumerate(EMAILS):\n",
- " \n",
- " # Substitute the email text into the email placeholder variable\n",
- " formatted_prompt = PROMPT.format(email=email)\n",
- " \n",
- " # Get Claude's response\n",
- " response = get_completion(formatted_prompt, prefill=PREFILL)\n",
- "\n",
- " # Grade Claude's response\n",
- " grade = any([bool(re.search(REGEX_CATEGORIES[ans], response)) for ans in ANSWERS[i]])\n",
- " \n",
- " # Print Claude's response\n",
- " print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- " print(\"USER TURN\")\n",
- " print(formatted_prompt)\n",
- " print(\"\\nASSISTANT TURN\")\n",
- " print(PREFILL)\n",
- " print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- " print(response)\n",
- " print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- " print(\"This exercise has been correctly solved:\", grade, \"\\n\\n\\n\\n\\n\\n\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_6_2_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"Is this movie review sentiment positive or negative?\n",
- "\n",
- "This movie blew my mind with its freshness and originality. In totally unrelated news, I have been living under a rock since the year 1900.\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"You are a savvy reader of movie reviews.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"\"\"Is this review sentiment positive or negative? First, write the best arguments for each side in and XML tags, then answer.\n",
- "\n",
- "This movie blew my mind with its freshness and originality. In totally unrelated news, I have been living under a rock since 1900.\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"Is this review sentiment negative or positive? First write the best arguments for each side in and XML tags, then answer.\n",
- "\n",
- "This movie blew my mind with its freshness and originality. Unrelatedly, I have been living under a rock since 1900.\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Name a famous movie starring an actor who was born in the year 1956.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Name a famous movie starring an actor who was born in the year 1956. First brainstorm about some actors and their birth years in tags, then give your answer.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "name": "python",
- "version": "3.12.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/07_Using_Examples _Few-Shot_Prompting.ipynb b/AmazonBedrock/anthropic/07_Using_Examples _Few-Shot_Prompting.ipynb
deleted file mode 100755
index aedaaf4..0000000
--- a/AmazonBedrock/anthropic/07_Using_Examples _Few-Shot_Prompting.ipynb
+++ /dev/null
@@ -1,397 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 7: Using Examples (Few-Shot Prompting)\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "**Giving Claude examples of how you want it to behave (or how you want it not to behave) is extremely effective** for:\n",
- "- Getting the right answer\n",
- "- Getting the answer in the right format\n",
- "\n",
- "This sort of prompting is also called \"**few shot prompting**\". You might also encounter the phrase \"zero-shot\" or \"n-shot\" or \"one-shot\". The number of \"shots\" refers to how many examples are used within the prompt."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "Pretend you're a developer trying to build a \"parent bot\" that responds to questions from kids. **Claude's default response is quite formal and robotic**. This is going to break a child's heart."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Will Santa bring me presents on Christmas?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You could take the time to describe your desired tone, but it's much easier just to **give Claude a few examples of ideal responses**."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"Please complete the conversation by writing the next line, speaking as \"A\".\n",
- "Q: Is the tooth fairy real?\n",
- "A: Of course, sweetie. Wrap up your tooth and put it under your pillow tonight. There might be something waiting for you in the morning.\n",
- "Q: Will Santa bring me presents on Christmas?\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In the following formatting example, we could walk Claude step by step through a set of formatting instructions on how to extract names and professions and then format them exactly the way we want, or we could just **provide Claude with some correctly-formatted examples and Claude can extrapolate from there**. Note the `` in the `assistant` turn to start Claude off on the right foot."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = \"\"\"Silvermist Hollow, a charming village, was home to an extraordinary group of individuals.\n",
- "Among them was Dr. Liam Patel, a neurosurgeon who revolutionized surgical techniques at the regional medical center.\n",
- "Olivia Chen was an innovative architect who transformed the village's landscape with her sustainable and breathtaking designs.\n",
- "The local theater was graced by the enchanting symphonies of Ethan Kovacs, a professionally-trained musician and composer.\n",
- "Isabella Torres, a self-taught chef with a passion for locally sourced ingredients, created a culinary sensation with her farm-to-table restaurant, which became a must-visit destination for food lovers.\n",
- "These remarkable individuals, each with their distinct talents, contributed to the vibrant tapestry of life in Silvermist Hollow.\n",
- "\n",
- "1. Dr. Liam Patel [NEUROSURGEON]\n",
- "2. Olivia Chen [ARCHITECT]\n",
- "3. Ethan Kovacs [MISICIAN AND COMPOSER]\n",
- "4. Isabella Torres [CHEF]\n",
- "\n",
- "\n",
- "At the heart of the town, Chef Oliver Hamilton has transformed the culinary scene with his farm-to-table restaurant, Green Plate. Oliver's dedication to sourcing local, organic ingredients has earned the establishment rave reviews from food critics and locals alike.\n",
- "Just down the street, you'll find the Riverside Grove Library, where head librarian Elizabeth Chen has worked diligently to create a welcoming and inclusive space for all. Her efforts to expand the library's offerings and establish reading programs for children have had a significant impact on the town's literacy rates.\n",
- "As you stroll through the charming town square, you'll be captivated by the beautiful murals adorning the walls. These masterpieces are the work of renowned artist, Isabella Torres, whose talent for capturing the essence of Riverside Grove has brought the town to life.\n",
- "Riverside Grove's athletic achievements are also worth noting, thanks to former Olympic swimmer-turned-coach, Marcus Jenkins. Marcus has used his experience and passion to train the town's youth, leading the Riverside Grove Swim Team to several regional championships.\n",
- "\n",
- "1. Oliver Hamilton [CHEF]\n",
- "2. Elizabeth Chen [LIBRARIAN]\n",
- "3. Isabella Torres [ARTIST]\n",
- "4. Marcus Jenkins [COACH]\n",
- "\n",
- "\n",
- "Oak Valley, a charming small town, is home to a remarkable trio of individuals whose skills and dedication have left a lasting impact on the community.\n",
- "At the town's bustling farmer's market, you'll find Laura Simmons, a passionate organic farmer known for her delicious and sustainably grown produce. Her dedication to promoting healthy eating has inspired the town to embrace a more eco-conscious lifestyle.\n",
- "In Oak Valley's community center, Kevin Alvarez, a skilled dance instructor, has brought the joy of movement to people of all ages. His inclusive dance classes have fostered a sense of unity and self-expression among residents, enriching the local arts scene.\n",
- "Lastly, Rachel O'Connor, a tireless volunteer, dedicates her time to various charitable initiatives. Her commitment to improving the lives of others has been instrumental in creating a strong sense of community within Oak Valley.\n",
- "Through their unique talents and unwavering dedication, Laura, Kevin, and Rachel have woven themselves into the fabric of Oak Valley, helping to create a vibrant and thriving small town.\"\"\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN:\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN:\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 7.1 - Email Formatting via Examples](#exercise-71---email-formatting-via-examples)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 7.1 - Email Formatting via Examples\n",
- "We're going to redo Exercise 6.2, but this time, we're going to edit the `PROMPT` to use \"few-shot\" examples of emails + proper classification (and formatting) to get Claude to output the correct answer. We want the *last* letter of Claude's output to be the letter of the category.\n",
- "\n",
- "Refer to the comments beside each email in the `EMAILS` list if you forget which letter category is correct for each email.\n",
- "\n",
- "Remember that these are the categories for the emails:\t\t\t\t\t\t\t\t\t\t\n",
- "- (A) Pre-sale question\n",
- "- (B) Broken or defective item\n",
- "- (C) Billing question\n",
- "- (D) Other (please explain)\t\t\t\t\t\t\t\t"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = \"\"\"Please classify this email as either green or blue: {email}\"\"\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Variable content stored as a list\n",
- "EMAILS = [\n",
- " \"Hi -- My Mixmaster4000 is producing a strange noise when I operate it. It also smells a bit smoky and plasticky, like burning electronics. I need a replacement.\", # (B) Broken or defective item\n",
- " \"Can I use my Mixmaster 4000 to mix paint, or is it only meant for mixing food?\", # (A) Pre-sale question OR (D) Other (please explain)\n",
- " \"I HAVE BEEN WAITING 4 MONTHS FOR MY MONTHLY CHARGES TO END AFTER CANCELLING!! WTF IS GOING ON???\", # (C) Billing question\n",
- " \"How did I get here I am not good with computer. Halp.\" # (D) Other (please explain)\n",
- "]\n",
- "\n",
- "# Correct categorizations stored as a list of lists to accommodate the possibility of multiple correct categorizations per email\n",
- "ANSWERS = [\n",
- " [\"B\"],\n",
- " [\"A\",\"D\"],\n",
- " [\"C\"],\n",
- " [\"D\"]\n",
- "]\n",
- "\n",
- "# Iterate through list of emails\n",
- "for i,email in enumerate(EMAILS):\n",
- " \n",
- " # Substitute the email text into the email placeholder variable\n",
- " formatted_prompt = PROMPT.format(email=email)\n",
- " \n",
- " # Get Claude's response\n",
- " response = get_completion(formatted_prompt, prefill=PREFILL)\n",
- "\n",
- " # Grade Claude's response\n",
- " grade = any([bool(re.search(ans, response[-1])) for ans in ANSWERS[i]])\n",
- " \n",
- " # Print Claude's response\n",
- " print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- " print(\"USER TURN\")\n",
- " print(formatted_prompt)\n",
- " print(\"\\nASSISTANT TURN\")\n",
- " print(PREFILL)\n",
- " print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- " print(response)\n",
- " print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- " print(\"This exercise has been correctly solved:\", grade, \"\\n\\n\\n\\n\\n\\n\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_7_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Still stuck? Run the cell below for an example solution."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_7_1_solution)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Will Santa bring me presents on Christmas?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"Please complete the conversation by writing the next line, speaking as \"A\".\n",
- "Q: Is the tooth fairy real?\n",
- "A: Of course, sweetie. Wrap up your tooth and put it under your pillow tonight. There might be something waiting for you in the morning.\n",
- "Q: Will Santa bring me presents on Christmas?\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt template with a placeholder for the variable content\n",
- "PROMPT = \"\"\"Silvermist Hollow, a charming village, was home to an extraordinary group of individuals.\n",
- "Among them was Dr. Liam Patel, a neurosurgeon who revolutionized surgical techniques at the regional medical center.\n",
- "Olivia Chen was an innovative architect who transformed the village's landscape with her sustainable and breathtaking designs.\n",
- "The local theater was graced by the enchanting symphonies of Ethan Kovacs, a professionally-trained musician and composer.\n",
- "Isabella Torres, a self-taught chef with a passion for locally sourced ingredients, created a culinary sensation with her farm-to-table restaurant, which became a must-visit destination for food lovers.\n",
- "These remarkable individuals, each with their distinct talents, contributed to the vibrant tapestry of life in Silvermist Hollow.\n",
- "\n",
- "1. Dr. Liam Patel [NEUROSURGEON]\n",
- "2. Olivia Chen [ARCHITECT]\n",
- "3. Ethan Kovacs [MISICIAN AND COMPOSER]\n",
- "4. Isabella Torres [CHEF]\n",
- "\n",
- "\n",
- "At the heart of the town, Chef Oliver Hamilton has transformed the culinary scene with his farm-to-table restaurant, Green Plate. Oliver's dedication to sourcing local, organic ingredients has earned the establishment rave reviews from food critics and locals alike.\n",
- "Just down the street, you'll find the Riverside Grove Library, where head librarian Elizabeth Chen has worked diligently to create a welcoming and inclusive space for all. Her efforts to expand the library's offerings and establish reading programs for children have had a significant impact on the town's literacy rates.\n",
- "As you stroll through the charming town square, you'll be captivated by the beautiful murals adorning the walls. These masterpieces are the work of renowned artist, Isabella Torres, whose talent for capturing the essence of Riverside Grove has brought the town to life.\n",
- "Riverside Grove's athletic achievements are also worth noting, thanks to former Olympic swimmer-turned-coach, Marcus Jenkins. Marcus has used his experience and passion to train the town's youth, leading the Riverside Grove Swim Team to several regional championships.\n",
- "\n",
- "1. Oliver Hamilton [CHEF]\n",
- "2. Elizabeth Chen [LIBRARIAN]\n",
- "3. Isabella Torres [ARTIST]\n",
- "4. Marcus Jenkins [COACH]\n",
- "\n",
- "\n",
- "Oak Valley, a charming small town, is home to a remarkable trio of individuals whose skills and dedication have left a lasting impact on the community.\n",
- "At the town's bustling farmer's market, you'll find Laura Simmons, a passionate organic farmer known for her delicious and sustainably grown produce. Her dedication to promoting healthy eating has inspired the town to embrace a more eco-conscious lifestyle.\n",
- "In Oak Valley's community center, Kevin Alvarez, a skilled dance instructor, has brought the joy of movement to people of all ages. His inclusive dance classes have fostered a sense of unity and self-expression among residents, enriching the local arts scene.\n",
- "Lastly, Rachel O'Connor, a tireless volunteer, dedicates her time to various charitable initiatives. Her commitment to improving the lives of others has been instrumental in creating a strong sense of community within Oak Valley.\n",
- "Through their unique talents and unwavering dedication, Laura, Kevin, and Rachel have woven themselves into the fabric of Oak Valley, helping to create a vibrant and thriving small town.\"\"\"\n",
- "\n",
- "# Prefill for Claude's response\n",
- "PREFILL = \"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN:\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN:\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/08_Avoiding_Hallucinations.ipynb b/AmazonBedrock/anthropic/08_Avoiding_Hallucinations.ipynb
deleted file mode 100755
index 8bf0e68..0000000
--- a/AmazonBedrock/anthropic/08_Avoiding_Hallucinations.ipynb
+++ /dev/null
@@ -1,707 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 8: Avoiding Hallucinations\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "Some bad news: **Claude sometimes \"hallucinates\" and makes claims that are untrue or unjustified**. The good news: there are techniques you can use to minimize hallucinations.\n",
- "\t\t\t\t\n",
- "Below, we'll go over a few of these techniques, namely:\n",
- "- Giving Claude the option to say it doesn't know the answer to a question\n",
- "- Asking Claude to find evidence before answering\n",
- "\n",
- "However, **there are many methods to avoid hallucinations**, including many of the techniques you've already learned in this course. If Claude hallucinates, experiment with multiple techniques to get Claude to increase its accuracy."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "Here is a question about general factual knowledge in answer to which **Claude hallucinates several large hippos because it's trying to be as helpful as possible**."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the heaviest hippo of all time?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A solution we can try here is to \"**give Claude an out**\" — tell Claude that it's OK for it to decline to answer, or to only answer if it actually knows the answer with certainty."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the heaviest hippo of all time? Only answer if you know the answer with certainty.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In the prompt below, we give Claude a long document containing some \"distractor information\" that is almost but not quite relevant to the user's question. **Without prompting help, Claude falls for the distractor information** and gives an incorrect \"hallucinated\" answer as to the size of Matterport's subscriber base as of May 31, 2020.\n",
- "\n",
- "**Note:** As you'll learn later in the next chapter, **it's best practice to have the question at the bottom *after* any text or document**, but we put it at the top here to make the prompt easier to read. Feel free to double click on the prompt cell to get the full prompt text (it's very long!)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"What was Matterport's subscriber base on the precise date of May 31, 2020?\n",
- "Please read the below document. Then write a brief numerical answer inside tags.\n",
- "\n",
- "\n",
- "Matterport SEC filing 10-K 2023\n",
- "Item 1. Business\n",
- "Our Company\n",
- "Matterport is leading the digitization and datafication of the built world. We believe the digital transformation of the built world will fundamentally change the way people interact with buildings and the physical spaces around them.\n",
- "Since its founding in 2011, Matterport’s pioneering technology has set the standard for digitizing, accessing and managing buildings, spaces and places online. Our platform’s innovative software, spatial data-driven data science, and 3D capture technology have broken down the barriers that have kept the largest asset class in the world, buildings and physical spaces, offline and underutilized for many years. We believe the digitization and datafication of the built world will continue to unlock significant operational efficiencies and property values, and that Matterport is the platform to lead this enormous global transformation.\n",
- "The world is rapidly moving from offline to online. Digital transformation has made a powerful and lasting impact across every business and industry today. According to International Data Corporation, or IDC, over $6.8 trillion of direct investments will be made on digital transformation from 2020 to 2023, the global digital transformation spending is forecasted to reach $3.4 trillion in 2026 with a five-year compound annual growth rate (“CAGR”) of 16.3%, and digital twin investments are expected to have a five-year CAGR of 35.2%. With this secular shift, there is also growing demand for the built world to transition from physical to digital. Nevertheless, the vast majority of buildings and spaces remain offline and undigitized. The global building stock, estimated by Savills to be $327 trillion in total property value as of 2021, remains largely offline today, and we estimate that less than 0.1% is penetrated by digital transformation.\n",
- "Matterport was among the first to recognize the increasing need for digitization of the built world and the power of spatial data, the unique details underlying buildings and spaces, in facilitating the understanding of buildings and spaces. In the past, technology advanced physical road maps to the data-rich, digital maps and location services we all rely on today. Matterport now digitizes buildings, creating a data-rich environment to vastly increase our understanding and the full potential of each and every space we capture. Just as we can instantly, at the touch of a button, learn the fastest route from one city to another or locate the nearest coffee shops, Matterport’s spatial data for buildings unlocks a rich set of insights and learnings about properties and spaces worldwide. In addition, just as the geo-spatial mapping platforms of today have opened their mapping data to industry to create new business models such as ridesharing, e-commerce, food delivery marketplaces, and even short-term rental and home sharing, open access to Matterport’s structured spatial data is enabling new opportunities and business models for hospitality, facilities management, insurance, construction, real estate and retail, among others.\n",
- "We believe the total addressable market opportunity for digitizing the built world is over $240 billion, and could be as high as $1 trillion as the market matures at scale. This is based on our analysis, modeling and understanding of the global building stock of over 4 billion properties and 20 billion spaces in the world today. With the help of artificial intelligence (“AI”), machine learning (“ML”) and deep learning (“DL”) technologies, we believe that, with the additional monetization opportunities from powerful spatial data-driven property insights and analytics, the total addressable market for the digitization and datafication of the built world will reach more than $1 trillion.\n",
- "\n",
- "Our spatial data platform and capture of digital twins deliver value across a diverse set of industries and use cases. Large retailers can manage thousands of store locations remotely, real estate agencies can provide virtual open houses for hundreds of properties and thousands of visitors at the same time, property developers can monitor the entirety of the construction process with greater detail and speed, and insurance companies can more precisely document and evaluate claims and underwriting assessments with efficiency and precision. Matterport delivers the critical digital experience, tools and information that matter to our subscribers about properties of virtually any size, shape, and location worldwide.\n",
- "For nearly a decade, we have been growing our spatial data platform and expanding our capabilities in order to create the most detailed, accurate, and data-rich digital twins available. Moreover, our 3D reconstruction process is fully automated, allowing our solution to scale with equal precision to millions of buildings and spaces of any type, shape, and size in the world. The universal applicability of our service provides Matterport significant scale and reach across diverse verticals and any geography. As of December 31, 2022, our subscriber base had grown approximately 39% to over 701,000 subscribers from 503,000 subscribers as of December 31, 2021, with our digital twins reaching more than 170 countries. We have digitized more than 28 billion square feet of space across multiple industries, representing significant scale and growth over the rest of the market.\n",
- "\n",
- "As we continue to transform buildings into data worldwide, we are extending our spatial data platform to further transform property planning, development, management and intelligence for our subscribers across industries to become the de facto building and business intelligence engine for the built world. We believe the demand for spatial data and resulting insights for enterprises, businesses and institutions across industries, including real estate, architecture, engineering and construction (“AEC”), retail, insurance and government, will continue to grow rapidly.\n",
- "We believe digitization and datafication represent a tremendous greenfield opportunity for growth across this massive category and asset class. From the early stages of design and development to marketing, operations, insurance and building repair and maintenance, our platform’s software and technology provide subscribers critical tools and insights to drive cost savings, increase revenues and optimally manage their buildings and spaces. We believe that hundreds of billions of dollars in unrealized utilization and operating efficiencies in the built world can be unlocked through the power of our spatial data platform. Our platform and data solutions have universal applicability across industries and building categories, giving Matterport a significant advantage as we can address the entirety of this large market opportunity and increase the value of what we believe to be the largest asset class in the world.\n",
- "With a demonstrated track record of delivering value to our subscribers, our offerings include software subscription, data licensing, services and product hardware. As of December 31, 2022, our subscriber base included over 24% of Fortune 1000 companies, with less than 10% of our total revenue generated from our top 10 subscribers. We expect more than 80% of our revenue to come from our software subscription and data license solutions by 2025. Our innovative 3D capture products, the Pro2 and Pro3 Cameras, have played an integral part in shaping the 3D building and property visualization ecosystem. The Pro2 and Pro3 Cameras have driven adoption of our solutions and have generated the unique high-quality and scaled data set that has enabled Cortex, our proprietary AI software engine, to become the pioneering engine for digital twin creation. With this data advantage initially spurred by the Pro2 Camera, we have developed a capture device agnostic platform that scales and can generate new building and property insights for our subscribers across industries and geographies.\n",
- "We have recently experienced rapid growth. Our subscribers have grown approximately 49-fold from December 31, 2018 to December 31, 2022. Our revenue increased by approximately 22% to $136.1 million for the year ended December 31, 2022, from approximately $111.2 million for the year ended December 31, 2021. Our gross profit decreased by $8.1 million or 14%, to $51.8 million for the year ended December 31, 2022, from $60.0 million for the year ended December 31, 2021, primarily attributable to certain disruptive and incremental costs due to the global supply chain constraints in fiscal year 2022. Our ability to retain and grow the subscription revenue generated by our existing subscribers is an important measure of the health of our business and our future growth prospects. We track our performance in this area by measuring our net dollar expansion rate from the same set of customers across comparable periods. Our net dollar expansion rate of 103% for the three months ended December 31, 2022 demonstrates the stickiness and growth potential of our platform.\n",
- "Our Industry and Market Opportunity\n",
- "Today, the vast majority of buildings and spaces remain undigitized. We estimate our current serviceable addressable market includes approximately 1.3 billion spaces worldwide, primarily from the real estate and travel and hospitality sectors. With approximately 9.2 million spaces under management as of December 31, 2022, we are continuing to penetrate the global building stock and expand our footprint across various end markets, including residential and commercial real estate, facilities management, retail, AEC, insurance and repair, and travel and hospitality. We estimate our total addressable market to be more than 4 billion buildings and 20 billion spaces globally, yielding a more than $240 billion market opportunity. We believe that as Matterport’s unique spatial data library and property data services continue to grow, this opportunity could increase to more than $1 trillion based on the size of the building stock and the untapped value creation available to buildings worldwide. The constraints created by the COVID-19 pandemic have only reinforced and accelerated the importance of our scaled 3D capture solution that we have developed for diverse industries and markets over the past decade.\n",
- "\n",
- "Our Spatial Data Platform\n",
- "Overview\n",
- "Our technology platform uses spatial data collected from a wide variety of digital capture devices to transform physical buildings and spaces into dimensionally accurate, photorealistic digital twins that provide our subscribers access to previously unavailable building information and insights.\n",
- "As a first mover in this massive market for nearly a decade, we have developed and scaled our industry-leading 3D reconstruction technology powered by Cortex, our proprietary AI-driven software engine that uses machine learning to recreate a photorealistic, 3D virtual representation of an entire building structure, including contents, equipment and furnishings. The finished product is a detailed and dynamic replication of the physical space that can be explored, analyzed and customized from a web browser on any device, including smartphones. The power to manage even large-scale commercial buildings is in the palm of each subscriber’s hands, made possible by our advanced technology and breakthrough innovations across our entire spatial data technology stack.\n",
- "Key elements of our spatial data platform include:\n",
- "•Bringing offline buildings online. Traditionally, our customers needed to conduct in-person site visits to understand and assess their buildings and spaces. While photographs and floor plans can be helpful, these forms of two-dimensional (“2D”) representation have limited information and tend to be static and rigid, and thus lack the interactive element critical to a holistic understanding of each building and space. With the AI-powered capabilities of Cortex, our proprietary AI software, representation of physical objects is no longer confined to static 2D images and physical visits can be eliminated. Cortex helps to move the buildings and spaces from offline to online and makes them accessible to our customers in real-time and on demand from anywhere. After subscribers scan their buildings, our visualization algorithms accurately infer spatial positions and depths from flat, 2D imagery captured through the scans and transform them into high- fidelity and precise digital twin models. This creates a fully automated image processing pipeline to ensure that each digital twin is of professional grade image quality.\n",
- "•Driven by spatial data. We are a data-driven company. Each incremental capture of a space grows the richness and depth of our spatial data library. Spatial data represents the unique and idiosyncratic details that underlie and compose the buildings and spaces in the human- made environment. Cortex uses the breadth of the billions of data points we have accumulated over the years to improve the 3D accuracy of our digital twins. We help our subscribers pinpoint the height, location and other characteristics of objects in their digital twin. Our sophisticated algorithms also deliver significant commercial value to our subscribers by generating data-based insights that allow them to confidently make assessments and decisions about their properties. For instance, property developers can assess the amount of natural heat and daylight coming from specific windows, retailers can ensure each store layout is up to the same level of code and brand requirements, and factories can insure machinery layouts meet specifications and location guidelines. With approximately 9.2 million spaces under management as of December 31, 2022, our spatial data library is the clearinghouse for information about the built world.\n",
- "•Powered by AI and ML. Artificial intelligence and machine learning technologies effectively utilize spatial data to create a robust virtual experience that is dynamic, realistic, interactive, informative and permits multiple viewing angles. AI and ML also make costly cameras unnecessary for everyday scans—subscribers can now scan their spaces by simply tapping a button on their smartphones. As a result, Matterport is a device agnostic platform, helping us more rapidly scale and drive towards our mission of digitizing and indexing the built world.\n",
- "Our value proposition to subscribers is designed to serve the entirety of the digital building lifecycle, from design and build to maintenance and operations, promotion, sale, lease, insure, repair, restore, secure and finance. As a result, we believe we are uniquely positioned to grow our revenue with our subscribers as we help them to discover opportunities to drive short- and long-term return on investment by taking their buildings and spaces from offline to online across their portfolios of properties.\n",
- "Ubiquitous Capture\n",
- "Matterport has become the standard for 3D space capture. Our technology platform empowers subscribers worldwide to quickly, easily and accurately digitize, customize and manage interactive and dimensionally accurate digital twins of their buildings and spaces.\n",
- "The Matterport platform is designed to work with a wide range of LiDAR, spherical, 3D and 360 cameras, as well as smartphones, to suit the capture needs of all of our subscribers. This provides the flexibility to capture a space of any size, scale, and complexity, at anytime and anywhere.\n",
- "•Matterport Pro3 is our newest 3D camera that scans properties faster than earlier versions to help accelerate project completion. Pro3 provides the highest accuracy scans of both indoor and outdoor spaces and is designed for speed, fidelity, versatility and accuracy. Capturing 3D data up to 100 meters away at less than 20 seconds per sweep, Pro3’s ultra-fast, high-precision LiDAR sensor can run for hours and takes millions of measurements in any conditions.\n",
- "•Matterport Pro2 is our proprietary 3D camera that has been used to capture millions of spaces around the world with a high degree of fidelity, precision, speed and simplicity. Capable of capturing buildings more than 500,000 square feet in size, it has become the camera of choice for many residential, commercial, industrial and large-scale properties.\n",
- "•360 Cameras. Matterport supports a selection of 360 cameras available in the market. These affordable, pocket sized devices deliver precision captures with high fidelity and are appropriate for capturing smaller homes, condos, short-term rentals, apartments, and more. The spherical lens image capture technology of these devices gives Cortex robust, detailed image data to transform panoramas into our industry-leading digital twins.\n",
- "•LEICA BLK360. Through our partnership with Leica, our 3D reconstruction technology and our AI powered software engine, Cortex, transform this powerful LiDAR camera into an ultra-precise capture device for creating Matterport digital twins. It is the solution of choice for AEC professionals when exacting precision is required.\n",
- "•Smartphone Capture. Our capture apps are commercially available for both iOS and Android. Matterport’s smartphone capture solution has democratized 3D capture, making it easy and accessible for anyone to digitize buildings and spaces with a recent iPhone device since the initial introduction of Matterport for iPhone in May 2020. In April 2021, we announced the official release of the Android Capture app, giving Android users the ability to quickly and easily capture buildings and spaces in immersive 3D. In February 2022, we launched Matterport Axis, a motorized mount that holds a smartphone and can be used with the Matterport Capture app to capture 3D digital twins of any physical space with increased speed, precision, and consistency.\n",
- "Cortex and 3D Reconstruction (the Matterport Digital Twin)\n",
- "With a spatial data library, as of December 31, 2022, of approximately 9.2 million spaces under management, representing approximately 28 billion captured square feet of space, we use our advanced ML and DL technologies to algorithmically transform the spatial data we capture into an accurate 3D digital reproduction of any physical space. This intelligent, automated 3D reconstruction is made possible by Cortex, our AI-powered software engine that includes a deep learning neural network that uses our spatial data library to understand how a building or space is divided into floors and rooms, where the doorways and openings are located, and what types of rooms are present, such that those forms are compiled and aligned with dimensional accuracy into a dynamic, photorealistic digital twin. Other components of Cortex include AI-powered computer vision technologies to identify and classify the contents inside a building or space, and object recognition technologies to identify and segment everything from furnishings and equipment to doors, windows, light fixtures, fire suppression sprinklers and fire escapes. Our highly scalable artificial intelligence platform enables our subscribers to tap into powerful, enhanced building data and insights at the click of a button.\n",
- "\n",
- "The Science Behind the Matterport Digital Twin: Cortex AI Highlights\n",
- "Matterport Runs on Cortex\n",
- "Cortex is our AI-powered software engine that includes a precision deep learning neural network to create digital twins of any building or space. Developed using our proprietary spatial data captured with our Pro2 and Pro3 cameras, Cortex delivers a high degree of precision and accuracy while enabling 3D capture using everyday devices.\n",
- "Generic neural networks struggle with 3D reconstruction of the real world. Matterport-optimized networks deliver more accurate and robust results. More than just raw training data, Matterport’s datasets allow us to develop new neural network architectures and evaluate them against user behavior and real-world data in millions of situations.\n",
- "•Deep learning: Connecting and optimizing the detailed neural network data architecture of each space is key to creating robust, highly accurate 3D digital twins. Cortex evaluates and optimizes each 3D model against Matterport’s rich spatial data aggregated from millions of buildings and spaces and the human annotations of those data provided by tens of thousands of subscribers worldwide. Cortex’s evaluative abilities and its data-driven optimization of 3D reconstruction yield consistent, high-precision results across a wide array of building configurations, spaces and environments.\n",
- "•Dynamic 3D reconstruction: Creating precise 3D spatial data at scale from 2D visuals and static images requires a combination of photorealistic, detailed data from multiple viewpoints and millions of spaces that train and optimize Cortex’s neural network and learning capabilities for improved 3D reconstruction of any space. Cortex’s capabilities combined with real-time spatial alignment algorithms in our 3D capture technology create an intuitive “preview” of any work in progress, allowing subscribers to work with their content interactively and in real-time.\n",
- "•Computer vision: Cortex enables a suite of powerful features to enhance the value of digital twins. These include automatic measurements for rooms or objects in a room, automatic 2D-from-3D high-definition photo gallery creation, auto face blurring for privacy protection, custom videos, walkthroughs, auto room labeling and object recognition.\n",
- "•Advanced image processing: Matterport’s computational photography algorithms create a fully automated image processing pipeline to help ensure that each digital twin is of professional grade image quality. Our patented technology makes 3D capture as simple as pressing a single button. Matterport’s software and technology manage the remaining steps, including white balance and camera-specific color correction, high dynamic range tone mapping, de-noising, haze removal, sharpening, saturation and other adjustments to improve image quality.\n",
- "Spatial Data and AI-Powered Insights\n",
- "Every Matterport digital twin contains extensive information about a building, room or physical space. The data uses our AI-powered Cortex engine. In addition to the Matterport digital twin itself, our spatial data consists of precision building geometry and structural detail, building contents, fixtures and condition, along with high-definition imagery and photorealistic detail from many vantage points in a space. Cortex employs a technique we call deep spatial indexing. Deep spatial indexing uses artificial intelligence, computer vision and deep learning to identify and convey important details about each space, its structure and its contents with precision and fidelity. We have created a robust spatial data standard that enables Matterport subscribers to harness an interoperable digital system of record for any building.\n",
- "In addition to creating a highly interactive digital experience for subscribers through the construction of digital twins, we ask ourselves two questions for every subscriber: (1) what is important about their building or physical space and (2) what learnings and insights can we deliver for this space? Our AI-powered Cortex engine helps us answer these questions using our spatial data library to provide aggregated property trends and operational and valuation insights. Moreover, as the Matterport platform ecosystem continues to expand, our subscribers, partners and other third-party developers can bring their own tools to further the breadth and depth of insights they can harvest from our rich spatial data layer.\n",
- "Extensible Platform Ecosystem\n",
- "Matterport offers the largest and most accurate library of spatial data in the world, with, as of December 31, 2022, approximately 9.2 million spaces under management and approximately 28 billion captured square feet. The versatility of our spatial data platform and extensive enterprise software development kit and application programming interfaces (“APIs”) has allowed us to develop a robust global ecosystem of channels and partners that extend the Matterport value proposition by geography and vertical market. We intend to continue to deploy a broad set of workflow integrations with our partners and their subscribers to promote an integrated Matterport solution across our target markets. We are also developing a third-party software marketplace to extend the power of our spatial data platform with easy-to-deploy and easy-to-access Matterport software add-ons. The marketplace enables developers to build new applications and spatial data mining tools, enhance the Matterport 3D experience, and create new productivity and property management tools that supplement our core offerings. These value-added capabilities created by third-party developers enable a scalable new revenue stream, with Matterport sharing the subscription and services revenue from each add-on that is deployed to subscribers through the online marketplace. The network effects of our platform ecosystem contributes to the growth of our business, and we believe that it will continue to bolster future growth by enhancing subscriber stickiness and user engagement.\n",
- "Examples of Matterport add-ons and extensions include:\n",
- "•Add-ons: Encircle (easy-to-use field documentation tools for faster claims processing); WP Matterport Shortcode (free Wordpress plugin that allows Matterport to be embedded quickly and easily with a Matterport shortcode), WP3D Models (WordPress + Matterport integration plugin); Rela (all-in-one marketing solution for listings); CAPTUR3D (all-in-one Content Management System that extends value to Matterport digital twins); Private Model Emded (feature that allows enterprises to privately share digital twins with a large group of employees on the corporate network without requiring additional user licenses); Views (new workgroup collaboration framework to enable groups and large organizations to create separate, permissions-based workflows to manage different tasks with different teams); and Guided Tours and Tags (tool to elevate the visitor experience by creating directed virtual tours of any commercial or residential space tailored to the interests of their visitors). We unveiled our private beta integration with Amazon Web Services (AWS) IoT TwinMaker to enable enterprise customers to seamlessly connect IoT data into visually immersive and dimensionally accurate Matterport digital twin.\n",
- "•Services: Matterport ADA Compliant Digital Twin (solution to provide American Disability Act compliant digital twins) and Enterprise Cloud Software Platform (reimagined cloud software platform for the enterprise that creates, publishes, and manages digital twins of buildings and spaces of any size of shape, indoors or outdoors).\n",
- "Our Competitive Strengths\n",
- "We believe that we have a number of competitive strengths that will enable our market leadership to grow. Our competitive strengths include:\n",
- "•Breadth and depth of the Matterport platform. Our core strength is our all-in-one spatial data platform with broad reach across diverse verticals and geographies such as capture to processing to industries without customization. With the ability to integrate seamlessly with various enterprise systems, our platform delivers value across the property lifecycle for diverse end markets, including real estate, AEC, travel and hospitality, repair and insurance, and industrial and facilities. As of December 31, 2022, our global reach extended to subscribers in more than 170 countries, including over 24% of Fortune 1000 companies.\n",
- "•Market leadership and first-mover advantage. Matterport defined the category of digitizing and datafying the built world almost a decade ago, and we have become the global leader in the category. As of December 31, 2022, we had over 701,000 subscribers on our platform and approximately 9.2 million spaces under management. Our leadership is primarily driven by the fact that we were the first mover in digital twin creation. As a result of our first mover advantage, we have amassed a deep and rich library of spatial data that continues to compound and enhance our leadership position.\n",
- "•Significant network effect. With each new capture and piece of data added to our platform, the richness of our dataset and the depth of insights from our spaces under management grow. In addition, the combination of our ability to turn data into insights with incremental data from new data captures by our subscribers enables Matterport to develop features for subscribers to our platform. We were a first mover in building a spatial data library for the built world, and our leadership in gathering and deriving insights from data continues to compound and the relevance of those insights attracts more new subscribers.\n",
- "•Massive spatial data library as the raw material for valuable property insights. The scale of our spatial data library is a significant advantage in deriving insights for our subscribers. Our spatial data library serves as vital ground truth for Cortex, enabling Matterport to create powerful 3D digital twins using a wide range of camera technology, including low-cost digital and smartphone cameras. As of December 31, 2022, our data came from approximately 9.2 million spaces under management and approximately 28 billion captured square feet. As a result, we have taken property insights and analytics to new levels, benefiting subscribers across various industries. For example, facilities managers significantly reduce the time needed to create building layouts, leading to a significant decrease in the cost of site surveying and as-built modeling. AEC subscribers use the analytics of each as-built space to streamline documentation and collaborate with ease.\n",
- "•Global reach and scale. We are focused on continuing to expand our AI-powered spatial data platform worldwide. We have a significant presence in North America, Europe and Asia, with leadership teams and a go-to-market infrastructure in each of these regions. We have offices in London, Singapore and several across the United States, and we are accelerating our international expansion. As of December 31, 2022, we had over 701,000 subscribers in more than 170 countries. We believe that the geography-agnostic nature of our spatial data platform is a significant advantage as we continue to grow internationally.\n",
- "•Broad patent portfolio supporting 10 years of R&D and innovation. As of December 31, 2022, we had 54 issued and 37 pending patent applications. Our success is based on almost 10 years of focus on innovation. Innovation has been at the center of Matterport, and we will continue to prioritize our investments in R&D to further our market leading position.\n",
- "•Superior capture technology. Matterport’s capture technology platform is a software framework that enables support for a wide variety of capture devices required to create a Matterport digital twin of a building or space.\n",
- "This includes support for LiDAR cameras, 360 cameras, smartphones, Matterport Axis and the Matterport Pro2 and Pro3 cameras. The Pro2 camera was foundational to our spatial data advantage, and we have expanded that advantage with an array of Matterport-enabled third-party capture devices. In August 2022, we launched and began shipment of our Pro3 Camera along with major updates to our industry-leading digital twin cloud platform. The Matterport Pro3 Camera is an advanced 3D capture device, which includes faster boot time, swappable batteries, and a lighter design. The Pro3 camera can perform both indoors and outdoors and is designed for speed, fidelity, versatility and accuracy. Along with our Pro2 Camera, we expect that future sales of our Pro3 Camera will continue to drive increased adoption of our solutions. Matterport is democratizing the 3D capture experience, making high-fidelity and high-accuracy 3D digital twins readily available for any building type and any subscriber need in the property life cycle. While there are other 3D capture solution providers, very few can produce true, dimensionally accurate 3D results, and fewer still can automatically create a final product in photorealistic 3D, and at global scale. This expansive capture technology offering would not be possible without our rich spatial data library available to train the AI-powered Cortex engine to automatically generate accurate digital twins from photos captured with a smartphone or 360 camera.\n",
- "\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "How do we fix this? Well, a great way to reduce hallucinations on long documents is to **make Claude gather evidence first.** \n",
- "\n",
- "In this case, we **tell Claude to first extract relevant quotes, then base its answer on those quotes**. Telling Claude to do so here makes it correctly notice that the quote does not answer the question."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"What was Matterport's subscriber base on the precise date of May 31, 2020?\n",
- "Please read the below document. Then, in tags, pull the most relevant quote from the document and consider whether it answers the user's question or whether it lacks sufficient detail. Then write a brief numerical answer in tags.\n",
- "\n",
- "\n",
- "Matterport SEC filing 10-K 2023\n",
- "Item 1. Business\n",
- "Our Company\n",
- "Matterport is leading the digitization and datafication of the built world. We believe the digital transformation of the built world will fundamentally change the way people interact with buildings and the physical spaces around them.\n",
- "Since its founding in 2011, Matterport’s pioneering technology has set the standard for digitizing, accessing and managing buildings, spaces and places online. Our platform’s innovative software, spatial data-driven data science, and 3D capture technology have broken down the barriers that have kept the largest asset class in the world, buildings and physical spaces, offline and underutilized for many years. We believe the digitization and datafication of the built world will continue to unlock significant operational efficiencies and property values, and that Matterport is the platform to lead this enormous global transformation.\n",
- "The world is rapidly moving from offline to online. Digital transformation has made a powerful and lasting impact across every business and industry today. According to International Data Corporation, or IDC, over $6.8 trillion of direct investments will be made on digital transformation from 2020 to 2023, the global digital transformation spending is forecasted to reach $3.4 trillion in 2026 with a five-year compound annual growth rate (“CAGR”) of 16.3%, and digital twin investments are expected to have a five-year CAGR of 35.2%. With this secular shift, there is also growing demand for the built world to transition from physical to digital. Nevertheless, the vast majority of buildings and spaces remain offline and undigitized. The global building stock, estimated by Savills to be $327 trillion in total property value as of 2021, remains largely offline today, and we estimate that less than 0.1% is penetrated by digital transformation.\n",
- "Matterport was among the first to recognize the increasing need for digitization of the built world and the power of spatial data, the unique details underlying buildings and spaces, in facilitating the understanding of buildings and spaces. In the past, technology advanced physical road maps to the data-rich, digital maps and location services we all rely on today. Matterport now digitizes buildings, creating a data-rich environment to vastly increase our understanding and the full potential of each and every space we capture. Just as we can instantly, at the touch of a button, learn the fastest route from one city to another or locate the nearest coffee shops, Matterport’s spatial data for buildings unlocks a rich set of insights and learnings about properties and spaces worldwide. In addition, just as the geo-spatial mapping platforms of today have opened their mapping data to industry to create new business models such as ridesharing, e-commerce, food delivery marketplaces, and even short-term rental and home sharing, open access to Matterport’s structured spatial data is enabling new opportunities and business models for hospitality, facilities management, insurance, construction, real estate and retail, among others.\n",
- "We believe the total addressable market opportunity for digitizing the built world is over $240 billion, and could be as high as $1 trillion as the market matures at scale. This is based on our analysis, modeling and understanding of the global building stock of over 4 billion properties and 20 billion spaces in the world today. With the help of artificial intelligence (“AI”), machine learning (“ML”) and deep learning (“DL”) technologies, we believe that, with the additional monetization opportunities from powerful spatial data-driven property insights and analytics, the total addressable market for the digitization and datafication of the built world will reach more than $1 trillion.\n",
- "\n",
- "Our spatial data platform and capture of digital twins deliver value across a diverse set of industries and use cases. Large retailers can manage thousands of store locations remotely, real estate agencies can provide virtual open houses for hundreds of properties and thousands of visitors at the same time, property developers can monitor the entirety of the construction process with greater detail and speed, and insurance companies can more precisely document and evaluate claims and underwriting assessments with efficiency and precision. Matterport delivers the critical digital experience, tools and information that matter to our subscribers about properties of virtually any size, shape, and location worldwide.\n",
- "For nearly a decade, we have been growing our spatial data platform and expanding our capabilities in order to create the most detailed, accurate, and data-rich digital twins available. Moreover, our 3D reconstruction process is fully automated, allowing our solution to scale with equal precision to millions of buildings and spaces of any type, shape, and size in the world. The universal applicability of our service provides Matterport significant scale and reach across diverse verticals and any geography. As of December 31, 2022, our subscriber base had grown approximately 39% to over 701,000 subscribers from 503,000 subscribers as of December 31, 2021, with our digital twins reaching more than 170 countries. We have digitized more than 28 billion square feet of space across multiple industries, representing significant scale and growth over the rest of the market.\n",
- "\n",
- "As we continue to transform buildings into data worldwide, we are extending our spatial data platform to further transform property planning, development, management and intelligence for our subscribers across industries to become the de facto building and business intelligence engine for the built world. We believe the demand for spatial data and resulting insights for enterprises, businesses and institutions across industries, including real estate, architecture, engineering and construction (“AEC”), retail, insurance and government, will continue to grow rapidly.\n",
- "We believe digitization and datafication represent a tremendous greenfield opportunity for growth across this massive category and asset class. From the early stages of design and development to marketing, operations, insurance and building repair and maintenance, our platform’s software and technology provide subscribers critical tools and insights to drive cost savings, increase revenues and optimally manage their buildings and spaces. We believe that hundreds of billions of dollars in unrealized utilization and operating efficiencies in the built world can be unlocked through the power of our spatial data platform. Our platform and data solutions have universal applicability across industries and building categories, giving Matterport a significant advantage as we can address the entirety of this large market opportunity and increase the value of what we believe to be the largest asset class in the world.\n",
- "With a demonstrated track record of delivering value to our subscribers, our offerings include software subscription, data licensing, services and product hardware. As of December 31, 2022, our subscriber base included over 24% of Fortune 1000 companies, with less than 10% of our total revenue generated from our top 10 subscribers. We expect more than 80% of our revenue to come from our software subscription and data license solutions by 2025. Our innovative 3D capture products, the Pro2 and Pro3 Cameras, have played an integral part in shaping the 3D building and property visualization ecosystem. The Pro2 and Pro3 Cameras have driven adoption of our solutions and have generated the unique high-quality and scaled data set that has enabled Cortex, our proprietary AI software engine, to become the pioneering engine for digital twin creation. With this data advantage initially spurred by the Pro2 Camera, we have developed a capture device agnostic platform that scales and can generate new building and property insights for our subscribers across industries and geographies.\n",
- "We have recently experienced rapid growth. Our subscribers have grown approximately 49-fold from December 31, 2018 to December 31, 2022. Our revenue increased by approximately 22% to $136.1 million for the year ended December 31, 2022, from approximately $111.2 million for the year ended December 31, 2021. Our gross profit decreased by $8.1 million or 14%, to $51.8 million for the year ended December 31, 2022, from $60.0 million for the year ended December 31, 2021, primarily attributable to certain disruptive and incremental costs due to the global supply chain constraints in fiscal year 2022. Our ability to retain and grow the subscription revenue generated by our existing subscribers is an important measure of the health of our business and our future growth prospects. We track our performance in this area by measuring our net dollar expansion rate from the same set of customers across comparable periods. Our net dollar expansion rate of 103% for the three months ended December 31, 2022 demonstrates the stickiness and growth potential of our platform.\n",
- "Our Industry and Market Opportunity\n",
- "Today, the vast majority of buildings and spaces remain undigitized. We estimate our current serviceable addressable market includes approximately 1.3 billion spaces worldwide, primarily from the real estate and travel and hospitality sectors. With approximately 9.2 million spaces under management as of December 31, 2022, we are continuing to penetrate the global building stock and expand our footprint across various end markets, including residential and commercial real estate, facilities management, retail, AEC, insurance and repair, and travel and hospitality. We estimate our total addressable market to be more than 4 billion buildings and 20 billion spaces globally, yielding a more than $240 billion market opportunity. We believe that as Matterport’s unique spatial data library and property data services continue to grow, this opportunity could increase to more than $1 trillion based on the size of the building stock and the untapped value creation available to buildings worldwide. The constraints created by the COVID-19 pandemic have only reinforced and accelerated the importance of our scaled 3D capture solution that we have developed for diverse industries and markets over the past decade.\n",
- "\n",
- "Our Spatial Data Platform\n",
- "Overview\n",
- "Our technology platform uses spatial data collected from a wide variety of digital capture devices to transform physical buildings and spaces into dimensionally accurate, photorealistic digital twins that provide our subscribers access to previously unavailable building information and insights.\n",
- "As a first mover in this massive market for nearly a decade, we have developed and scaled our industry-leading 3D reconstruction technology powered by Cortex, our proprietary AI-driven software engine that uses machine learning to recreate a photorealistic, 3D virtual representation of an entire building structure, including contents, equipment and furnishings. The finished product is a detailed and dynamic replication of the physical space that can be explored, analyzed and customized from a web browser on any device, including smartphones. The power to manage even large-scale commercial buildings is in the palm of each subscriber’s hands, made possible by our advanced technology and breakthrough innovations across our entire spatial data technology stack.\n",
- "Key elements of our spatial data platform include:\n",
- "•Bringing offline buildings online. Traditionally, our customers needed to conduct in-person site visits to understand and assess their buildings and spaces. While photographs and floor plans can be helpful, these forms of two-dimensional (“2D”) representation have limited information and tend to be static and rigid, and thus lack the interactive element critical to a holistic understanding of each building and space. With the AI-powered capabilities of Cortex, our proprietary AI software, representation of physical objects is no longer confined to static 2D images and physical visits can be eliminated. Cortex helps to move the buildings and spaces from offline to online and makes them accessible to our customers in real-time and on demand from anywhere. After subscribers scan their buildings, our visualization algorithms accurately infer spatial positions and depths from flat, 2D imagery captured through the scans and transform them into high- fidelity and precise digital twin models. This creates a fully automated image processing pipeline to ensure that each digital twin is of professional grade image quality.\n",
- "•Driven by spatial data. We are a data-driven company. Each incremental capture of a space grows the richness and depth of our spatial data library. Spatial data represents the unique and idiosyncratic details that underlie and compose the buildings and spaces in the human- made environment. Cortex uses the breadth of the billions of data points we have accumulated over the years to improve the 3D accuracy of our digital twins. We help our subscribers pinpoint the height, location and other characteristics of objects in their digital twin. Our sophisticated algorithms also deliver significant commercial value to our subscribers by generating data-based insights that allow them to confidently make assessments and decisions about their properties. For instance, property developers can assess the amount of natural heat and daylight coming from specific windows, retailers can ensure each store layout is up to the same level of code and brand requirements, and factories can insure machinery layouts meet specifications and location guidelines. With approximately 9.2 million spaces under management as of December 31, 2022, our spatial data library is the clearinghouse for information about the built world.\n",
- "•Powered by AI and ML. Artificial intelligence and machine learning technologies effectively utilize spatial data to create a robust virtual experience that is dynamic, realistic, interactive, informative and permits multiple viewing angles. AI and ML also make costly cameras unnecessary for everyday scans—subscribers can now scan their spaces by simply tapping a button on their smartphones. As a result, Matterport is a device agnostic platform, helping us more rapidly scale and drive towards our mission of digitizing and indexing the built world.\n",
- "Our value proposition to subscribers is designed to serve the entirety of the digital building lifecycle, from design and build to maintenance and operations, promotion, sale, lease, insure, repair, restore, secure and finance. As a result, we believe we are uniquely positioned to grow our revenue with our subscribers as we help them to discover opportunities to drive short- and long-term return on investment by taking their buildings and spaces from offline to online across their portfolios of properties.\n",
- "Ubiquitous Capture\n",
- "Matterport has become the standard for 3D space capture. Our technology platform empowers subscribers worldwide to quickly, easily and accurately digitize, customize and manage interactive and dimensionally accurate digital twins of their buildings and spaces.\n",
- "The Matterport platform is designed to work with a wide range of LiDAR, spherical, 3D and 360 cameras, as well as smartphones, to suit the capture needs of all of our subscribers. This provides the flexibility to capture a space of any size, scale, and complexity, at anytime and anywhere.\n",
- "•Matterport Pro3 is our newest 3D camera that scans properties faster than earlier versions to help accelerate project completion. Pro3 provides the highest accuracy scans of both indoor and outdoor spaces and is designed for speed, fidelity, versatility and accuracy. Capturing 3D data up to 100 meters away at less than 20 seconds per sweep, Pro3’s ultra-fast, high-precision LiDAR sensor can run for hours and takes millions of measurements in any conditions.\n",
- "•Matterport Pro2 is our proprietary 3D camera that has been used to capture millions of spaces around the world with a high degree of fidelity, precision, speed and simplicity. Capable of capturing buildings more than 500,000 square feet in size, it has become the camera of choice for many residential, commercial, industrial and large-scale properties.\n",
- "•360 Cameras. Matterport supports a selection of 360 cameras available in the market. These affordable, pocket sized devices deliver precision captures with high fidelity and are appropriate for capturing smaller homes, condos, short-term rentals, apartments, and more. The spherical lens image capture technology of these devices gives Cortex robust, detailed image data to transform panoramas into our industry-leading digital twins.\n",
- "•LEICA BLK360. Through our partnership with Leica, our 3D reconstruction technology and our AI powered software engine, Cortex, transform this powerful LiDAR camera into an ultra-precise capture device for creating Matterport digital twins. It is the solution of choice for AEC professionals when exacting precision is required.\n",
- "•Smartphone Capture. Our capture apps are commercially available for both iOS and Android. Matterport’s smartphone capture solution has democratized 3D capture, making it easy and accessible for anyone to digitize buildings and spaces with a recent iPhone device since the initial introduction of Matterport for iPhone in May 2020. In April 2021, we announced the official release of the Android Capture app, giving Android users the ability to quickly and easily capture buildings and spaces in immersive 3D. In February 2022, we launched Matterport Axis, a motorized mount that holds a smartphone and can be used with the Matterport Capture app to capture 3D digital twins of any physical space with increased speed, precision, and consistency.\n",
- "Cortex and 3D Reconstruction (the Matterport Digital Twin)\n",
- "With a spatial data library, as of December 31, 2022, of approximately 9.2 million spaces under management, representing approximately 28 billion captured square feet of space, we use our advanced ML and DL technologies to algorithmically transform the spatial data we capture into an accurate 3D digital reproduction of any physical space. This intelligent, automated 3D reconstruction is made possible by Cortex, our AI-powered software engine that includes a deep learning neural network that uses our spatial data library to understand how a building or space is divided into floors and rooms, where the doorways and openings are located, and what types of rooms are present, such that those forms are compiled and aligned with dimensional accuracy into a dynamic, photorealistic digital twin. Other components of Cortex include AI-powered computer vision technologies to identify and classify the contents inside a building or space, and object recognition technologies to identify and segment everything from furnishings and equipment to doors, windows, light fixtures, fire suppression sprinklers and fire escapes. Our highly scalable artificial intelligence platform enables our subscribers to tap into powerful, enhanced building data and insights at the click of a button.\n",
- "\n",
- "The Science Behind the Matterport Digital Twin: Cortex AI Highlights\n",
- "Matterport Runs on Cortex\n",
- "Cortex is our AI-powered software engine that includes a precision deep learning neural network to create digital twins of any building or space. Developed using our proprietary spatial data captured with our Pro2 and Pro3 cameras, Cortex delivers a high degree of precision and accuracy while enabling 3D capture using everyday devices.\n",
- "Generic neural networks struggle with 3D reconstruction of the real world. Matterport-optimized networks deliver more accurate and robust results. More than just raw training data, Matterport’s datasets allow us to develop new neural network architectures and evaluate them against user behavior and real-world data in millions of situations.\n",
- "•Deep learning: Connecting and optimizing the detailed neural network data architecture of each space is key to creating robust, highly accurate 3D digital twins. Cortex evaluates and optimizes each 3D model against Matterport’s rich spatial data aggregated from millions of buildings and spaces and the human annotations of those data provided by tens of thousands of subscribers worldwide. Cortex’s evaluative abilities and its data-driven optimization of 3D reconstruction yield consistent, high-precision results across a wide array of building configurations, spaces and environments.\n",
- "•Dynamic 3D reconstruction: Creating precise 3D spatial data at scale from 2D visuals and static images requires a combination of photorealistic, detailed data from multiple viewpoints and millions of spaces that train and optimize Cortex’s neural network and learning capabilities for improved 3D reconstruction of any space. Cortex’s capabilities combined with real-time spatial alignment algorithms in our 3D capture technology create an intuitive “preview” of any work in progress, allowing subscribers to work with their content interactively and in real-time.\n",
- "•Computer vision: Cortex enables a suite of powerful features to enhance the value of digital twins. These include automatic measurements for rooms or objects in a room, automatic 2D-from-3D high-definition photo gallery creation, auto face blurring for privacy protection, custom videos, walkthroughs, auto room labeling and object recognition.\n",
- "•Advanced image processing: Matterport’s computational photography algorithms create a fully automated image processing pipeline to help ensure that each digital twin is of professional grade image quality. Our patented technology makes 3D capture as simple as pressing a single button. Matterport’s software and technology manage the remaining steps, including white balance and camera-specific color correction, high dynamic range tone mapping, de-noising, haze removal, sharpening, saturation and other adjustments to improve image quality.\n",
- "Spatial Data and AI-Powered Insights\n",
- "Every Matterport digital twin contains extensive information about a building, room or physical space. The data uses our AI-powered Cortex engine. In addition to the Matterport digital twin itself, our spatial data consists of precision building geometry and structural detail, building contents, fixtures and condition, along with high-definition imagery and photorealistic detail from many vantage points in a space. Cortex employs a technique we call deep spatial indexing. Deep spatial indexing uses artificial intelligence, computer vision and deep learning to identify and convey important details about each space, its structure and its contents with precision and fidelity. We have created a robust spatial data standard that enables Matterport subscribers to harness an interoperable digital system of record for any building.\n",
- "In addition to creating a highly interactive digital experience for subscribers through the construction of digital twins, we ask ourselves two questions for every subscriber: (1) what is important about their building or physical space and (2) what learnings and insights can we deliver for this space? Our AI-powered Cortex engine helps us answer these questions using our spatial data library to provide aggregated property trends and operational and valuation insights. Moreover, as the Matterport platform ecosystem continues to expand, our subscribers, partners and other third-party developers can bring their own tools to further the breadth and depth of insights they can harvest from our rich spatial data layer.\n",
- "Extensible Platform Ecosystem\n",
- "Matterport offers the largest and most accurate library of spatial data in the world, with, as of December 31, 2022, approximately 9.2 million spaces under management and approximately 28 billion captured square feet. The versatility of our spatial data platform and extensive enterprise software development kit and application programming interfaces (“APIs”) has allowed us to develop a robust global ecosystem of channels and partners that extend the Matterport value proposition by geography and vertical market. We intend to continue to deploy a broad set of workflow integrations with our partners and their subscribers to promote an integrated Matterport solution across our target markets. We are also developing a third-party software marketplace to extend the power of our spatial data platform with easy-to-deploy and easy-to-access Matterport software add-ons. The marketplace enables developers to build new applications and spatial data mining tools, enhance the Matterport 3D experience, and create new productivity and property management tools that supplement our core offerings. These value-added capabilities created by third-party developers enable a scalable new revenue stream, with Matterport sharing the subscription and services revenue from each add-on that is deployed to subscribers through the online marketplace. The network effects of our platform ecosystem contributes to the growth of our business, and we believe that it will continue to bolster future growth by enhancing subscriber stickiness and user engagement.\n",
- "Examples of Matterport add-ons and extensions include:\n",
- "•Add-ons: Encircle (easy-to-use field documentation tools for faster claims processing); WP Matterport Shortcode (free Wordpress plugin that allows Matterport to be embedded quickly and easily with a Matterport shortcode), WP3D Models (WordPress + Matterport integration plugin); Rela (all-in-one marketing solution for listings); CAPTUR3D (all-in-one Content Management System that extends value to Matterport digital twins); Private Model Emded (feature that allows enterprises to privately share digital twins with a large group of employees on the corporate network without requiring additional user licenses); Views (new workgroup collaboration framework to enable groups and large organizations to create separate, permissions-based workflows to manage different tasks with different teams); and Guided Tours and Tags (tool to elevate the visitor experience by creating directed virtual tours of any commercial or residential space tailored to the interests of their visitors). We unveiled our private beta integration with Amazon Web Services (AWS) IoT TwinMaker to enable enterprise customers to seamlessly connect IoT data into visually immersive and dimensionally accurate Matterport digital twin.\n",
- "•Services: Matterport ADA Compliant Digital Twin (solution to provide American Disability Act compliant digital twins) and Enterprise Cloud Software Platform (reimagined cloud software platform for the enterprise that creates, publishes, and manages digital twins of buildings and spaces of any size of shape, indoors or outdoors).\n",
- "Our Competitive Strengths\n",
- "We believe that we have a number of competitive strengths that will enable our market leadership to grow. Our competitive strengths include:\n",
- "•Breadth and depth of the Matterport platform. Our core strength is our all-in-one spatial data platform with broad reach across diverse verticals and geographies such as capture to processing to industries without customization. With the ability to integrate seamlessly with various enterprise systems, our platform delivers value across the property lifecycle for diverse end markets, including real estate, AEC, travel and hospitality, repair and insurance, and industrial and facilities. As of December 31, 2022, our global reach extended to subscribers in more than 170 countries, including over 24% of Fortune 1000 companies.\n",
- "•Market leadership and first-mover advantage. Matterport defined the category of digitizing and datafying the built world almost a decade ago, and we have become the global leader in the category. As of December 31, 2022, we had over 701,000 subscribers on our platform and approximately 9.2 million spaces under management. Our leadership is primarily driven by the fact that we were the first mover in digital twin creation. As a result of our first mover advantage, we have amassed a deep and rich library of spatial data that continues to compound and enhance our leadership position.\n",
- "•Significant network effect. With each new capture and piece of data added to our platform, the richness of our dataset and the depth of insights from our spaces under management grow. In addition, the combination of our ability to turn data into insights with incremental data from new data captures by our subscribers enables Matterport to develop features for subscribers to our platform. We were a first mover in building a spatial data library for the built world, and our leadership in gathering and deriving insights from data continues to compound and the relevance of those insights attracts more new subscribers.\n",
- "•Massive spatial data library as the raw material for valuable property insights. The scale of our spatial data library is a significant advantage in deriving insights for our subscribers. Our spatial data library serves as vital ground truth for Cortex, enabling Matterport to create powerful 3D digital twins using a wide range of camera technology, including low-cost digital and smartphone cameras. As of December 31, 2022, our data came from approximately 9.2 million spaces under management and approximately 28 billion captured square feet. As a result, we have taken property insights and analytics to new levels, benefiting subscribers across various industries. For example, facilities managers significantly reduce the time needed to create building layouts, leading to a significant decrease in the cost of site surveying and as-built modeling. AEC subscribers use the analytics of each as-built space to streamline documentation and collaborate with ease.\n",
- "•Global reach and scale. We are focused on continuing to expand our AI-powered spatial data platform worldwide. We have a significant presence in North America, Europe and Asia, with leadership teams and a go-to-market infrastructure in each of these regions. We have offices in London, Singapore and several across the United States, and we are accelerating our international expansion. As of December 31, 2022, we had over 701,000 subscribers in more than 170 countries. We believe that the geography-agnostic nature of our spatial data platform is a significant advantage as we continue to grow internationally.\n",
- "•Broad patent portfolio supporting 10 years of R&D and innovation. As of December 31, 2022, we had 54 issued and 37 pending patent applications. Our success is based on almost 10 years of focus on innovation. Innovation has been at the center of Matterport, and we will continue to prioritize our investments in R&D to further our market leading position.\n",
- "•Superior capture technology. Matterport’s capture technology platform is a software framework that enables support for a wide variety of capture devices required to create a Matterport digital twin of a building or space.\n",
- "This includes support for LiDAR cameras, 360 cameras, smartphones, Matterport Axis and the Matterport Pro2 and Pro3 cameras. The Pro2 camera was foundational to our spatial data advantage, and we have expanded that advantage with an array of Matterport-enabled third-party capture devices. In August 2022, we launched and began shipment of our Pro3 Camera along with major updates to our industry-leading digital twin cloud platform. The Matterport Pro3 Camera is an advanced 3D capture device, which includes faster boot time, swappable batteries, and a lighter design. The Pro3 camera can perform both indoors and outdoors and is designed for speed, fidelity, versatility and accuracy. Along with our Pro2 Camera, we expect that future sales of our Pro3 Camera will continue to drive increased adoption of our solutions. Matterport is democratizing the 3D capture experience, making high-fidelity and high-accuracy 3D digital twins readily available for any building type and any subscriber need in the property life cycle. While there are other 3D capture solution providers, very few can produce true, dimensionally accurate 3D results, and fewer still can automatically create a final product in photorealistic 3D, and at global scale. This expansive capture technology offering would not be possible without our rich spatial data library available to train the AI-powered Cortex engine to automatically generate accurate digital twins from photos captured with a smartphone or 360 camera.\n",
- "\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Bonus lesson\n",
- "\n",
- "Sometimes, Claude's hallucinations can be solved by lowering the `temperature` of Claude's responses. Temperature is a measurement of answer creativity between 0 and 1, with 1 being more unpredictable and less standardized, and 0 being the most consistent. \n",
- "\n",
- "Asking Claude something at temperature 0 will generally yield an almost-deterministic answer set across repeated trials (although complete determinism is not guaranteed). Asking Claude something at temperature 1 (or gradations in between) will yield more variable answers. Learn more about temperature and other parameters [here](https://docs.anthropic.com/claude/reference/messages_post).\n",
- "\n",
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 8.1 - Beyoncé Hallucination](#exercise-81---beyoncé-hallucination)\n",
- "- [Exercise 8.2 - Prospectus Hallucination](#exercise-82---prospectus-hallucination)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 8.1 - Beyoncé Hallucination\n",
- "Modify the `PROMPT` to fix Claude's hallucination issue by giving Claude an out. (Renaissance is Beyoncé's seventh studio album, not her eigthth.)\n",
- "\n",
- "We suggest you run the cell first to see what Claude hallucinates before trying to fix it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"In what year did star performer Beyoncé release her eighth studio album?\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " contains = bool(\n",
- " re.search(\"Unfortunately\", text) or\n",
- " re.search(\"I do not\", text) or\n",
- " re.search(\"I don't\", text)\n",
- " )\n",
- " does_not_contain = not bool(re.search(\"2022\", text))\n",
- " return contains and does_not_contain\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_8_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 8.1 - Prospectus Hallucination\n",
- "Modify the `PROMPT` to fix Claude's hallucination issue by asking for citations. The correct answer is that subscribers went up 49x."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"From December 2018 to December 2022, by what amount did Matterport's subscribers grow?\n",
- "\n",
- "\n",
- "Matterport SEC filing 10-K 2023\n",
- "Item 1. Business\n",
- "Our Company\n",
- "Matterport is leading the digitization and datafication of the built world. We believe the digital transformation of the built world will fundamentally change the way people interact with buildings and the physical spaces around them.\n",
- "Since its founding in 2011, Matterport’s pioneering technology has set the standard for digitizing, accessing and managing buildings, spaces and places online. Our platform’s innovative software, spatial data-driven data science, and 3D capture technology have broken down the barriers that have kept the largest asset class in the world, buildings and physical spaces, offline and underutilized for many years. We believe the digitization and datafication of the built world will continue to unlock significant operational efficiencies and property values, and that Matterport is the platform to lead this enormous global transformation.\n",
- "The world is rapidly moving from offline to online. Digital transformation has made a powerful and lasting impact across every business and industry today. According to International Data Corporation, or IDC, over $6.8 trillion of direct investments will be made on digital transformation from 2020 to 2023, the global digital transformation spending is forecasted to reach $3.4 trillion in 2026 with a five-year compound annual growth rate (“CAGR”) of 16.3%, and digital twin investments are expected to have a five-year CAGR of 35.2%. With this secular shift, there is also growing demand for the built world to transition from physical to digital. Nevertheless, the vast majority of buildings and spaces remain offline and undigitized. The global building stock, estimated by Savills to be $327 trillion in total property value as of 2021, remains largely offline today, and we estimate that less than 0.1% is penetrated by digital transformation.\n",
- "Matterport was among the first to recognize the increasing need for digitization of the built world and the power of spatial data, the unique details underlying buildings and spaces, in facilitating the understanding of buildings and spaces. In the past, technology advanced physical road maps to the data-rich, digital maps and location services we all rely on today. Matterport now digitizes buildings, creating a data-rich environment to vastly increase our understanding and the full potential of each and every space we capture. Just as we can instantly, at the touch of a button, learn the fastest route from one city to another or locate the nearest coffee shops, Matterport’s spatial data for buildings unlocks a rich set of insights and learnings about properties and spaces worldwide. In addition, just as the geo-spatial mapping platforms of today have opened their mapping data to industry to create new business models such as ridesharing, e-commerce, food delivery marketplaces, and even short-term rental and home sharing, open access to Matterport’s structured spatial data is enabling new opportunities and business models for hospitality, facilities management, insurance, construction, real estate and retail, among others.\n",
- "We believe the total addressable market opportunity for digitizing the built world is over $240 billion, and could be as high as $1 trillion as the market matures at scale. This is based on our analysis, modeling and understanding of the global building stock of over 4 billion properties and 20 billion spaces in the world today. With the help of artificial intelligence (“AI”), machine learning (“ML”) and deep learning (“DL”) technologies, we believe that, with the additional monetization opportunities from powerful spatial data-driven property insights and analytics, the total addressable market for the digitization and datafication of the built world will reach more than $1 trillion.\n",
- "\n",
- "Our spatial data platform and capture of digital twins deliver value across a diverse set of industries and use cases. Large retailers can manage thousands of store locations remotely, real estate agencies can provide virtual open houses for hundreds of properties and thousands of visitors at the same time, property developers can monitor the entirety of the construction process with greater detail and speed, and insurance companies can more precisely document and evaluate claims and underwriting assessments with efficiency and precision. Matterport delivers the critical digital experience, tools and information that matter to our subscribers about properties of virtually any size, shape, and location worldwide.\n",
- "For nearly a decade, we have been growing our spatial data platform and expanding our capabilities in order to create the most detailed, accurate, and data-rich digital twins available. Moreover, our 3D reconstruction process is fully automated, allowing our solution to scale with equal precision to millions of buildings and spaces of any type, shape, and size in the world. The universal applicability of our service provides Matterport significant scale and reach across diverse verticals and any geography. As of December 31, 2022, our subscriber base had grown approximately 39% to over 701,000 subscribers from 503,000 subscribers as of December 31, 2021, with our digital twins reaching more than 170 countries. We have digitized more than 28 billion square feet of space across multiple industries, representing significant scale and growth over the rest of the market.\n",
- "\n",
- "As we continue to transform buildings into data worldwide, we are extending our spatial data platform to further transform property planning, development, management and intelligence for our subscribers across industries to become the de facto building and business intelligence engine for the built world. We believe the demand for spatial data and resulting insights for enterprises, businesses and institutions across industries, including real estate, architecture, engineering and construction (“AEC”), retail, insurance and government, will continue to grow rapidly.\n",
- "We believe digitization and datafication represent a tremendous greenfield opportunity for growth across this massive category and asset class. From the early stages of design and development to marketing, operations, insurance and building repair and maintenance, our platform’s software and technology provide subscribers critical tools and insights to drive cost savings, increase revenues and optimally manage their buildings and spaces. We believe that hundreds of billions of dollars in unrealized utilization and operating efficiencies in the built world can be unlocked through the power of our spatial data platform. Our platform and data solutions have universal applicability across industries and building categories, giving Matterport a significant advantage as we can address the entirety of this large market opportunity and increase the value of what we believe to be the largest asset class in the world.\n",
- "With a demonstrated track record of delivering value to our subscribers, our offerings include software subscription, data licensing, services and product hardware. As of December 31, 2022, our subscriber base included over 24% of Fortune 1000 companies, with less than 10% of our total revenue generated from our top 10 subscribers. We expect more than 80% of our revenue to come from our software subscription and data license solutions by 2025. Our innovative 3D capture products, the Pro2 and Pro3 Cameras, have played an integral part in shaping the 3D building and property visualization ecosystem. The Pro2 and Pro3 Cameras have driven adoption of our solutions and have generated the unique high-quality and scaled data set that has enabled Cortex, our proprietary AI software engine, to become the pioneering engine for digital twin creation. With this data advantage initially spurred by the Pro2 Camera, we have developed a capture device agnostic platform that scales and can generate new building and property insights for our subscribers across industries and geographies.\n",
- "We have recently experienced rapid growth. Our subscribers have grown approximately 49-fold from December 31, 2018 to December 31, 2022. Our revenue increased by approximately 22% to $136.1 million for the year ended December 31, 2022, from approximately $111.2 million for the year ended December 31, 2021. Our gross profit decreased by $8.1 million or 14%, to $51.8 million for the year ended December 31, 2022, from $60.0 million for the year ended December 31, 2021, primarily attributable to certain disruptive and incremental costs due to the global supply chain constraints in fiscal year 2022. Our ability to retain and grow the subscription revenue generated by our existing subscribers is an important measure of the health of our business and our future growth prospects. We track our performance in this area by measuring our net dollar expansion rate from the same set of customers across comparable periods. Our net dollar expansion rate of 103% for the three months ended December 31, 2022 demonstrates the stickiness and growth potential of our platform.\n",
- "Our Industry and Market Opportunity\n",
- "Today, the vast majority of buildings and spaces remain undigitized. We estimate our current serviceable addressable market includes approximately 1.3 billion spaces worldwide, primarily from the real estate and travel and hospitality sectors. With approximately 9.2 million spaces under management as of December 31, 2022, we are continuing to penetrate the global building stock and expand our footprint across various end markets, including residential and commercial real estate, facilities management, retail, AEC, insurance and repair, and travel and hospitality. We estimate our total addressable market to be more than 4 billion buildings and 20 billion spaces globally, yielding a more than $240 billion market opportunity. We believe that as Matterport’s unique spatial data library and property data services continue to grow, this opportunity could increase to more than $1 trillion based on the size of the building stock and the untapped value creation available to buildings worldwide. The constraints created by the COVID-19 pandemic have only reinforced and accelerated the importance of our scaled 3D capture solution that we have developed for diverse industries and markets over the past decade.\n",
- "\n",
- "Our Spatial Data Platform\n",
- "Overview\n",
- "Our technology platform uses spatial data collected from a wide variety of digital capture devices to transform physical buildings and spaces into dimensionally accurate, photorealistic digital twins that provide our subscribers access to previously unavailable building information and insights.\n",
- "As a first mover in this massive market for nearly a decade, we have developed and scaled our industry-leading 3D reconstruction technology powered by Cortex, our proprietary AI-driven software engine that uses machine learning to recreate a photorealistic, 3D virtual representation of an entire building structure, including contents, equipment and furnishings. The finished product is a detailed and dynamic replication of the physical space that can be explored, analyzed and customized from a web browser on any device, including smartphones. The power to manage even large-scale commercial buildings is in the palm of each subscriber’s hands, made possible by our advanced technology and breakthrough innovations across our entire spatial data technology stack.\n",
- "Key elements of our spatial data platform include:\n",
- "•Bringing offline buildings online. Traditionally, our customers needed to conduct in-person site visits to understand and assess their buildings and spaces. While photographs and floor plans can be helpful, these forms of two-dimensional (“2D”) representation have limited information and tend to be static and rigid, and thus lack the interactive element critical to a holistic understanding of each building and space. With the AI-powered capabilities of Cortex, our proprietary AI software, representation of physical objects is no longer confined to static 2D images and physical visits can be eliminated. Cortex helps to move the buildings and spaces from offline to online and makes them accessible to our customers in real-time and on demand from anywhere. After subscribers scan their buildings, our visualization algorithms accurately infer spatial positions and depths from flat, 2D imagery captured through the scans and transform them into high- fidelity and precise digital twin models. This creates a fully automated image processing pipeline to ensure that each digital twin is of professional grade image quality.\n",
- "•Driven by spatial data. We are a data-driven company. Each incremental capture of a space grows the richness and depth of our spatial data library. Spatial data represents the unique and idiosyncratic details that underlie and compose the buildings and spaces in the human- made environment. Cortex uses the breadth of the billions of data points we have accumulated over the years to improve the 3D accuracy of our digital twins. We help our subscribers pinpoint the height, location and other characteristics of objects in their digital twin. Our sophisticated algorithms also deliver significant commercial value to our subscribers by generating data-based insights that allow them to confidently make assessments and decisions about their properties. For instance, property developers can assess the amount of natural heat and daylight coming from specific windows, retailers can ensure each store layout is up to the same level of code and brand requirements, and factories can insure machinery layouts meet specifications and location guidelines. With approximately 9.2 million spaces under management as of December 31, 2022, our spatial data library is the clearinghouse for information about the built world.\n",
- "•Powered by AI and ML. Artificial intelligence and machine learning technologies effectively utilize spatial data to create a robust virtual experience that is dynamic, realistic, interactive, informative and permits multiple viewing angles. AI and ML also make costly cameras unnecessary for everyday scans—subscribers can now scan their spaces by simply tapping a button on their smartphones. As a result, Matterport is a device agnostic platform, helping us more rapidly scale and drive towards our mission of digitizing and indexing the built world.\n",
- "Our value proposition to subscribers is designed to serve the entirety of the digital building lifecycle, from design and build to maintenance and operations, promotion, sale, lease, insure, repair, restore, secure and finance. As a result, we believe we are uniquely positioned to grow our revenue with our subscribers as we help them to discover opportunities to drive short- and long-term return on investment by taking their buildings and spaces from offline to online across their portfolios of properties.\n",
- "Ubiquitous Capture\n",
- "Matterport has become the standard for 3D space capture. Our technology platform empowers subscribers worldwide to quickly, easily and accurately digitize, customize and manage interactive and dimensionally accurate digital twins of their buildings and spaces.\n",
- "The Matterport platform is designed to work with a wide range of LiDAR, spherical, 3D and 360 cameras, as well as smartphones, to suit the capture needs of all of our subscribers. This provides the flexibility to capture a space of any size, scale, and complexity, at anytime and anywhere.\n",
- "•Matterport Pro3 is our newest 3D camera that scans properties faster than earlier versions to help accelerate project completion. Pro3 provides the highest accuracy scans of both indoor and outdoor spaces and is designed for speed, fidelity, versatility and accuracy. Capturing 3D data up to 100 meters away at less than 20 seconds per sweep, Pro3’s ultra-fast, high-precision LiDAR sensor can run for hours and takes millions of measurements in any conditions.\n",
- "•Matterport Pro2 is our proprietary 3D camera that has been used to capture millions of spaces around the world with a high degree of fidelity, precision, speed and simplicity. Capable of capturing buildings more than 500,000 square feet in size, it has become the camera of choice for many residential, commercial, industrial and large-scale properties.\n",
- "•360 Cameras. Matterport supports a selection of 360 cameras available in the market. These affordable, pocket sized devices deliver precision captures with high fidelity and are appropriate for capturing smaller homes, condos, short-term rentals, apartments, and more. The spherical lens image capture technology of these devices gives Cortex robust, detailed image data to transform panoramas into our industry-leading digital twins.\n",
- "•LEICA BLK360. Through our partnership with Leica, our 3D reconstruction technology and our AI powered software engine, Cortex, transform this powerful LiDAR camera into an ultra-precise capture device for creating Matterport digital twins. It is the solution of choice for AEC professionals when exacting precision is required.\n",
- "•Smartphone Capture. Our capture apps are commercially available for both iOS and Android. Matterport’s smartphone capture solution has democratized 3D capture, making it easy and accessible for anyone to digitize buildings and spaces with a recent iPhone device since the initial introduction of Matterport for iPhone in May 2020. In April 2021, we announced the official release of the Android Capture app, giving Android users the ability to quickly and easily capture buildings and spaces in immersive 3D. In February 2022, we launched Matterport Axis, a motorized mount that holds a smartphone and can be used with the Matterport Capture app to capture 3D digital twins of any physical space with increased speed, precision, and consistency.\n",
- "Cortex and 3D Reconstruction (the Matterport Digital Twin)\n",
- "With a spatial data library, as of December 31, 2022, of approximately 9.2 million spaces under management, representing approximately 28 billion captured square feet of space, we use our advanced ML and DL technologies to algorithmically transform the spatial data we capture into an accurate 3D digital reproduction of any physical space. This intelligent, automated 3D reconstruction is made possible by Cortex, our AI-powered software engine that includes a deep learning neural network that uses our spatial data library to understand how a building or space is divided into floors and rooms, where the doorways and openings are located, and what types of rooms are present, such that those forms are compiled and aligned with dimensional accuracy into a dynamic, photorealistic digital twin. Other components of Cortex include AI-powered computer vision technologies to identify and classify the contents inside a building or space, and object recognition technologies to identify and segment everything from furnishings and equipment to doors, windows, light fixtures, fire suppression sprinklers and fire escapes. Our highly scalable artificial intelligence platform enables our subscribers to tap into powerful, enhanced building data and insights at the click of a button.\n",
- "\n",
- "The Science Behind the Matterport Digital Twin: Cortex AI Highlights\n",
- "Matterport Runs on Cortex\n",
- "Cortex is our AI-powered software engine that includes a precision deep learning neural network to create digital twins of any building or space. Developed using our proprietary spatial data captured with our Pro2 and Pro3 cameras, Cortex delivers a high degree of precision and accuracy while enabling 3D capture using everyday devices.\n",
- "Generic neural networks struggle with 3D reconstruction of the real world. Matterport-optimized networks deliver more accurate and robust results. More than just raw training data, Matterport’s datasets allow us to develop new neural network architectures and evaluate them against user behavior and real-world data in millions of situations.\n",
- "•Deep learning: Connecting and optimizing the detailed neural network data architecture of each space is key to creating robust, highly accurate 3D digital twins. Cortex evaluates and optimizes each 3D model against Matterport’s rich spatial data aggregated from millions of buildings and spaces and the human annotations of those data provided by tens of thousands of subscribers worldwide. Cortex’s evaluative abilities and its data-driven optimization of 3D reconstruction yield consistent, high-precision results across a wide array of building configurations, spaces and environments.\n",
- "•Dynamic 3D reconstruction: Creating precise 3D spatial data at scale from 2D visuals and static images requires a combination of photorealistic, detailed data from multiple viewpoints and millions of spaces that train and optimize Cortex’s neural network and learning capabilities for improved 3D reconstruction of any space. Cortex’s capabilities combined with real-time spatial alignment algorithms in our 3D capture technology create an intuitive “preview” of any work in progress, allowing subscribers to work with their content interactively and in real-time.\n",
- "•Computer vision: Cortex enables a suite of powerful features to enhance the value of digital twins. These include automatic measurements for rooms or objects in a room, automatic 2D-from-3D high-definition photo gallery creation, auto face blurring for privacy protection, custom videos, walkthroughs, auto room labeling and object recognition.\n",
- "•Advanced image processing: Matterport’s computational photography algorithms create a fully automated image processing pipeline to help ensure that each digital twin is of professional grade image quality. Our patented technology makes 3D capture as simple as pressing a single button. Matterport’s software and technology manage the remaining steps, including white balance and camera-specific color correction, high dynamic range tone mapping, de-noising, haze removal, sharpening, saturation and other adjustments to improve image quality.\n",
- "Spatial Data and AI-Powered Insights\n",
- "Every Matterport digital twin contains extensive information about a building, room or physical space. The data uses our AI-powered Cortex engine. In addition to the Matterport digital twin itself, our spatial data consists of precision building geometry and structural detail, building contents, fixtures and condition, along with high-definition imagery and photorealistic detail from many vantage points in a space. Cortex employs a technique we call deep spatial indexing. Deep spatial indexing uses artificial intelligence, computer vision and deep learning to identify and convey important details about each space, its structure and its contents with precision and fidelity. We have created a robust spatial data standard that enables Matterport subscribers to harness an interoperable digital system of record for any building.\n",
- "In addition to creating a highly interactive digital experience for subscribers through the construction of digital twins, we ask ourselves two questions for every subscriber: (1) what is important about their building or physical space and (2) what learnings and insights can we deliver for this space? Our AI-powered Cortex engine helps us answer these questions using our spatial data library to provide aggregated property trends and operational and valuation insights. Moreover, as the Matterport platform ecosystem continues to expand, our subscribers, partners and other third-party developers can bring their own tools to further the breadth and depth of insights they can harvest from our rich spatial data layer.\n",
- "Extensible Platform Ecosystem\n",
- "Matterport offers the largest and most accurate library of spatial data in the world, with, as of December 31, 2022, approximately 9.2 million spaces under management and approximately 28 billion captured square feet. The versatility of our spatial data platform and extensive enterprise software development kit and application programming interfaces (“APIs”) has allowed us to develop a robust global ecosystem of channels and partners that extend the Matterport value proposition by geography and vertical market. We intend to continue to deploy a broad set of workflow integrations with our partners and their subscribers to promote an integrated Matterport solution across our target markets. We are also developing a third-party software marketplace to extend the power of our spatial data platform with easy-to-deploy and easy-to-access Matterport software add-ons. The marketplace enables developers to build new applications and spatial data mining tools, enhance the Matterport 3D experience, and create new productivity and property management tools that supplement our core offerings. These value-added capabilities created by third-party developers enable a scalable new revenue stream, with Matterport sharing the subscription and services revenue from each add-on that is deployed to subscribers through the online marketplace. The network effects of our platform ecosystem contributes to the growth of our business, and we believe that it will continue to bolster future growth by enhancing subscriber stickiness and user engagement.\n",
- "Examples of Matterport add-ons and extensions include:\n",
- "•Add-ons: Encircle (easy-to-use field documentation tools for faster claims processing); WP Matterport Shortcode (free Wordpress plugin that allows Matterport to be embedded quickly and easily with a Matterport shortcode), WP3D Models (WordPress + Matterport integration plugin); Rela (all-in-one marketing solution for listings); CAPTUR3D (all-in-one Content Management System that extends value to Matterport digital twins); Private Model Emded (feature that allows enterprises to privately share digital twins with a large group of employees on the corporate network without requiring additional user licenses); Views (new workgroup collaboration framework to enable groups and large organizations to create separate, permissions-based workflows to manage different tasks with different teams); and Guided Tours and Tags (tool to elevate the visitor experience by creating directed virtual tours of any commercial or residential space tailored to the interests of their visitors). We unveiled our private beta integration with Amazon Web Services (AWS) IoT TwinMaker to enable enterprise customers to seamlessly connect IoT data into visually immersive and dimensionally accurate Matterport digital twin.\n",
- "•Services: Matterport ADA Compliant Digital Twin (solution to provide American Disability Act compliant digital twins) and Enterprise Cloud Software Platform (reimagined cloud software platform for the enterprise that creates, publishes, and manages digital twins of buildings and spaces of any size of shape, indoors or outdoors).\n",
- "Our Competitive Strengths\n",
- "We believe that we have a number of competitive strengths that will enable our market leadership to grow. Our competitive strengths include:\n",
- "•Breadth and depth of the Matterport platform. Our core strength is our all-in-one spatial data platform with broad reach across diverse verticals and geographies such as capture to processing to industries without customization. With the ability to integrate seamlessly with various enterprise systems, our platform delivers value across the property lifecycle for diverse end markets, including real estate, AEC, travel and hospitality, repair and insurance, and industrial and facilities. As of December 31, 2022, our global reach extended to subscribers in more than 170 countries, including over 24% of Fortune 1000 companies.\n",
- "•Market leadership and first-mover advantage. Matterport defined the category of digitizing and datafying the built world almost a decade ago, and we have become the global leader in the category. As of December 31, 2022, we had over 701,000 subscribers on our platform and approximately 9.2 million spaces under management. Our leadership is primarily driven by the fact that we were the first mover in digital twin creation. As a result of our first mover advantage, we have amassed a deep and rich library of spatial data that continues to compound and enhance our leadership position.\n",
- "•Significant network effect. With each new capture and piece of data added to our platform, the richness of our dataset and the depth of insights from our spaces under management grow. In addition, the combination of our ability to turn data into insights with incremental data from new data captures by our subscribers enables Matterport to develop features for subscribers to our platform. We were a first mover in building a spatial data library for the built world, and our leadership in gathering and deriving insights from data continues to compound and the relevance of those insights attracts more new subscribers.\n",
- "•Massive spatial data library as the raw material for valuable property insights. The scale of our spatial data library is a significant advantage in deriving insights for our subscribers. Our spatial data library serves as vital ground truth for Cortex, enabling Matterport to create powerful 3D digital twins using a wide range of camera technology, including low-cost digital and smartphone cameras. As of December 31, 2022, our data came from approximately 9.2 million spaces under management and approximately 28 billion captured square feet. As a result, we have taken property insights and analytics to new levels, benefiting subscribers across various industries. For example, facilities managers significantly reduce the time needed to create building layouts, leading to a significant decrease in the cost of site surveying and as-built modeling. AEC subscribers use the analytics of each as-built space to streamline documentation and collaborate with ease.\n",
- "•Global reach and scale. We are focused on continuing to expand our AI-powered spatial data platform worldwide. We have a significant presence in North America, Europe and Asia, with leadership teams and a go-to-market infrastructure in each of these regions. We have offices in London, Singapore and several across the United States, and we are accelerating our international expansion. As of December 31, 2022, we had over 701,000 subscribers in more than 170 countries. We believe that the geography-agnostic nature of our spatial data platform is a significant advantage as we continue to grow internationally.\n",
- "•Broad patent portfolio supporting 10 years of R&D and innovation. As of December 31, 2022, we had 54 issued and 37 pending patent applications. Our success is based on almost 10 years of focus on innovation. Innovation has been at the center of Matterport, and we will continue to prioritize our investments in R&D to further our market leading position.\n",
- "•Superior capture technology. Matterport’s capture technology platform is a software framework that enables support for a wide variety of capture devices required to create a Matterport digital twin of a building or space.\n",
- "This includes support for LiDAR cameras, 360 cameras, smartphones, Matterport Axis and the Matterport Pro2 and Pro3 cameras. The Pro2 camera was foundational to our spatial data advantage, and we have expanded that advantage with an array of Matterport-enabled third-party capture devices. In August 2022, we launched and began shipment of our Pro3 Camera along with major updates to our industry-leading digital twin cloud platform. The Matterport Pro3 Camera is an advanced 3D capture device, which includes faster boot time, swappable batteries, and a lighter design. The Pro3 camera can perform both indoors and outdoors and is designed for speed, fidelity, versatility and accuracy. Along with our Pro2 Camera, we expect that future sales of our Pro3 Camera will continue to drive increased adoption of our solutions. Matterport is democratizing the 3D capture experience, making high-fidelity and high-accuracy 3D digital twins readily available for any building type and any subscriber need in the property life cycle. While there are other 3D capture solution providers, very few can produce true, dimensionally accurate 3D results, and fewer still can automatically create a final product in photorealistic 3D, and at global scale. This expansive capture technology offering would not be possible without our rich spatial data library available to train the AI-powered Cortex engine to automatically generate accurate digital twins from photos captured with a smartphone or 360 camera.\n",
- "\"\"\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(\"49-fold\", text))\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n------------------------------------------ GRADING ------------------------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_8_2_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the heaviest hippo of all time?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Who is the heaviest hippo of all time? Only answer if you know the answer with certainty.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"What was Matterport's subscriber base on the precise date of May 31, 2020?\n",
- "Please read the below document. Then write a brief numerical answer inside tags.\n",
- "\n",
- "\n",
- "Matterport SEC filing 10-K 2023\n",
- "Item 1. Business\n",
- "Our Company\n",
- "Matterport is leading the digitization and datafication of the built world. We believe the digital transformation of the built world will fundamentally change the way people interact with buildings and the physical spaces around them.\n",
- "Since its founding in 2011, Matterport’s pioneering technology has set the standard for digitizing, accessing and managing buildings, spaces and places online. Our platform’s innovative software, spatial data-driven data science, and 3D capture technology have broken down the barriers that have kept the largest asset class in the world, buildings and physical spaces, offline and underutilized for many years. We believe the digitization and datafication of the built world will continue to unlock significant operational efficiencies and property values, and that Matterport is the platform to lead this enormous global transformation.\n",
- "The world is rapidly moving from offline to online. Digital transformation has made a powerful and lasting impact across every business and industry today. According to International Data Corporation, or IDC, over $6.8 trillion of direct investments will be made on digital transformation from 2020 to 2023, the global digital transformation spending is forecasted to reach $3.4 trillion in 2026 with a five-year compound annual growth rate (“CAGR”) of 16.3%, and digital twin investments are expected to have a five-year CAGR of 35.2%. With this secular shift, there is also growing demand for the built world to transition from physical to digital. Nevertheless, the vast majority of buildings and spaces remain offline and undigitized. The global building stock, estimated by Savills to be $327 trillion in total property value as of 2021, remains largely offline today, and we estimate that less than 0.1% is penetrated by digital transformation.\n",
- "Matterport was among the first to recognize the increasing need for digitization of the built world and the power of spatial data, the unique details underlying buildings and spaces, in facilitating the understanding of buildings and spaces. In the past, technology advanced physical road maps to the data-rich, digital maps and location services we all rely on today. Matterport now digitizes buildings, creating a data-rich environment to vastly increase our understanding and the full potential of each and every space we capture. Just as we can instantly, at the touch of a button, learn the fastest route from one city to another or locate the nearest coffee shops, Matterport’s spatial data for buildings unlocks a rich set of insights and learnings about properties and spaces worldwide. In addition, just as the geo-spatial mapping platforms of today have opened their mapping data to industry to create new business models such as ridesharing, e-commerce, food delivery marketplaces, and even short-term rental and home sharing, open access to Matterport’s structured spatial data is enabling new opportunities and business models for hospitality, facilities management, insurance, construction, real estate and retail, among others.\n",
- "We believe the total addressable market opportunity for digitizing the built world is over $240 billion, and could be as high as $1 trillion as the market matures at scale. This is based on our analysis, modeling and understanding of the global building stock of over 4 billion properties and 20 billion spaces in the world today. With the help of artificial intelligence (“AI”), machine learning (“ML”) and deep learning (“DL”) technologies, we believe that, with the additional monetization opportunities from powerful spatial data-driven property insights and analytics, the total addressable market for the digitization and datafication of the built world will reach more than $1 trillion.\n",
- "\n",
- "Our spatial data platform and capture of digital twins deliver value across a diverse set of industries and use cases. Large retailers can manage thousands of store locations remotely, real estate agencies can provide virtual open houses for hundreds of properties and thousands of visitors at the same time, property developers can monitor the entirety of the construction process with greater detail and speed, and insurance companies can more precisely document and evaluate claims and underwriting assessments with efficiency and precision. Matterport delivers the critical digital experience, tools and information that matter to our subscribers about properties of virtually any size, shape, and location worldwide.\n",
- "For nearly a decade, we have been growing our spatial data platform and expanding our capabilities in order to create the most detailed, accurate, and data-rich digital twins available. Moreover, our 3D reconstruction process is fully automated, allowing our solution to scale with equal precision to millions of buildings and spaces of any type, shape, and size in the world. The universal applicability of our service provides Matterport significant scale and reach across diverse verticals and any geography. As of December 31, 2022, our subscriber base had grown approximately 39% to over 701,000 subscribers from 503,000 subscribers as of December 31, 2021, with our digital twins reaching more than 170 countries. We have digitized more than 28 billion square feet of space across multiple industries, representing significant scale and growth over the rest of the market.\n",
- "\n",
- "As we continue to transform buildings into data worldwide, we are extending our spatial data platform to further transform property planning, development, management and intelligence for our subscribers across industries to become the de facto building and business intelligence engine for the built world. We believe the demand for spatial data and resulting insights for enterprises, businesses and institutions across industries, including real estate, architecture, engineering and construction (“AEC”), retail, insurance and government, will continue to grow rapidly.\n",
- "We believe digitization and datafication represent a tremendous greenfield opportunity for growth across this massive category and asset class. From the early stages of design and development to marketing, operations, insurance and building repair and maintenance, our platform’s software and technology provide subscribers critical tools and insights to drive cost savings, increase revenues and optimally manage their buildings and spaces. We believe that hundreds of billions of dollars in unrealized utilization and operating efficiencies in the built world can be unlocked through the power of our spatial data platform. Our platform and data solutions have universal applicability across industries and building categories, giving Matterport a significant advantage as we can address the entirety of this large market opportunity and increase the value of what we believe to be the largest asset class in the world.\n",
- "With a demonstrated track record of delivering value to our subscribers, our offerings include software subscription, data licensing, services and product hardware. As of December 31, 2022, our subscriber base included over 24% of Fortune 1000 companies, with less than 10% of our total revenue generated from our top 10 subscribers. We expect more than 80% of our revenue to come from our software subscription and data license solutions by 2025. Our innovative 3D capture products, the Pro2 and Pro3 Cameras, have played an integral part in shaping the 3D building and property visualization ecosystem. The Pro2 and Pro3 Cameras have driven adoption of our solutions and have generated the unique high-quality and scaled data set that has enabled Cortex, our proprietary AI software engine, to become the pioneering engine for digital twin creation. With this data advantage initially spurred by the Pro2 Camera, we have developed a capture device agnostic platform that scales and can generate new building and property insights for our subscribers across industries and geographies.\n",
- "We have recently experienced rapid growth. Our subscribers have grown approximately 49-fold from December 31, 2018 to December 31, 2022. Our revenue increased by approximately 22% to $136.1 million for the year ended December 31, 2022, from approximately $111.2 million for the year ended December 31, 2021. Our gross profit decreased by $8.1 million or 14%, to $51.8 million for the year ended December 31, 2022, from $60.0 million for the year ended December 31, 2021, primarily attributable to certain disruptive and incremental costs due to the global supply chain constraints in fiscal year 2022. Our ability to retain and grow the subscription revenue generated by our existing subscribers is an important measure of the health of our business and our future growth prospects. We track our performance in this area by measuring our net dollar expansion rate from the same set of customers across comparable periods. Our net dollar expansion rate of 103% for the three months ended December 31, 2022 demonstrates the stickiness and growth potential of our platform.\n",
- "Our Industry and Market Opportunity\n",
- "Today, the vast majority of buildings and spaces remain undigitized. We estimate our current serviceable addressable market includes approximately 1.3 billion spaces worldwide, primarily from the real estate and travel and hospitality sectors. With approximately 9.2 million spaces under management as of December 31, 2022, we are continuing to penetrate the global building stock and expand our footprint across various end markets, including residential and commercial real estate, facilities management, retail, AEC, insurance and repair, and travel and hospitality. We estimate our total addressable market to be more than 4 billion buildings and 20 billion spaces globally, yielding a more than $240 billion market opportunity. We believe that as Matterport’s unique spatial data library and property data services continue to grow, this opportunity could increase to more than $1 trillion based on the size of the building stock and the untapped value creation available to buildings worldwide. The constraints created by the COVID-19 pandemic have only reinforced and accelerated the importance of our scaled 3D capture solution that we have developed for diverse industries and markets over the past decade.\n",
- "\n",
- "Our Spatial Data Platform\n",
- "Overview\n",
- "Our technology platform uses spatial data collected from a wide variety of digital capture devices to transform physical buildings and spaces into dimensionally accurate, photorealistic digital twins that provide our subscribers access to previously unavailable building information and insights.\n",
- "As a first mover in this massive market for nearly a decade, we have developed and scaled our industry-leading 3D reconstruction technology powered by Cortex, our proprietary AI-driven software engine that uses machine learning to recreate a photorealistic, 3D virtual representation of an entire building structure, including contents, equipment and furnishings. The finished product is a detailed and dynamic replication of the physical space that can be explored, analyzed and customized from a web browser on any device, including smartphones. The power to manage even large-scale commercial buildings is in the palm of each subscriber’s hands, made possible by our advanced technology and breakthrough innovations across our entire spatial data technology stack.\n",
- "Key elements of our spatial data platform include:\n",
- "•Bringing offline buildings online. Traditionally, our customers needed to conduct in-person site visits to understand and assess their buildings and spaces. While photographs and floor plans can be helpful, these forms of two-dimensional (“2D”) representation have limited information and tend to be static and rigid, and thus lack the interactive element critical to a holistic understanding of each building and space. With the AI-powered capabilities of Cortex, our proprietary AI software, representation of physical objects is no longer confined to static 2D images and physical visits can be eliminated. Cortex helps to move the buildings and spaces from offline to online and makes them accessible to our customers in real-time and on demand from anywhere. After subscribers scan their buildings, our visualization algorithms accurately infer spatial positions and depths from flat, 2D imagery captured through the scans and transform them into high- fidelity and precise digital twin models. This creates a fully automated image processing pipeline to ensure that each digital twin is of professional grade image quality.\n",
- "•Driven by spatial data. We are a data-driven company. Each incremental capture of a space grows the richness and depth of our spatial data library. Spatial data represents the unique and idiosyncratic details that underlie and compose the buildings and spaces in the human- made environment. Cortex uses the breadth of the billions of data points we have accumulated over the years to improve the 3D accuracy of our digital twins. We help our subscribers pinpoint the height, location and other characteristics of objects in their digital twin. Our sophisticated algorithms also deliver significant commercial value to our subscribers by generating data-based insights that allow them to confidently make assessments and decisions about their properties. For instance, property developers can assess the amount of natural heat and daylight coming from specific windows, retailers can ensure each store layout is up to the same level of code and brand requirements, and factories can insure machinery layouts meet specifications and location guidelines. With approximately 9.2 million spaces under management as of December 31, 2022, our spatial data library is the clearinghouse for information about the built world.\n",
- "•Powered by AI and ML. Artificial intelligence and machine learning technologies effectively utilize spatial data to create a robust virtual experience that is dynamic, realistic, interactive, informative and permits multiple viewing angles. AI and ML also make costly cameras unnecessary for everyday scans—subscribers can now scan their spaces by simply tapping a button on their smartphones. As a result, Matterport is a device agnostic platform, helping us more rapidly scale and drive towards our mission of digitizing and indexing the built world.\n",
- "Our value proposition to subscribers is designed to serve the entirety of the digital building lifecycle, from design and build to maintenance and operations, promotion, sale, lease, insure, repair, restore, secure and finance. As a result, we believe we are uniquely positioned to grow our revenue with our subscribers as we help them to discover opportunities to drive short- and long-term return on investment by taking their buildings and spaces from offline to online across their portfolios of properties.\n",
- "Ubiquitous Capture\n",
- "Matterport has become the standard for 3D space capture. Our technology platform empowers subscribers worldwide to quickly, easily and accurately digitize, customize and manage interactive and dimensionally accurate digital twins of their buildings and spaces.\n",
- "The Matterport platform is designed to work with a wide range of LiDAR, spherical, 3D and 360 cameras, as well as smartphones, to suit the capture needs of all of our subscribers. This provides the flexibility to capture a space of any size, scale, and complexity, at anytime and anywhere.\n",
- "•Matterport Pro3 is our newest 3D camera that scans properties faster than earlier versions to help accelerate project completion. Pro3 provides the highest accuracy scans of both indoor and outdoor spaces and is designed for speed, fidelity, versatility and accuracy. Capturing 3D data up to 100 meters away at less than 20 seconds per sweep, Pro3’s ultra-fast, high-precision LiDAR sensor can run for hours and takes millions of measurements in any conditions.\n",
- "•Matterport Pro2 is our proprietary 3D camera that has been used to capture millions of spaces around the world with a high degree of fidelity, precision, speed and simplicity. Capable of capturing buildings more than 500,000 square feet in size, it has become the camera of choice for many residential, commercial, industrial and large-scale properties.\n",
- "•360 Cameras. Matterport supports a selection of 360 cameras available in the market. These affordable, pocket sized devices deliver precision captures with high fidelity and are appropriate for capturing smaller homes, condos, short-term rentals, apartments, and more. The spherical lens image capture technology of these devices gives Cortex robust, detailed image data to transform panoramas into our industry-leading digital twins.\n",
- "•LEICA BLK360. Through our partnership with Leica, our 3D reconstruction technology and our AI powered software engine, Cortex, transform this powerful LiDAR camera into an ultra-precise capture device for creating Matterport digital twins. It is the solution of choice for AEC professionals when exacting precision is required.\n",
- "•Smartphone Capture. Our capture apps are commercially available for both iOS and Android. Matterport’s smartphone capture solution has democratized 3D capture, making it easy and accessible for anyone to digitize buildings and spaces with a recent iPhone device since the initial introduction of Matterport for iPhone in May 2020. In April 2021, we announced the official release of the Android Capture app, giving Android users the ability to quickly and easily capture buildings and spaces in immersive 3D. In February 2022, we launched Matterport Axis, a motorized mount that holds a smartphone and can be used with the Matterport Capture app to capture 3D digital twins of any physical space with increased speed, precision, and consistency.\n",
- "Cortex and 3D Reconstruction (the Matterport Digital Twin)\n",
- "With a spatial data library, as of December 31, 2022, of approximately 9.2 million spaces under management, representing approximately 28 billion captured square feet of space, we use our advanced ML and DL technologies to algorithmically transform the spatial data we capture into an accurate 3D digital reproduction of any physical space. This intelligent, automated 3D reconstruction is made possible by Cortex, our AI-powered software engine that includes a deep learning neural network that uses our spatial data library to understand how a building or space is divided into floors and rooms, where the doorways and openings are located, and what types of rooms are present, such that those forms are compiled and aligned with dimensional accuracy into a dynamic, photorealistic digital twin. Other components of Cortex include AI-powered computer vision technologies to identify and classify the contents inside a building or space, and object recognition technologies to identify and segment everything from furnishings and equipment to doors, windows, light fixtures, fire suppression sprinklers and fire escapes. Our highly scalable artificial intelligence platform enables our subscribers to tap into powerful, enhanced building data and insights at the click of a button.\n",
- "\n",
- "The Science Behind the Matterport Digital Twin: Cortex AI Highlights\n",
- "Matterport Runs on Cortex\n",
- "Cortex is our AI-powered software engine that includes a precision deep learning neural network to create digital twins of any building or space. Developed using our proprietary spatial data captured with our Pro2 and Pro3 cameras, Cortex delivers a high degree of precision and accuracy while enabling 3D capture using everyday devices.\n",
- "Generic neural networks struggle with 3D reconstruction of the real world. Matterport-optimized networks deliver more accurate and robust results. More than just raw training data, Matterport’s datasets allow us to develop new neural network architectures and evaluate them against user behavior and real-world data in millions of situations.\n",
- "•Deep learning: Connecting and optimizing the detailed neural network data architecture of each space is key to creating robust, highly accurate 3D digital twins. Cortex evaluates and optimizes each 3D model against Matterport’s rich spatial data aggregated from millions of buildings and spaces and the human annotations of those data provided by tens of thousands of subscribers worldwide. Cortex’s evaluative abilities and its data-driven optimization of 3D reconstruction yield consistent, high-precision results across a wide array of building configurations, spaces and environments.\n",
- "•Dynamic 3D reconstruction: Creating precise 3D spatial data at scale from 2D visuals and static images requires a combination of photorealistic, detailed data from multiple viewpoints and millions of spaces that train and optimize Cortex’s neural network and learning capabilities for improved 3D reconstruction of any space. Cortex’s capabilities combined with real-time spatial alignment algorithms in our 3D capture technology create an intuitive “preview” of any work in progress, allowing subscribers to work with their content interactively and in real-time.\n",
- "•Computer vision: Cortex enables a suite of powerful features to enhance the value of digital twins. These include automatic measurements for rooms or objects in a room, automatic 2D-from-3D high-definition photo gallery creation, auto face blurring for privacy protection, custom videos, walkthroughs, auto room labeling and object recognition.\n",
- "•Advanced image processing: Matterport’s computational photography algorithms create a fully automated image processing pipeline to help ensure that each digital twin is of professional grade image quality. Our patented technology makes 3D capture as simple as pressing a single button. Matterport’s software and technology manage the remaining steps, including white balance and camera-specific color correction, high dynamic range tone mapping, de-noising, haze removal, sharpening, saturation and other adjustments to improve image quality.\n",
- "Spatial Data and AI-Powered Insights\n",
- "Every Matterport digital twin contains extensive information about a building, room or physical space. The data uses our AI-powered Cortex engine. In addition to the Matterport digital twin itself, our spatial data consists of precision building geometry and structural detail, building contents, fixtures and condition, along with high-definition imagery and photorealistic detail from many vantage points in a space. Cortex employs a technique we call deep spatial indexing. Deep spatial indexing uses artificial intelligence, computer vision and deep learning to identify and convey important details about each space, its structure and its contents with precision and fidelity. We have created a robust spatial data standard that enables Matterport subscribers to harness an interoperable digital system of record for any building.\n",
- "In addition to creating a highly interactive digital experience for subscribers through the construction of digital twins, we ask ourselves two questions for every subscriber: (1) what is important about their building or physical space and (2) what learnings and insights can we deliver for this space? Our AI-powered Cortex engine helps us answer these questions using our spatial data library to provide aggregated property trends and operational and valuation insights. Moreover, as the Matterport platform ecosystem continues to expand, our subscribers, partners and other third-party developers can bring their own tools to further the breadth and depth of insights they can harvest from our rich spatial data layer.\n",
- "Extensible Platform Ecosystem\n",
- "Matterport offers the largest and most accurate library of spatial data in the world, with, as of December 31, 2022, approximately 9.2 million spaces under management and approximately 28 billion captured square feet. The versatility of our spatial data platform and extensive enterprise software development kit and application programming interfaces (“APIs”) has allowed us to develop a robust global ecosystem of channels and partners that extend the Matterport value proposition by geography and vertical market. We intend to continue to deploy a broad set of workflow integrations with our partners and their subscribers to promote an integrated Matterport solution across our target markets. We are also developing a third-party software marketplace to extend the power of our spatial data platform with easy-to-deploy and easy-to-access Matterport software add-ons. The marketplace enables developers to build new applications and spatial data mining tools, enhance the Matterport 3D experience, and create new productivity and property management tools that supplement our core offerings. These value-added capabilities created by third-party developers enable a scalable new revenue stream, with Matterport sharing the subscription and services revenue from each add-on that is deployed to subscribers through the online marketplace. The network effects of our platform ecosystem contributes to the growth of our business, and we believe that it will continue to bolster future growth by enhancing subscriber stickiness and user engagement.\n",
- "Examples of Matterport add-ons and extensions include:\n",
- "•Add-ons: Encircle (easy-to-use field documentation tools for faster claims processing); WP Matterport Shortcode (free Wordpress plugin that allows Matterport to be embedded quickly and easily with a Matterport shortcode), WP3D Models (WordPress + Matterport integration plugin); Rela (all-in-one marketing solution for listings); CAPTUR3D (all-in-one Content Management System that extends value to Matterport digital twins); Private Model Emded (feature that allows enterprises to privately share digital twins with a large group of employees on the corporate network without requiring additional user licenses); Views (new workgroup collaboration framework to enable groups and large organizations to create separate, permissions-based workflows to manage different tasks with different teams); and Guided Tours and Tags (tool to elevate the visitor experience by creating directed virtual tours of any commercial or residential space tailored to the interests of their visitors). We unveiled our private beta integration with Amazon Web Services (AWS) IoT TwinMaker to enable enterprise customers to seamlessly connect IoT data into visually immersive and dimensionally accurate Matterport digital twin.\n",
- "•Services: Matterport ADA Compliant Digital Twin (solution to provide American Disability Act compliant digital twins) and Enterprise Cloud Software Platform (reimagined cloud software platform for the enterprise that creates, publishes, and manages digital twins of buildings and spaces of any size of shape, indoors or outdoors).\n",
- "Our Competitive Strengths\n",
- "We believe that we have a number of competitive strengths that will enable our market leadership to grow. Our competitive strengths include:\n",
- "•Breadth and depth of the Matterport platform. Our core strength is our all-in-one spatial data platform with broad reach across diverse verticals and geographies such as capture to processing to industries without customization. With the ability to integrate seamlessly with various enterprise systems, our platform delivers value across the property lifecycle for diverse end markets, including real estate, AEC, travel and hospitality, repair and insurance, and industrial and facilities. As of December 31, 2022, our global reach extended to subscribers in more than 170 countries, including over 24% of Fortune 1000 companies.\n",
- "•Market leadership and first-mover advantage. Matterport defined the category of digitizing and datafying the built world almost a decade ago, and we have become the global leader in the category. As of December 31, 2022, we had over 701,000 subscribers on our platform and approximately 9.2 million spaces under management. Our leadership is primarily driven by the fact that we were the first mover in digital twin creation. As a result of our first mover advantage, we have amassed a deep and rich library of spatial data that continues to compound and enhance our leadership position.\n",
- "•Significant network effect. With each new capture and piece of data added to our platform, the richness of our dataset and the depth of insights from our spaces under management grow. In addition, the combination of our ability to turn data into insights with incremental data from new data captures by our subscribers enables Matterport to develop features for subscribers to our platform. We were a first mover in building a spatial data library for the built world, and our leadership in gathering and deriving insights from data continues to compound and the relevance of those insights attracts more new subscribers.\n",
- "•Massive spatial data library as the raw material for valuable property insights. The scale of our spatial data library is a significant advantage in deriving insights for our subscribers. Our spatial data library serves as vital ground truth for Cortex, enabling Matterport to create powerful 3D digital twins using a wide range of camera technology, including low-cost digital and smartphone cameras. As of December 31, 2022, our data came from approximately 9.2 million spaces under management and approximately 28 billion captured square feet. As a result, we have taken property insights and analytics to new levels, benefiting subscribers across various industries. For example, facilities managers significantly reduce the time needed to create building layouts, leading to a significant decrease in the cost of site surveying and as-built modeling. AEC subscribers use the analytics of each as-built space to streamline documentation and collaborate with ease.\n",
- "•Global reach and scale. We are focused on continuing to expand our AI-powered spatial data platform worldwide. We have a significant presence in North America, Europe and Asia, with leadership teams and a go-to-market infrastructure in each of these regions. We have offices in London, Singapore and several across the United States, and we are accelerating our international expansion. As of December 31, 2022, we had over 701,000 subscribers in more than 170 countries. We believe that the geography-agnostic nature of our spatial data platform is a significant advantage as we continue to grow internationally.\n",
- "•Broad patent portfolio supporting 10 years of R&D and innovation. As of December 31, 2022, we had 54 issued and 37 pending patent applications. Our success is based on almost 10 years of focus on innovation. Innovation has been at the center of Matterport, and we will continue to prioritize our investments in R&D to further our market leading position.\n",
- "•Superior capture technology. Matterport’s capture technology platform is a software framework that enables support for a wide variety of capture devices required to create a Matterport digital twin of a building or space.\n",
- "This includes support for LiDAR cameras, 360 cameras, smartphones, Matterport Axis and the Matterport Pro2 and Pro3 cameras. The Pro2 camera was foundational to our spatial data advantage, and we have expanded that advantage with an array of Matterport-enabled third-party capture devices. In August 2022, we launched and began shipment of our Pro3 Camera along with major updates to our industry-leading digital twin cloud platform. The Matterport Pro3 Camera is an advanced 3D capture device, which includes faster boot time, swappable batteries, and a lighter design. The Pro3 camera can perform both indoors and outdoors and is designed for speed, fidelity, versatility and accuracy. Along with our Pro2 Camera, we expect that future sales of our Pro3 Camera will continue to drive increased adoption of our solutions. Matterport is democratizing the 3D capture experience, making high-fidelity and high-accuracy 3D digital twins readily available for any building type and any subscriber need in the property life cycle. While there are other 3D capture solution providers, very few can produce true, dimensionally accurate 3D results, and fewer still can automatically create a final product in photorealistic 3D, and at global scale. This expansive capture technology offering would not be possible without our rich spatial data library available to train the AI-powered Cortex engine to automatically generate accurate digital twins from photos captured with a smartphone or 360 camera.\n",
- "\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"\"\"What was Matterport's subscriber base on the precise date of May 31, 2020?\n",
- "Please read the below document. Then, in tags, pull the most relevant quote from the document and consider whether it answers the user's question or whether it lacks sufficient detail. Then write a brief numerical answer in tags.\n",
- "\n",
- "\n",
- "Matterport SEC filing 10-K 2023\n",
- "Item 1. Business\n",
- "Our Company\n",
- "Matterport is leading the digitization and datafication of the built world. We believe the digital transformation of the built world will fundamentally change the way people interact with buildings and the physical spaces around them.\n",
- "Since its founding in 2011, Matterport’s pioneering technology has set the standard for digitizing, accessing and managing buildings, spaces and places online. Our platform’s innovative software, spatial data-driven data science, and 3D capture technology have broken down the barriers that have kept the largest asset class in the world, buildings and physical spaces, offline and underutilized for many years. We believe the digitization and datafication of the built world will continue to unlock significant operational efficiencies and property values, and that Matterport is the platform to lead this enormous global transformation.\n",
- "The world is rapidly moving from offline to online. Digital transformation has made a powerful and lasting impact across every business and industry today. According to International Data Corporation, or IDC, over $6.8 trillion of direct investments will be made on digital transformation from 2020 to 2023, the global digital transformation spending is forecasted to reach $3.4 trillion in 2026 with a five-year compound annual growth rate (“CAGR”) of 16.3%, and digital twin investments are expected to have a five-year CAGR of 35.2%. With this secular shift, there is also growing demand for the built world to transition from physical to digital. Nevertheless, the vast majority of buildings and spaces remain offline and undigitized. The global building stock, estimated by Savills to be $327 trillion in total property value as of 2021, remains largely offline today, and we estimate that less than 0.1% is penetrated by digital transformation.\n",
- "Matterport was among the first to recognize the increasing need for digitization of the built world and the power of spatial data, the unique details underlying buildings and spaces, in facilitating the understanding of buildings and spaces. In the past, technology advanced physical road maps to the data-rich, digital maps and location services we all rely on today. Matterport now digitizes buildings, creating a data-rich environment to vastly increase our understanding and the full potential of each and every space we capture. Just as we can instantly, at the touch of a button, learn the fastest route from one city to another or locate the nearest coffee shops, Matterport’s spatial data for buildings unlocks a rich set of insights and learnings about properties and spaces worldwide. In addition, just as the geo-spatial mapping platforms of today have opened their mapping data to industry to create new business models such as ridesharing, e-commerce, food delivery marketplaces, and even short-term rental and home sharing, open access to Matterport’s structured spatial data is enabling new opportunities and business models for hospitality, facilities management, insurance, construction, real estate and retail, among others.\n",
- "We believe the total addressable market opportunity for digitizing the built world is over $240 billion, and could be as high as $1 trillion as the market matures at scale. This is based on our analysis, modeling and understanding of the global building stock of over 4 billion properties and 20 billion spaces in the world today. With the help of artificial intelligence (“AI”), machine learning (“ML”) and deep learning (“DL”) technologies, we believe that, with the additional monetization opportunities from powerful spatial data-driven property insights and analytics, the total addressable market for the digitization and datafication of the built world will reach more than $1 trillion.\n",
- "\n",
- "Our spatial data platform and capture of digital twins deliver value across a diverse set of industries and use cases. Large retailers can manage thousands of store locations remotely, real estate agencies can provide virtual open houses for hundreds of properties and thousands of visitors at the same time, property developers can monitor the entirety of the construction process with greater detail and speed, and insurance companies can more precisely document and evaluate claims and underwriting assessments with efficiency and precision. Matterport delivers the critical digital experience, tools and information that matter to our subscribers about properties of virtually any size, shape, and location worldwide.\n",
- "For nearly a decade, we have been growing our spatial data platform and expanding our capabilities in order to create the most detailed, accurate, and data-rich digital twins available. Moreover, our 3D reconstruction process is fully automated, allowing our solution to scale with equal precision to millions of buildings and spaces of any type, shape, and size in the world. The universal applicability of our service provides Matterport significant scale and reach across diverse verticals and any geography. As of December 31, 2022, our subscriber base had grown approximately 39% to over 701,000 subscribers from 503,000 subscribers as of December 31, 2021, with our digital twins reaching more than 170 countries. We have digitized more than 28 billion square feet of space across multiple industries, representing significant scale and growth over the rest of the market.\n",
- "\n",
- "As we continue to transform buildings into data worldwide, we are extending our spatial data platform to further transform property planning, development, management and intelligence for our subscribers across industries to become the de facto building and business intelligence engine for the built world. We believe the demand for spatial data and resulting insights for enterprises, businesses and institutions across industries, including real estate, architecture, engineering and construction (“AEC”), retail, insurance and government, will continue to grow rapidly.\n",
- "We believe digitization and datafication represent a tremendous greenfield opportunity for growth across this massive category and asset class. From the early stages of design and development to marketing, operations, insurance and building repair and maintenance, our platform’s software and technology provide subscribers critical tools and insights to drive cost savings, increase revenues and optimally manage their buildings and spaces. We believe that hundreds of billions of dollars in unrealized utilization and operating efficiencies in the built world can be unlocked through the power of our spatial data platform. Our platform and data solutions have universal applicability across industries and building categories, giving Matterport a significant advantage as we can address the entirety of this large market opportunity and increase the value of what we believe to be the largest asset class in the world.\n",
- "With a demonstrated track record of delivering value to our subscribers, our offerings include software subscription, data licensing, services and product hardware. As of December 31, 2022, our subscriber base included over 24% of Fortune 1000 companies, with less than 10% of our total revenue generated from our top 10 subscribers. We expect more than 80% of our revenue to come from our software subscription and data license solutions by 2025. Our innovative 3D capture products, the Pro2 and Pro3 Cameras, have played an integral part in shaping the 3D building and property visualization ecosystem. The Pro2 and Pro3 Cameras have driven adoption of our solutions and have generated the unique high-quality and scaled data set that has enabled Cortex, our proprietary AI software engine, to become the pioneering engine for digital twin creation. With this data advantage initially spurred by the Pro2 Camera, we have developed a capture device agnostic platform that scales and can generate new building and property insights for our subscribers across industries and geographies.\n",
- "We have recently experienced rapid growth. Our subscribers have grown approximately 49-fold from December 31, 2018 to December 31, 2022. Our revenue increased by approximately 22% to $136.1 million for the year ended December 31, 2022, from approximately $111.2 million for the year ended December 31, 2021. Our gross profit decreased by $8.1 million or 14%, to $51.8 million for the year ended December 31, 2022, from $60.0 million for the year ended December 31, 2021, primarily attributable to certain disruptive and incremental costs due to the global supply chain constraints in fiscal year 2022. Our ability to retain and grow the subscription revenue generated by our existing subscribers is an important measure of the health of our business and our future growth prospects. We track our performance in this area by measuring our net dollar expansion rate from the same set of customers across comparable periods. Our net dollar expansion rate of 103% for the three months ended December 31, 2022 demonstrates the stickiness and growth potential of our platform.\n",
- "Our Industry and Market Opportunity\n",
- "Today, the vast majority of buildings and spaces remain undigitized. We estimate our current serviceable addressable market includes approximately 1.3 billion spaces worldwide, primarily from the real estate and travel and hospitality sectors. With approximately 9.2 million spaces under management as of December 31, 2022, we are continuing to penetrate the global building stock and expand our footprint across various end markets, including residential and commercial real estate, facilities management, retail, AEC, insurance and repair, and travel and hospitality. We estimate our total addressable market to be more than 4 billion buildings and 20 billion spaces globally, yielding a more than $240 billion market opportunity. We believe that as Matterport’s unique spatial data library and property data services continue to grow, this opportunity could increase to more than $1 trillion based on the size of the building stock and the untapped value creation available to buildings worldwide. The constraints created by the COVID-19 pandemic have only reinforced and accelerated the importance of our scaled 3D capture solution that we have developed for diverse industries and markets over the past decade.\n",
- "\n",
- "Our Spatial Data Platform\n",
- "Overview\n",
- "Our technology platform uses spatial data collected from a wide variety of digital capture devices to transform physical buildings and spaces into dimensionally accurate, photorealistic digital twins that provide our subscribers access to previously unavailable building information and insights.\n",
- "As a first mover in this massive market for nearly a decade, we have developed and scaled our industry-leading 3D reconstruction technology powered by Cortex, our proprietary AI-driven software engine that uses machine learning to recreate a photorealistic, 3D virtual representation of an entire building structure, including contents, equipment and furnishings. The finished product is a detailed and dynamic replication of the physical space that can be explored, analyzed and customized from a web browser on any device, including smartphones. The power to manage even large-scale commercial buildings is in the palm of each subscriber’s hands, made possible by our advanced technology and breakthrough innovations across our entire spatial data technology stack.\n",
- "Key elements of our spatial data platform include:\n",
- "•Bringing offline buildings online. Traditionally, our customers needed to conduct in-person site visits to understand and assess their buildings and spaces. While photographs and floor plans can be helpful, these forms of two-dimensional (“2D”) representation have limited information and tend to be static and rigid, and thus lack the interactive element critical to a holistic understanding of each building and space. With the AI-powered capabilities of Cortex, our proprietary AI software, representation of physical objects is no longer confined to static 2D images and physical visits can be eliminated. Cortex helps to move the buildings and spaces from offline to online and makes them accessible to our customers in real-time and on demand from anywhere. After subscribers scan their buildings, our visualization algorithms accurately infer spatial positions and depths from flat, 2D imagery captured through the scans and transform them into high- fidelity and precise digital twin models. This creates a fully automated image processing pipeline to ensure that each digital twin is of professional grade image quality.\n",
- "•Driven by spatial data. We are a data-driven company. Each incremental capture of a space grows the richness and depth of our spatial data library. Spatial data represents the unique and idiosyncratic details that underlie and compose the buildings and spaces in the human- made environment. Cortex uses the breadth of the billions of data points we have accumulated over the years to improve the 3D accuracy of our digital twins. We help our subscribers pinpoint the height, location and other characteristics of objects in their digital twin. Our sophisticated algorithms also deliver significant commercial value to our subscribers by generating data-based insights that allow them to confidently make assessments and decisions about their properties. For instance, property developers can assess the amount of natural heat and daylight coming from specific windows, retailers can ensure each store layout is up to the same level of code and brand requirements, and factories can insure machinery layouts meet specifications and location guidelines. With approximately 9.2 million spaces under management as of December 31, 2022, our spatial data library is the clearinghouse for information about the built world.\n",
- "•Powered by AI and ML. Artificial intelligence and machine learning technologies effectively utilize spatial data to create a robust virtual experience that is dynamic, realistic, interactive, informative and permits multiple viewing angles. AI and ML also make costly cameras unnecessary for everyday scans—subscribers can now scan their spaces by simply tapping a button on their smartphones. As a result, Matterport is a device agnostic platform, helping us more rapidly scale and drive towards our mission of digitizing and indexing the built world.\n",
- "Our value proposition to subscribers is designed to serve the entirety of the digital building lifecycle, from design and build to maintenance and operations, promotion, sale, lease, insure, repair, restore, secure and finance. As a result, we believe we are uniquely positioned to grow our revenue with our subscribers as we help them to discover opportunities to drive short- and long-term return on investment by taking their buildings and spaces from offline to online across their portfolios of properties.\n",
- "Ubiquitous Capture\n",
- "Matterport has become the standard for 3D space capture. Our technology platform empowers subscribers worldwide to quickly, easily and accurately digitize, customize and manage interactive and dimensionally accurate digital twins of their buildings and spaces.\n",
- "The Matterport platform is designed to work with a wide range of LiDAR, spherical, 3D and 360 cameras, as well as smartphones, to suit the capture needs of all of our subscribers. This provides the flexibility to capture a space of any size, scale, and complexity, at anytime and anywhere.\n",
- "•Matterport Pro3 is our newest 3D camera that scans properties faster than earlier versions to help accelerate project completion. Pro3 provides the highest accuracy scans of both indoor and outdoor spaces and is designed for speed, fidelity, versatility and accuracy. Capturing 3D data up to 100 meters away at less than 20 seconds per sweep, Pro3’s ultra-fast, high-precision LiDAR sensor can run for hours and takes millions of measurements in any conditions.\n",
- "•Matterport Pro2 is our proprietary 3D camera that has been used to capture millions of spaces around the world with a high degree of fidelity, precision, speed and simplicity. Capable of capturing buildings more than 500,000 square feet in size, it has become the camera of choice for many residential, commercial, industrial and large-scale properties.\n",
- "•360 Cameras. Matterport supports a selection of 360 cameras available in the market. These affordable, pocket sized devices deliver precision captures with high fidelity and are appropriate for capturing smaller homes, condos, short-term rentals, apartments, and more. The spherical lens image capture technology of these devices gives Cortex robust, detailed image data to transform panoramas into our industry-leading digital twins.\n",
- "•LEICA BLK360. Through our partnership with Leica, our 3D reconstruction technology and our AI powered software engine, Cortex, transform this powerful LiDAR camera into an ultra-precise capture device for creating Matterport digital twins. It is the solution of choice for AEC professionals when exacting precision is required.\n",
- "•Smartphone Capture. Our capture apps are commercially available for both iOS and Android. Matterport’s smartphone capture solution has democratized 3D capture, making it easy and accessible for anyone to digitize buildings and spaces with a recent iPhone device since the initial introduction of Matterport for iPhone in May 2020. In April 2021, we announced the official release of the Android Capture app, giving Android users the ability to quickly and easily capture buildings and spaces in immersive 3D. In February 2022, we launched Matterport Axis, a motorized mount that holds a smartphone and can be used with the Matterport Capture app to capture 3D digital twins of any physical space with increased speed, precision, and consistency.\n",
- "Cortex and 3D Reconstruction (the Matterport Digital Twin)\n",
- "With a spatial data library, as of December 31, 2022, of approximately 9.2 million spaces under management, representing approximately 28 billion captured square feet of space, we use our advanced ML and DL technologies to algorithmically transform the spatial data we capture into an accurate 3D digital reproduction of any physical space. This intelligent, automated 3D reconstruction is made possible by Cortex, our AI-powered software engine that includes a deep learning neural network that uses our spatial data library to understand how a building or space is divided into floors and rooms, where the doorways and openings are located, and what types of rooms are present, such that those forms are compiled and aligned with dimensional accuracy into a dynamic, photorealistic digital twin. Other components of Cortex include AI-powered computer vision technologies to identify and classify the contents inside a building or space, and object recognition technologies to identify and segment everything from furnishings and equipment to doors, windows, light fixtures, fire suppression sprinklers and fire escapes. Our highly scalable artificial intelligence platform enables our subscribers to tap into powerful, enhanced building data and insights at the click of a button.\n",
- "\n",
- "The Science Behind the Matterport Digital Twin: Cortex AI Highlights\n",
- "Matterport Runs on Cortex\n",
- "Cortex is our AI-powered software engine that includes a precision deep learning neural network to create digital twins of any building or space. Developed using our proprietary spatial data captured with our Pro2 and Pro3 cameras, Cortex delivers a high degree of precision and accuracy while enabling 3D capture using everyday devices.\n",
- "Generic neural networks struggle with 3D reconstruction of the real world. Matterport-optimized networks deliver more accurate and robust results. More than just raw training data, Matterport’s datasets allow us to develop new neural network architectures and evaluate them against user behavior and real-world data in millions of situations.\n",
- "•Deep learning: Connecting and optimizing the detailed neural network data architecture of each space is key to creating robust, highly accurate 3D digital twins. Cortex evaluates and optimizes each 3D model against Matterport’s rich spatial data aggregated from millions of buildings and spaces and the human annotations of those data provided by tens of thousands of subscribers worldwide. Cortex’s evaluative abilities and its data-driven optimization of 3D reconstruction yield consistent, high-precision results across a wide array of building configurations, spaces and environments.\n",
- "•Dynamic 3D reconstruction: Creating precise 3D spatial data at scale from 2D visuals and static images requires a combination of photorealistic, detailed data from multiple viewpoints and millions of spaces that train and optimize Cortex’s neural network and learning capabilities for improved 3D reconstruction of any space. Cortex’s capabilities combined with real-time spatial alignment algorithms in our 3D capture technology create an intuitive “preview” of any work in progress, allowing subscribers to work with their content interactively and in real-time.\n",
- "•Computer vision: Cortex enables a suite of powerful features to enhance the value of digital twins. These include automatic measurements for rooms or objects in a room, automatic 2D-from-3D high-definition photo gallery creation, auto face blurring for privacy protection, custom videos, walkthroughs, auto room labeling and object recognition.\n",
- "•Advanced image processing: Matterport’s computational photography algorithms create a fully automated image processing pipeline to help ensure that each digital twin is of professional grade image quality. Our patented technology makes 3D capture as simple as pressing a single button. Matterport’s software and technology manage the remaining steps, including white balance and camera-specific color correction, high dynamic range tone mapping, de-noising, haze removal, sharpening, saturation and other adjustments to improve image quality.\n",
- "Spatial Data and AI-Powered Insights\n",
- "Every Matterport digital twin contains extensive information about a building, room or physical space. The data uses our AI-powered Cortex engine. In addition to the Matterport digital twin itself, our spatial data consists of precision building geometry and structural detail, building contents, fixtures and condition, along with high-definition imagery and photorealistic detail from many vantage points in a space. Cortex employs a technique we call deep spatial indexing. Deep spatial indexing uses artificial intelligence, computer vision and deep learning to identify and convey important details about each space, its structure and its contents with precision and fidelity. We have created a robust spatial data standard that enables Matterport subscribers to harness an interoperable digital system of record for any building.\n",
- "In addition to creating a highly interactive digital experience for subscribers through the construction of digital twins, we ask ourselves two questions for every subscriber: (1) what is important about their building or physical space and (2) what learnings and insights can we deliver for this space? Our AI-powered Cortex engine helps us answer these questions using our spatial data library to provide aggregated property trends and operational and valuation insights. Moreover, as the Matterport platform ecosystem continues to expand, our subscribers, partners and other third-party developers can bring their own tools to further the breadth and depth of insights they can harvest from our rich spatial data layer.\n",
- "Extensible Platform Ecosystem\n",
- "Matterport offers the largest and most accurate library of spatial data in the world, with, as of December 31, 2022, approximately 9.2 million spaces under management and approximately 28 billion captured square feet. The versatility of our spatial data platform and extensive enterprise software development kit and application programming interfaces (“APIs”) has allowed us to develop a robust global ecosystem of channels and partners that extend the Matterport value proposition by geography and vertical market. We intend to continue to deploy a broad set of workflow integrations with our partners and their subscribers to promote an integrated Matterport solution across our target markets. We are also developing a third-party software marketplace to extend the power of our spatial data platform with easy-to-deploy and easy-to-access Matterport software add-ons. The marketplace enables developers to build new applications and spatial data mining tools, enhance the Matterport 3D experience, and create new productivity and property management tools that supplement our core offerings. These value-added capabilities created by third-party developers enable a scalable new revenue stream, with Matterport sharing the subscription and services revenue from each add-on that is deployed to subscribers through the online marketplace. The network effects of our platform ecosystem contributes to the growth of our business, and we believe that it will continue to bolster future growth by enhancing subscriber stickiness and user engagement.\n",
- "Examples of Matterport add-ons and extensions include:\n",
- "•Add-ons: Encircle (easy-to-use field documentation tools for faster claims processing); WP Matterport Shortcode (free Wordpress plugin that allows Matterport to be embedded quickly and easily with a Matterport shortcode), WP3D Models (WordPress + Matterport integration plugin); Rela (all-in-one marketing solution for listings); CAPTUR3D (all-in-one Content Management System that extends value to Matterport digital twins); Private Model Emded (feature that allows enterprises to privately share digital twins with a large group of employees on the corporate network without requiring additional user licenses); Views (new workgroup collaboration framework to enable groups and large organizations to create separate, permissions-based workflows to manage different tasks with different teams); and Guided Tours and Tags (tool to elevate the visitor experience by creating directed virtual tours of any commercial or residential space tailored to the interests of their visitors). We unveiled our private beta integration with Amazon Web Services (AWS) IoT TwinMaker to enable enterprise customers to seamlessly connect IoT data into visually immersive and dimensionally accurate Matterport digital twin.\n",
- "•Services: Matterport ADA Compliant Digital Twin (solution to provide American Disability Act compliant digital twins) and Enterprise Cloud Software Platform (reimagined cloud software platform for the enterprise that creates, publishes, and manages digital twins of buildings and spaces of any size of shape, indoors or outdoors).\n",
- "Our Competitive Strengths\n",
- "We believe that we have a number of competitive strengths that will enable our market leadership to grow. Our competitive strengths include:\n",
- "•Breadth and depth of the Matterport platform. Our core strength is our all-in-one spatial data platform with broad reach across diverse verticals and geographies such as capture to processing to industries without customization. With the ability to integrate seamlessly with various enterprise systems, our platform delivers value across the property lifecycle for diverse end markets, including real estate, AEC, travel and hospitality, repair and insurance, and industrial and facilities. As of December 31, 2022, our global reach extended to subscribers in more than 170 countries, including over 24% of Fortune 1000 companies.\n",
- "•Market leadership and first-mover advantage. Matterport defined the category of digitizing and datafying the built world almost a decade ago, and we have become the global leader in the category. As of December 31, 2022, we had over 701,000 subscribers on our platform and approximately 9.2 million spaces under management. Our leadership is primarily driven by the fact that we were the first mover in digital twin creation. As a result of our first mover advantage, we have amassed a deep and rich library of spatial data that continues to compound and enhance our leadership position.\n",
- "•Significant network effect. With each new capture and piece of data added to our platform, the richness of our dataset and the depth of insights from our spaces under management grow. In addition, the combination of our ability to turn data into insights with incremental data from new data captures by our subscribers enables Matterport to develop features for subscribers to our platform. We were a first mover in building a spatial data library for the built world, and our leadership in gathering and deriving insights from data continues to compound and the relevance of those insights attracts more new subscribers.\n",
- "•Massive spatial data library as the raw material for valuable property insights. The scale of our spatial data library is a significant advantage in deriving insights for our subscribers. Our spatial data library serves as vital ground truth for Cortex, enabling Matterport to create powerful 3D digital twins using a wide range of camera technology, including low-cost digital and smartphone cameras. As of December 31, 2022, our data came from approximately 9.2 million spaces under management and approximately 28 billion captured square feet. As a result, we have taken property insights and analytics to new levels, benefiting subscribers across various industries. For example, facilities managers significantly reduce the time needed to create building layouts, leading to a significant decrease in the cost of site surveying and as-built modeling. AEC subscribers use the analytics of each as-built space to streamline documentation and collaborate with ease.\n",
- "•Global reach and scale. We are focused on continuing to expand our AI-powered spatial data platform worldwide. We have a significant presence in North America, Europe and Asia, with leadership teams and a go-to-market infrastructure in each of these regions. We have offices in London, Singapore and several across the United States, and we are accelerating our international expansion. As of December 31, 2022, we had over 701,000 subscribers in more than 170 countries. We believe that the geography-agnostic nature of our spatial data platform is a significant advantage as we continue to grow internationally.\n",
- "•Broad patent portfolio supporting 10 years of R&D and innovation. As of December 31, 2022, we had 54 issued and 37 pending patent applications. Our success is based on almost 10 years of focus on innovation. Innovation has been at the center of Matterport, and we will continue to prioritize our investments in R&D to further our market leading position.\n",
- "•Superior capture technology. Matterport’s capture technology platform is a software framework that enables support for a wide variety of capture devices required to create a Matterport digital twin of a building or space.\n",
- "This includes support for LiDAR cameras, 360 cameras, smartphones, Matterport Axis and the Matterport Pro2 and Pro3 cameras. The Pro2 camera was foundational to our spatial data advantage, and we have expanded that advantage with an array of Matterport-enabled third-party capture devices. In August 2022, we launched and began shipment of our Pro3 Camera along with major updates to our industry-leading digital twin cloud platform. The Matterport Pro3 Camera is an advanced 3D capture device, which includes faster boot time, swappable batteries, and a lighter design. The Pro3 camera can perform both indoors and outdoors and is designed for speed, fidelity, versatility and accuracy. Along with our Pro2 Camera, we expect that future sales of our Pro3 Camera will continue to drive increased adoption of our solutions. Matterport is democratizing the 3D capture experience, making high-fidelity and high-accuracy 3D digital twins readily available for any building type and any subscriber need in the property life cycle. While there are other 3D capture solution providers, very few can produce true, dimensionally accurate 3D results, and fewer still can automatically create a final product in photorealistic 3D, and at global scale. This expansive capture technology offering would not be possible without our rich spatial data library available to train the AI-powered Cortex engine to automatically generate accurate digital twins from photos captured with a smartphone or 360 camera.\n",
- "\"\"\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/09_Complex_Prompts_from_Scratch.ipynb b/AmazonBedrock/anthropic/09_Complex_Prompts_from_Scratch.ipynb
deleted file mode 100755
index eecdf3c..0000000
--- a/AmazonBedrock/anthropic/09_Complex_Prompts_from_Scratch.ipynb
+++ /dev/null
@@ -1,1225 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 9: Complex Prompts from Scratch\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt, system='', prefill=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=[\n",
- " {\"role\": \"user\", \"content\": prompt},\n",
- " {\"role\": \"assistant\", \"content\": prefill}\n",
- " ],\n",
- " system=system\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "Congratulations on making it to the last chapter! Now time to put everything together and learn how to **create unique and complex prompts**. \n",
- "\n",
- "Below, you will be using a **guided structure that we recommend for complex prompts**. In latter parts of this chapter, we will show you some industry-specific prompts and explain how those prompts are similarly structured.\n",
- "\n",
- "**Note:** **Not all prompts need every element of the following complex structure**. We encourage you to play around with and include or disinclude elements and see how it affects Claude's response. It is usually **best to use many prompt elements to get your prompt working first, then refine and slim down your prompt afterward**."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example - Career Coach Chatbot\n",
- "\n",
- "The following structure combines multiple prompt engineering elements and is a good starting point for complex prompts. **The ordering matters for some elements**, not for others. We will note when best practices indicate ordering matters, but in general, **if you stick to this ordering, it will be a good start to a stellar prompt**.\n",
- "\n",
- "For the following example, we will be building a prompt for a controlled roleplay wherein Claude takes on a situational role with a specific task. Our goal is to prompt Claude to act as a friendly career coach.\n",
- "\n",
- "Read then run the cell below to compile the various prompt elements into one whole prompt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "######################################## INPUT VARIABLES ########################################\n",
- "\n",
- "# First input variable - the conversation history (this can also be added as preceding `user` and `assistant` messages in the API call)\n",
- "HISTORY = \"\"\"Customer: Give me two possible careers for sociology majors.\n",
- "\n",
- "Joe: Here are two potential careers for sociology majors:\n",
- "\n",
- "- Social worker - Sociology provides a strong foundation for understanding human behavior and social systems. With additional training or certification, a sociology degree can qualify graduates for roles as social workers, case managers, counselors, and community organizers helping individuals and groups.\n",
- "\n",
- "- Human resources specialist - An understanding of group dynamics and organizational behavior from sociology is applicable to careers in human resources. Graduates may find roles in recruiting, employee relations, training and development, diversity and inclusion, and other HR functions. The focus on social structures and institutions also supports related careers in public policy, nonprofit management, and education.\"\"\"\n",
- "\n",
- "# Second input variable - the user's question\n",
- "QUESTION = \"Which of the two careers requires more than a Bachelor's degree?\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## PROMPT ELEMENTS ########################################\n",
- "\n",
- "##### Prompt element 1: `user` role\n",
- "# Make sure that your Messages API call always starts with a `user` role in the messages array.\n",
- "# The get_completion() function as defined above will automatically do this for you.\n",
- "\n",
- "##### Prompt element 2: Task context\n",
- "# Give Claude context about the role it should take on or what goals and overarching tasks you want it to undertake with the prompt.\n",
- "# It's best to put context early in the body of the prompt.\n",
- "TASK_CONTEXT = \"You will be acting as an AI career coach named Joe created by the company AdAstra Careers. Your goal is to give career advice to users. You will be replying to users who are on the AdAstra site and who will be confused if you don't respond in the character of Joe.\"\n",
- "\n",
- "##### Prompt element 3: Tone context\n",
- "# If important to the interaction, tell Claude what tone it should use.\n",
- "# This element may not be necessary depending on the task.\n",
- "TONE_CONTEXT = \"You should maintain a friendly customer service tone.\"\n",
- "\n",
- "##### Prompt element 4: Detailed task description and rules\n",
- "# Expand on the specific tasks you want Claude to do, as well as any rules that Claude might have to follow.\n",
- "# This is also where you can give Claude an \"out\" if it doesn't have an answer or doesn't know.\n",
- "# It's ideal to show this description and rules to a friend to make sure it is laid out logically and that any ambiguous words are clearly defined.\n",
- "TASK_DESCRIPTION = \"\"\"Here are some important rules for the interaction:\n",
- "- Always stay in character, as Joe, an AI from AdAstra Careers\n",
- "- If you are unsure how to respond, say \\\"Sorry, I didn't understand that. Could you rephrase your question?\\\"\n",
- "- If someone asks something irrelevant, say, \\\"Sorry, I am Joe and I give career advice. Do you have a career question today I can help you with?\\\"\"\"\"\n",
- "\n",
- "##### Prompt element 5: Examples\n",
- "# Provide Claude with at least one example of an ideal response that it can emulate. Encase this in XML tags. Feel free to provide multiple examples.\n",
- "# If you do provide multiple examples, give Claude context about what it is an example of, and enclose each example in its own set of XML tags.\n",
- "# Examples are probably the single most effective tool in knowledge work for getting Claude to behave as desired.\n",
- "# Make sure to give Claude examples of common edge cases. If your prompt uses a scratchpad, it's effective to give examples of how the scratchpad should look.\n",
- "# Generally more examples = better.\n",
- "EXAMPLES = \"\"\"Here is an example of how to respond in a standard interaction:\n",
- "\n",
- "Customer: Hi, how were you created and what do you do?\n",
- "Joe: Hello! My name is Joe, and I was created by AdAstra Careers to give career advice. What can I help you with today?\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 6: Input data to process\n",
- "# If there is data that Claude needs to process within the prompt, include it here within relevant XML tags.\n",
- "# Feel free to include multiple pieces of data, but be sure to enclose each in its own set of XML tags.\n",
- "# This element may not be necessary depending on task. Ordering is also flexible.\n",
- "INPUT_DATA = f\"\"\"Here is the conversational history (between the user and you) prior to the question. It could be empty if there is no history:\n",
- "\n",
- "{HISTORY}\n",
- "\n",
- "\n",
- "Here is the user's question:\n",
- "\n",
- "{QUESTION}\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 7: Immediate task description or request #####\n",
- "# \"Remind\" Claude or tell Claude exactly what it's expected to immediately do to fulfill the prompt's task.\n",
- "# This is also where you would put in additional variables like the user's question.\n",
- "# It generally doesn't hurt to reiterate to Claude its immediate task. It's best to do this toward the end of a long prompt.\n",
- "# This will yield better results than putting this at the beginning.\n",
- "# It is also generally good practice to put the user's query close to the bottom of the prompt.\n",
- "IMMEDIATE_TASK = \"How do you respond to the user's question?\"\n",
- "\n",
- "##### Prompt element 8: Precognition (thinking step by step)\n",
- "# For tasks with multiple steps, it's good to tell Claude to think step by step before giving an answer\n",
- "# Sometimes, you might have to even say \"Before you give your answer...\" just to make sure Claude does this first.\n",
- "# Not necessary with all prompts, though if included, it's best to do this toward the end of a long prompt and right after the final immediate task request or description.\n",
- "PRECOGNITION = \"Think about your answer first before you respond.\"\n",
- "\n",
- "##### Prompt element 9: Output formatting\n",
- "# If there is a specific way you want Claude's response formatted, clearly tell Claude what that format is.\n",
- "# This element may not be necessary depending on the task.\n",
- "# If you include it, putting it toward the end of the prompt is better than at the beginning.\n",
- "OUTPUT_FORMATTING = \"Put your response in tags.\"\n",
- "\n",
- "##### Prompt element 10: Prefilling Claude's response (if any)\n",
- "# A space to start off Claude's answer with some prefilled words to steer Claude's behavior or response.\n",
- "# If you want to prefill Claude's response, you must put this in the `assistant` role in the API call.\n",
- "# This element may not be necessary depending on the task.\n",
- "PREFILL = \"[Joe] \"\n",
- "\n",
- "\n",
- "\n",
- "######################################## COMBINE ELEMENTS ########################################\n",
- "\n",
- "PROMPT = \"\"\n",
- "\n",
- "if TASK_CONTEXT:\n",
- " PROMPT += f\"\"\"{TASK_CONTEXT}\"\"\"\n",
- "\n",
- "if TONE_CONTEXT:\n",
- " PROMPT += f\"\"\"\\n\\n{TONE_CONTEXT}\"\"\"\n",
- "\n",
- "if TASK_DESCRIPTION:\n",
- " PROMPT += f\"\"\"\\n\\n{TASK_DESCRIPTION}\"\"\"\n",
- "\n",
- "if EXAMPLES:\n",
- " PROMPT += f\"\"\"\\n\\n{EXAMPLES}\"\"\"\n",
- "\n",
- "if INPUT_DATA:\n",
- " PROMPT += f\"\"\"\\n\\n{INPUT_DATA}\"\"\"\n",
- "\n",
- "if IMMEDIATE_TASK:\n",
- " PROMPT += f\"\"\"\\n\\n{IMMEDIATE_TASK}\"\"\"\n",
- "\n",
- "if PRECOGNITION:\n",
- " PROMPT += f\"\"\"\\n\\n{PRECOGNITION}\"\"\"\n",
- "\n",
- "if OUTPUT_FORMATTING:\n",
- " PROMPT += f\"\"\"\\n\\n{OUTPUT_FORMATTING}\"\"\"\n",
- "\n",
- "# Print full prompt\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's run the prompt! Run the cell below to see Claude's output."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example - Legal Services\n",
- "\n",
- "**Prompts within the legal profession can be quite complex** due to the need to:\n",
- "- Parse long documents\n",
- "- Deal with complex topics\n",
- "- Format output in very specific ways\n",
- "- Follow multi-step analytical processes\n",
- "\n",
- "Let's see how we can use the complex prompt template to structure a prompt for a specific legal use-case. Below, we've detailed out an example prompt for a legal use-case wherein we ask Claude to answer questions about a legal issue using information from a legal document.\n",
- "\n",
- "We've **changed around the ordering of a few elements** to showcase that prompt structure can be flexible!\n",
- "\n",
- "**Prompt engineering is about scientific trial and error**. We encourage you to mix and match, move things around (the elements where ordering doesn't matter), and see what works best for you and your needs. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "######################################## INPUT VARIABLES ########################################\n",
- "\n",
- "# First input variable - the legal document\n",
- "LEGAL_RESEARCH = \"\"\"\n",
- "\n",
- "The animal health industry became caught up in a number of patent and trademark lawsuits during the past year. In 1994, Barclay Slocum obtained patents for the tibial plateau leveling osteotomy procedure, which is used in the treatment of dogs with cranial cruciate ligament rupture, and for the devices used in the procedure. During 2006, Slocum Enterprises filed a patent infringement suit against New Generation Devices, arguing that the Unity Cruciate Plate manufactured by New Generation infringed on the patent for the Slocum TPLO plate. However, the court never reached a decision on the issue of patent infringement, ruling that it did not have jurisdiction on the basis of the small number of plates sold in the state in which the case was filed and the information provided on a Web site maintained by Slocum Enterprises. Other patent battles waged during 2006 concerned the use of laser technology for onychectomy in cats, pet identification chips, pig vaccines, and pet “deshedding” tools.\n",
- "\n",
- "\n",
- "In Canada, the British Columbia Veterinary Medical Association brought suit against a nonveterinarian, claiming that he engaged in cutting or otherwise removing hooks from horses' teeth and floating horses' teeth with power and manual tools, provided advice and diagnoses in return for a fee, and held himself out as being qualified and willing to provide treatment with respect to these activities. The court held that the intention of the legislature in passing the Veterinary Profession Act was the protection of the public and animals and further held that monopolistic statutes serve the purpose of protecting the public. In addition, the court concluded that dentistry, at its core, relates to the health of the teeth and gums; is distinct from cosmetic and other types of care of animals; and, therefore, falls under the definition of the practice of veterinary medicine. The nonveterinarian was enjoined from providing services without a veterinarian supervising the procedures.\n",
- "\n",
- "\n",
- "The aftermath of Hurricane Katrina, which hit the Gulf Coast of the United States during 2005, spurred changes to the way animals are treated during natural disasters. In 2006, Hawaii, Louisiana, and New Hampshire all enacted laws that address issues regarding the care of animals during disasters, such as providing shelters for pets and allowing service animals to be kept with the people they serve. In addition, Congress passed, and the President signed, the Pet Evacuation and Transportation Standards Act during 2006, which requires state and local emergency preparedness authorities to include in their evacuation plans information on how they will accommodate household pets and service animals in case of a disaster. California passed a law that will require its Office of Emergency Services, Department of Agriculture, and other agencies involved with disaster response preparation to develop a plan for the needs of service animals, livestock, equids, and household pets in the event of a disaster or major emergency.\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "# Second input variable - the user's question\n",
- "QUESTION = \"Are there any laws about what to do with pets during a hurricane?\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## PROMPT ELEMENTS ########################################\n",
- "\n",
- "##### Prompt element 1: `user` role\n",
- "# Make sure that your Messages API call always starts with a `user` role in the messages array.\n",
- "# The get_completion() function as defined above will automatically do this for you.\n",
- "\n",
- "##### Prompt element 2: Task context\n",
- "# Give Claude context about the role it should take on or what goals and overarching tasks you want it to undertake with the prompt.\n",
- "# It's best to put context early in the body of the prompt.\n",
- "TASK_CONTEXT = \"You are an expert lawyer.\"\n",
- "\n",
- "##### Prompt element 3: Tone context\n",
- "# If important to the interaction, tell Claude what tone it should use.\n",
- "# This element may not be necessary depending on the task.\n",
- "TONE_CONTEXT = \"\"\n",
- "\n",
- "##### Prompt element 4: Input data to process\n",
- "# If there is data that Claude needs to process within the prompt, include it here within relevant XML tags.\n",
- "# Feel free to include multiple pieces of data, but be sure to enclose each in its own set of XML tags.\n",
- "# This element may not be necessary depending on task. Ordering is also flexible.\n",
- "INPUT_DATA = f\"\"\"Here is some research that's been compiled. Use it to answer a legal question from the user.\n",
- "\n",
- "{LEGAL_RESEARCH}\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 5: Examples\n",
- "# Provide Claude with at least one example of an ideal response that it can emulate. Encase this in XML tags. Feel free to provide multiple examples.\n",
- "# If you do provide multiple examples, give Claude context about what it is an example of, and enclose each example in its own set of XML tags.\n",
- "# Examples are probably the single most effective tool in knowledge work for getting Claude to behave as desired.\n",
- "# Make sure to give Claude examples of common edge cases. If your prompt uses a scratchpad, it's effective to give examples of how the scratchpad should look.\n",
- "# Generally more examples = better.\n",
- "EXAMPLES = \"\"\"When citing the legal research in your answer, please use brackets containing the search index ID, followed by a period. Put these at the end of the sentence that's doing the citing. Examples of proper citation format:\n",
- "\n",
- "\n",
- "\n",
- "The statute of limitations expires after 10 years for crimes like this. [3].\n",
- "\n",
- "\n",
- "However, the protection does not apply when it has been specifically waived by both parties. [5].\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 6: Detailed task description and rules\n",
- "# Expand on the specific tasks you want Claude to do, as well as any rules that Claude might have to follow.\n",
- "# This is also where you can give Claude an \"out\" if it doesn't have an answer or doesn't know.\n",
- "# It's ideal to show this description and rules to a friend to make sure it is laid out logically and that any ambiguous words are clearly defined.\n",
- "TASK_DESCRIPTION = \"\"\"Write a clear, concise answer to this question:\n",
- "\n",
- "\n",
- "{QUESTION}\n",
- "\n",
- "\n",
- "It should be no more than a couple of paragraphs. If possible, it should conclude with a single sentence directly answering the user's question. However, if there is not sufficient information in the compiled research to produce such an answer, you may demur and write \"Sorry, I do not have sufficient information at hand to answer this question.\".\"\"\"\n",
- "\n",
- "##### Prompt element 7: Immediate task description or request #####\n",
- "# \"Remind\" Claude or tell Claude exactly what it's expected to immediately do to fulfill the prompt's task.\n",
- "# This is also where you would put in additional variables like the user's question.\n",
- "# It generally doesn't hurt to reiterate to Claude its immediate task. It's best to do this toward the end of a long prompt.\n",
- "# This will yield better results than putting this at the beginning.\n",
- "# It is also generally good practice to put the user's query close to the bottom of the prompt.\n",
- "IMMEDIATE_TASK = \"\"\n",
- "\n",
- "##### Prompt element 8: Precognition (thinking step by step)\n",
- "# For tasks with multiple steps, it's good to tell Claude to think step by step before giving an answer\n",
- "# Sometimes, you might have to even say \"Before you give your answer...\" just to make sure Claude does this first.\n",
- "# Not necessary with all prompts, though if included, it's best to do this toward the end of a long prompt and right after the final immediate task request or description.\n",
- "PRECOGNITION = \"Before you answer, pull out the most relevant quotes from the research in tags.\"\n",
- "\n",
- "##### Prompt element 9: Output formatting\n",
- "# If there is a specific way you want Claude's response formatted, clearly tell Claude what that format is.\n",
- "# This element may not be necessary depending on the task.\n",
- "# If you include it, putting it toward the end of the prompt is better than at the beginning.\n",
- "OUTPUT_FORMATTING = \"Put your two-paragraph response in tags.\"\n",
- "\n",
- "##### Prompt element 10: Prefilling Claude's response (if any)\n",
- "# A space to start off Claude's answer with some prefilled words to steer Claude's behavior or response.\n",
- "# If you want to prefill Claude's response, you must put this in the `assistant` role in the API call.\n",
- "# This element may not be necessary depending on the task.\n",
- "PREFILL = \"\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## COMBINE ELEMENTS ########################################\n",
- "\n",
- "PROMPT = \"\"\n",
- "\n",
- "if TASK_CONTEXT:\n",
- " PROMPT += f\"\"\"{TASK_CONTEXT}\"\"\"\n",
- "\n",
- "if TONE_CONTEXT:\n",
- " PROMPT += f\"\"\"\\n\\n{TONE_CONTEXT}\"\"\"\n",
- "\n",
- "if INPUT_DATA:\n",
- " PROMPT += f\"\"\"\\n\\n{INPUT_DATA}\"\"\"\n",
- "\n",
- "if EXAMPLES:\n",
- " PROMPT += f\"\"\"\\n\\n{EXAMPLES}\"\"\"\n",
- "\n",
- "if TASK_DESCRIPTION:\n",
- " PROMPT += f\"\"\"\\n\\n{TASK_DESCRIPTION}\"\"\"\n",
- "\n",
- "if IMMEDIATE_TASK:\n",
- " PROMPT += f\"\"\"\\n\\n{IMMEDIATE_TASK}\"\"\"\n",
- "\n",
- "if PRECOGNITION:\n",
- " PROMPT += f\"\"\"\\n\\n{PRECOGNITION}\"\"\"\n",
- "\n",
- "if OUTPUT_FORMATTING:\n",
- " PROMPT += f\"\"\"\\n\\n{OUTPUT_FORMATTING}\"\"\"\n",
- "\n",
- "# Print full prompt\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's run the prompt! Run the cell below to see Claude's output."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 9.1 - Financial Services Chatbot](#exercise-91---financial-services-chatbot)\n",
- "- [Exercise 9.2 - Codebot](#exercise-92---codebot)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 9.1 - Financial Services Chatbot\n",
- "Prompts within the financial profession can also be quite complex due to reasons similar to legal prompts. Here's an exercise for a financial use-case, wherein Claude is used to **analyze tax information and answer questions**. Just like with the legal services example, we've changed around the ordering of a few elements, as our solution prompt makes more sense with a different flow (however, other structures would also work).\n",
- "\n",
- "We suggest you read through the variable content (in this case, `{QUESTION}` and `{TAX_CODE}`) to understand what content Claude is expected to work with. Be sure to reference `{QUESTION}` and `{TAX_CODE}` directly in your prompt somewhere (using f-string syntax like in the other examples) so that the actual variable content can be substituted in.\n",
- "\n",
- "Fill in the prompt element fields with content that match the description and the examples you've seen in the preceding examples of complex prompts. Once you have filled out all the prompt elements that you want to fill out, run the cell to see the concatenated prompt as well as Claude's response.\n",
- "\n",
- "Remember that prompt engineering is rarely purely formulaic, especially for large and complex prompts! It's important to develop test cases and **try a variety of prompts and prompt structures to see what works best for each situation**. Note that if you *do* change the ordering of the prompt elements, you should also remember to change the ordering of the concatenaton in the `COMBINE ELEMENTS` section."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "######################################## INPUT VARIABLES ########################################\n",
- "\n",
- "# First input variable - the user's question\n",
- "QUESTION = \"How long do I have to make an 83b election?\"\n",
- "\n",
- "# Second input variable - the tax code document that Claude will be using to answer the user's question\n",
- "TAX_CODE = \"\"\"\n",
- "(a)General rule\n",
- "If, in connection with the performance of services, property is transferred to any person other than the person for whom such services are performed, the excess of—\n",
- "(1)the fair market value of such property (determined without regard to any restriction other than a restriction which by its terms will never lapse) at the first time the rights of the person having the beneficial interest in such property are transferable or are not subject to a substantial risk of forfeiture, whichever occurs earlier, over\n",
- "(2)the amount (if any) paid for such property,\n",
- "shall be included in the gross income of the person who performed such services in the first taxable year in which the rights of the person having the beneficial interest in such property are transferable or are not subject to a substantial risk of forfeiture, whichever is applicable. The preceding sentence shall not apply if such person sells or otherwise disposes of such property in an arm’s length transaction before his rights in such property become transferable or not subject to a substantial risk of forfeiture.\n",
- "(b)Election to include in gross income in year of transfer\n",
- "(1)In general\n",
- "Any person who performs services in connection with which property is transferred to any person may elect to include in his gross income for the taxable year in which such property is transferred, the excess of—\n",
- "(A)the fair market value of such property at the time of transfer (determined without regard to any restriction other than a restriction which by its terms will never lapse), over\n",
- "(B)the amount (if any) paid for such property.\n",
- "If such election is made, subsection (a) shall not apply with respect to the transfer of such property, and if such property is subsequently forfeited, no deduction shall be allowed in respect of such forfeiture.\n",
- "(2)Election\n",
- "An election under paragraph (1) with respect to any transfer of property shall be made in such manner as the Secretary prescribes and shall be made not later than 30 days after the date of such transfer. Such election may not be revoked except with the consent of the Secretary.\n",
- "\n",
- "(c)Special rules\n",
- "For purposes of this section—\n",
- "(1)Substantial risk of forfeiture\n",
- "The rights of a person in property are subject to a substantial risk of forfeiture if such person’s rights to full enjoyment of such property are conditioned upon the future performance of substantial services by any individual.\n",
- "\n",
- "(2)Transferability of property\n",
- "The rights of a person in property are transferable only if the rights in such property of any transferee are not subject to a substantial risk of forfeiture.\n",
- "\n",
- "(3)Sales which may give rise to suit under section 16(b) of the Securities Exchange Act of 1934\n",
- "So long as the sale of property at a profit could subject a person to suit under section 16(b) of the Securities Exchange Act of 1934, such person’s rights in such property are—\n",
- "(A)subject to a substantial risk of forfeiture, and\n",
- "(B)not transferable.\n",
- "(4)For purposes of determining an individual’s basis in property transferred in connection with the performance of services, rules similar to the rules of section 72(w) shall apply.\n",
- "(d)Certain restrictions which will never lapse\n",
- "(1)Valuation\n",
- "In the case of property subject to a restriction which by its terms will never lapse, and which allows the transferee to sell such property only at a price determined under a formula, the price so determined shall be deemed to be the fair market value of the property unless established to the contrary by the Secretary, and the burden of proof shall be on the Secretary with respect to such value.\n",
- "\n",
- "(2)Cancellation\n",
- "If, in the case of property subject to a restriction which by its terms will never lapse, the restriction is canceled, then, unless the taxpayer establishes—\n",
- "(A)that such cancellation was not compensatory, and\n",
- "(B)that the person, if any, who would be allowed a deduction if the cancellation were treated as compensatory, will treat the transaction as not compensatory, as evidenced in such manner as the Secretary shall prescribe by regulations,\n",
- "the excess of the fair market value of the property (computed without regard to the restrictions) at the time of cancellation over the sum of—\n",
- "(C)the fair market value of such property (computed by taking the restriction into account) immediately before the cancellation, and\n",
- "(D)the amount, if any, paid for the cancellation,\n",
- "shall be treated as compensation for the taxable year in which such cancellation occurs.\n",
- "(e)Applicability of section\n",
- "This section shall not apply to—\n",
- "(1)a transaction to which section 421 applies,\n",
- "(2)a transfer to or from a trust described in section 401(a) or a transfer under an annuity plan which meets the requirements of section 404(a)(2),\n",
- "(3)the transfer of an option without a readily ascertainable fair market value,\n",
- "(4)the transfer of property pursuant to the exercise of an option with a readily ascertainable fair market value at the date of grant, or\n",
- "(5)group-term life insurance to which section 79 applies.\n",
- "(f)Holding period\n",
- "In determining the period for which the taxpayer has held property to which subsection (a) applies, there shall be included only the period beginning at the first time his rights in such property are transferable or are not subject to a substantial risk of forfeiture, whichever occurs earlier.\n",
- "\n",
- "(g)Certain exchanges\n",
- "If property to which subsection (a) applies is exchanged for property subject to restrictions and conditions substantially similar to those to which the property given in such exchange was subject, and if section 354, 355, 356, or 1036 (or so much of section 1031 as relates to section 1036) applied to such exchange, or if such exchange was pursuant to the exercise of a conversion privilege—\n",
- "(1)such exchange shall be disregarded for purposes of subsection (a), and\n",
- "(2)the property received shall be treated as property to which subsection (a) applies.\n",
- "(h)Deduction by employer\n",
- "In the case of a transfer of property to which this section applies or a cancellation of a restriction described in subsection (d), there shall be allowed as a deduction under section 162, to the person for whom were performed the services in connection with which such property was transferred, an amount equal to the amount included under subsection (a), (b), or (d)(2) in the gross income of the person who performed such services. Such deduction shall be allowed for the taxable year of such person in which or with which ends the taxable year in which such amount is included in the gross income of the person who performed such services.\n",
- "\n",
- "(i)Qualified equity grants\n",
- "(1)In general\n",
- "For purposes of this subtitle—\n",
- "(A)Timing of inclusion\n",
- "If qualified stock is transferred to a qualified employee who makes an election with respect to such stock under this subsection, subsection (a) shall be applied by including the amount determined under such subsection with respect to such stock in income of the employee in the taxable year determined under subparagraph (B) in lieu of the taxable year described in subsection (a).\n",
- "\n",
- "(B)Taxable year determined\n",
- "The taxable year determined under this subparagraph is the taxable year of the employee which includes the earliest of—\n",
- "(i)the first date such qualified stock becomes transferable (including, solely for purposes of this clause, becoming transferable to the employer),\n",
- "(ii)the date the employee first becomes an excluded employee,\n",
- "(iii)the first date on which any stock of the corporation which issued the qualified stock becomes readily tradable on an established securities market (as determined by the Secretary, but not including any market unless such market is recognized as an established securities market by the Secretary for purposes of a provision of this title other than this subsection),\n",
- "(iv)the date that is 5 years after the first date the rights of the employee in such stock are transferable or are not subject to a substantial risk of forfeiture, whichever occurs earlier, or\n",
- "(v)the date on which the employee revokes (at such time and in such manner as the Secretary provides) the election under this subsection with respect to such stock.\n",
- "(2)Qualified stock\n",
- "(A)In general\n",
- "For purposes of this subsection, the term “qualified stock” means, with respect to any qualified employee, any stock in a corporation which is the employer of such employee, if—\n",
- "(i)such stock is received—\n",
- "(I)in connection with the exercise of an option, or\n",
- "(II)in settlement of a restricted stock unit, and\n",
- "(ii)such option or restricted stock unit was granted by the corporation—\n",
- "(I)in connection with the performance of services as an employee, and\n",
- "(II)during a calendar year in which such corporation was an eligible corporation.\n",
- "(B)Limitation\n",
- "The term “qualified stock” shall not include any stock if the employee may sell such stock to, or otherwise receive cash in lieu of stock from, the corporation at the time that the rights of the employee in such stock first become transferable or not subject to a substantial risk of forfeiture.\n",
- "\n",
- "(C)Eligible corporation\n",
- "For purposes of subparagraph (A)(ii)(II)—\n",
- "(i)In general\n",
- "The term “eligible corporation” means, with respect to any calendar year, any corporation if—\n",
- "(I)no stock of such corporation (or any predecessor of such corporation) is readily tradable on an established securities market (as determined under paragraph (1)(B)(iii)) during any preceding calendar year, and\n",
- "(II)such corporation has a written plan under which, in such calendar year, not less than 80 percent of all employees who provide services to such corporation in the United States (or any possession of the United States) are granted stock options, or are granted restricted stock units, with the same rights and privileges to receive qualified stock.\n",
- "(ii)Same rights and privileges\n",
- "For purposes of clause (i)(II)—\n",
- "(I)except as provided in subclauses (II) and (III), the determination of rights and privileges with respect to stock shall be made in a similar manner as under section 423(b)(5),\n",
- "(II)employees shall not fail to be treated as having the same rights and privileges to receive qualified stock solely because the number of shares available to all employees is not equal in amount, so long as the number of shares available to each employee is more than a de minimis amount, and\n",
- "(III)rights and privileges with respect to the exercise of an option shall not be treated as the same as rights and privileges with respect to the settlement of a restricted stock unit.\n",
- "(iii)Employee\n",
- "For purposes of clause (i)(II), the term “employee” shall not include any employee described in section 4980E(d)(4) or any excluded employee.\n",
- "\n",
- "(iv)Special rule for calendar years before 2018\n",
- "In the case of any calendar year beginning before January 1, 2018, clause (i)(II) shall be applied without regard to whether the rights and privileges with respect to the qualified stock are the same.\n",
- "\n",
- "(3)Qualified employee; excluded employee\n",
- "For purposes of this subsection—\n",
- "(A)In general\n",
- "The term “qualified employee” means any individual who—\n",
- "(i)is not an excluded employee, and\n",
- "(ii)agrees in the election made under this subsection to meet such requirements as are determined by the Secretary to be necessary to ensure that the withholding requirements of the corporation under chapter 24 with respect to the qualified stock are met.\n",
- "(B)Excluded employee\n",
- "The term “excluded employee” means, with respect to any corporation, any individual—\n",
- "(i)who is a 1-percent owner (within the meaning of section 416(i)(1)(B)(ii)) at any time during the calendar year or who was such a 1 percent owner at any time during the 10 preceding calendar years,\n",
- "(ii)who is or has been at any prior time—\n",
- "(I)the chief executive officer of such corporation or an individual acting in such a capacity, or\n",
- "(II)the chief financial officer of such corporation or an individual acting in such a capacity,\n",
- "(iii)who bears a relationship described in section 318(a)(1) to any individual described in subclause (I) or (II) of clause (ii), or\n",
- "(iv)who is one of the 4 highest compensated officers of such corporation for the taxable year, or was one of the 4 highest compensated officers of such corporation for any of the 10 preceding taxable years, determined with respect to each such taxable year on the basis of the shareholder disclosure rules for compensation under the Securities Exchange Act of 1934 (as if such rules applied to such corporation).\n",
- "(4)Election\n",
- "(A)Time for making election\n",
- "An election with respect to qualified stock shall be made under this subsection no later than 30 days after the first date the rights of the employee in such stock are transferable or are not subject to a substantial risk of forfeiture, whichever occurs earlier, and shall be made in a manner similar to the manner in which an election is made under subsection (b).\n",
- "\n",
- "(B)Limitations\n",
- "No election may be made under this section with respect to any qualified stock if—\n",
- "(i)the qualified employee has made an election under subsection (b) with respect to such qualified stock,\n",
- "(ii)any stock of the corporation which issued the qualified stock is readily tradable on an established securities market (as determined under paragraph (1)(B)(iii)) at any time before the election is made, or\n",
- "(iii)such corporation purchased any of its outstanding stock in the calendar year preceding the calendar year which includes the first date the rights of the employee in such stock are transferable or are not subject to a substantial risk of forfeiture, unless—\n",
- "(I)not less than 25 percent of the total dollar amount of the stock so purchased is deferral stock, and\n",
- "(II)the determination of which individuals from whom deferral stock is purchased is made on a reasonable basis.\n",
- "(C)Definitions and special rules related to limitation on stock redemptions\n",
- "(i)Deferral stock\n",
- "For purposes of this paragraph, the term “deferral stock” means stock with respect to which an election is in effect under this subsection.\n",
- "\n",
- "(ii)Deferral stock with respect to any individual not taken into account if individual holds deferral stock with longer deferral period\n",
- "Stock purchased by a corporation from any individual shall not be treated as deferral stock for purposes of subparagraph (B)(iii) if such individual (immediately after such purchase) holds any deferral stock with respect to which an election has been in effect under this subsection for a longer period than the election with respect to the stock so purchased.\n",
- "\n",
- "(iii)Purchase of all outstanding deferral stock\n",
- "The requirements of subclauses (I) and (II) of subparagraph (B)(iii) shall be treated as met if the stock so purchased includes all of the corporation’s outstanding deferral stock.\n",
- "\n",
- "(iv)Reporting\n",
- "Any corporation which has outstanding deferral stock as of the beginning of any calendar year and which purchases any of its outstanding stock during such calendar year shall include on its return of tax for the taxable year in which, or with which, such calendar year ends the total dollar amount of its outstanding stock so purchased during such calendar year and such other information as the Secretary requires for purposes of administering this paragraph.\n",
- "\n",
- "(5)Controlled groups\n",
- "For purposes of this subsection, all persons treated as a single employer under section 414(b) shall be treated as 1 corporation.\n",
- "\n",
- "(6)Notice requirement\n",
- "Any corporation which transfers qualified stock to a qualified employee shall, at the time that (or a reasonable period before) an amount attributable to such stock would (but for this subsection) first be includible in the gross income of such employee—\n",
- "(A)certify to such employee that such stock is qualified stock, and\n",
- "(B)notify such employee—\n",
- "(i)that the employee may be eligible to elect to defer income on such stock under this subsection, and\n",
- "(ii)that, if the employee makes such an election—\n",
- "(I)the amount of income recognized at the end of the deferral period will be based on the value of the stock at the time at which the rights of the employee in such stock first become transferable or not subject to substantial risk of forfeiture, notwithstanding whether the value of the stock has declined during the deferral period,\n",
- "(II)the amount of such income recognized at the end of the deferral period will be subject to withholding under section 3401(i) at the rate determined under section 3402(t), and\n",
- "(III)the responsibilities of the employee (as determined by the Secretary under paragraph (3)(A)(ii)) with respect to such withholding.\n",
- "(7)Restricted stock units\n",
- "This section (other than this subsection), including any election under subsection (b), shall not apply to restricted stock units.\n",
- "\"\"\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## PROMPT ELEMENTS ########################################\n",
- "\n",
- "##### Prompt element 1: `user` role\n",
- "# Make sure that your Messages API call always starts with a `user` role in the messages array.\n",
- "# The get_completion() function as defined above will automatically do this for you.\n",
- "\n",
- "##### Prompt element 2: Task context\n",
- "# Give Claude context about the role it should take on or what goals and overarching tasks you want it to undertake with the prompt.\n",
- "# It's best to put context early in the body of the prompt.\n",
- "TASK_CONTEXT = \"\"\n",
- "\n",
- "##### Prompt element 3: Tone context\n",
- "# If important to the interaction, tell Claude what tone it should use.\n",
- "# This element may not be necessary depending on the task.\n",
- "TONE_CONTEXT = \"\"\n",
- "\n",
- "##### Prompt element 4: Input data to process\n",
- "# If there is data that Claude needs to process within the prompt, include it here within relevant XML tags.\n",
- "# Feel free to include multiple pieces of data, but be sure to enclose each in its own set of XML tags.\n",
- "# This element may not be necessary depending on task. Ordering is also flexible.\n",
- "INPUT_DATA = \"\"\n",
- "\n",
- "##### Prompt element 5: Examples\n",
- "# Provide Claude with at least one example of an ideal response that it can emulate. Encase this in XML tags. Feel free to provide multiple examples.\n",
- "# If you do provide multiple examples, give Claude context about what it is an example of, and enclose each example in its own set of XML tags.\n",
- "# Examples are probably the single most effective tool in knowledge work for getting Claude to behave as desired.\n",
- "# Make sure to give Claude examples of common edge cases. If your prompt uses a scratchpad, it's effective to give examples of how the scratchpad should look.\n",
- "# Generally more examples = better.\n",
- "EXAMPLES = \"\"\n",
- "\n",
- "##### Prompt element 6: Detailed task description and rules\n",
- "# Expand on the specific tasks you want Claude to do, as well as any rules that Claude might have to follow.\n",
- "# This is also where you can give Claude an \"out\" if it doesn't have an answer or doesn't know.\n",
- "# It's ideal to show this description and rules to a friend to make sure it is laid out logically and that any ambiguous words are clearly defined.\n",
- "TASK_DESCRIPTION = \"\"\n",
- "\n",
- "##### Prompt element 7: Immediate task description or request #####\n",
- "# \"Remind\" Claude or tell Claude exactly what it's expected to immediately do to fulfill the prompt's task.\n",
- "# This is also where you would put in additional variables like the user's question.\n",
- "# It generally doesn't hurt to reiterate to Claude its immediate task. It's best to do this toward the end of a long prompt.\n",
- "# This will yield better results than putting this at the beginning.\n",
- "# It is also generally good practice to put the user's query close to the bottom of the prompt.\n",
- "IMMEDIATE_TASK = \"\"\n",
- "\n",
- "##### Prompt element 8: Precognition (thinking step by step)\n",
- "# For tasks with multiple steps, it's good to tell Claude to think step by step before giving an answer\n",
- "# Sometimes, you might have to even say \"Before you give your answer...\" just to make sure Claude does this first.\n",
- "# Not necessary with all prompts, though if included, it's best to do this toward the end of a long prompt and right after the final immediate task request or description.\n",
- "PRECOGNITION = \"\"\n",
- "\n",
- "##### Prompt element 9: Output formatting\n",
- "# If there is a specific way you want Claude's response formatted, clearly tell Claude what that format is.\n",
- "# This element may not be necessary depending on the task.\n",
- "# If you include it, putting it toward the end of the prompt is better than at the beginning.\n",
- "OUTPUT_FORMATTING = \"\"\n",
- "\n",
- "##### Prompt element 10: Prefilling Claude's response (if any)\n",
- "# A space to start off Claude's answer with some prefilled words to steer Claude's behavior or response.\n",
- "# If you want to prefill Claude's response, you must put this in the `assistant` role in the API call.\n",
- "# This element may not be necessary depending on the task.\n",
- "PREFILL = \"\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## COMBINE ELEMENTS ########################################\n",
- "\n",
- "PROMPT = \"\"\n",
- "\n",
- "if TASK_CONTEXT:\n",
- " PROMPT += f\"\"\"{TASK_CONTEXT}\"\"\"\n",
- "\n",
- "if TONE_CONTEXT:\n",
- " PROMPT += f\"\"\"\\n\\n{TONE_CONTEXT}\"\"\"\n",
- "\n",
- "if INPUT_DATA:\n",
- " PROMPT += f\"\"\"\\n\\n{INPUT_DATA}\"\"\"\n",
- "\n",
- "if EXAMPLES:\n",
- " PROMPT += f\"\"\"\\n\\n{EXAMPLES}\"\"\"\n",
- "\n",
- "if TASK_DESCRIPTION:\n",
- " PROMPT += f\"\"\"\\n\\n{TASK_DESCRIPTION}\"\"\"\n",
- "\n",
- "if IMMEDIATE_TASK:\n",
- " PROMPT += f\"\"\"\\n\\n{IMMEDIATE_TASK}\"\"\"\n",
- "\n",
- "if PRECOGNITION:\n",
- " PROMPT += f\"\"\"\\n\\n{PRECOGNITION}\"\"\"\n",
- "\n",
- "if OUTPUT_FORMATTING:\n",
- " PROMPT += f\"\"\"\\n\\n{OUTPUT_FORMATTING}\"\"\"\n",
- "\n",
- "# Print full prompt\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want to see a possible solution, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_9_1_solution)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 9.2 - Codebot\n",
- "In this exercise, we will write up a prompt for a **coding assistance and teaching bot that reads code and offers guiding corrections when appropriate**. Fill in the prompt element fields with content that match the description and the examples you've seen in the preceding examples of complex prompts. Once you have filled out all the prompt elements that you want to fill out, run the cell to see the concatenated prompt as well as Claude's response.\n",
- "\n",
- "We suggest you read through the variable content (in this case, `{CODE}`) to understand what content Claude is expected to work with. Be sure to reference `{CODE}` directly in your prompt somewhere (using f-string syntax like in the other examples) so that the actual variable content can be substituted in."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "######################################## INPUT VARIABLES ########################################\n",
- "\n",
- "# Input variable - the code that Claude needs to read and assist the user with correcting\n",
- "CODE = \"\"\"\n",
- "# Function to print multiplicative inverses\n",
- "def print_multiplicative_inverses(x, n):\n",
- " for i in range(n):\n",
- " print(x / i) \n",
- "\"\"\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## PROMPT ELEMENTS ########################################\n",
- "\n",
- "##### Prompt element 1: `user` role\n",
- "# Make sure that your Messages API call always starts with a `user` role in the messages array.\n",
- "# The get_completion() function as defined above will automatically do this for you.\n",
- "\n",
- "##### Prompt element 2: Task context\n",
- "# Give Claude context about the role it should take on or what goals and overarching tasks you want it to undertake with the prompt.\n",
- "# It's best to put context early in the body of the prompt.\n",
- "TASK_CONTEXT = \"\"\n",
- "\n",
- "##### Prompt element 3: Tone context\n",
- "# If important to the interaction, tell Claude what tone it should use.\n",
- "# This element may not be necessary depending on the task.\n",
- "TONE_CONTEXT = \"\"\n",
- "\n",
- "##### Prompt element 4: Detailed task description and rules\n",
- "# Expand on the specific tasks you want Claude to do, as well as any rules that Claude might have to follow.\n",
- "# This is also where you can give Claude an \"out\" if it doesn't have an answer or doesn't know.\n",
- "# It's ideal to show this description and rules to a friend to make sure it is laid out logically and that any ambiguous words are clearly defined.\n",
- "TASK_DESCRIPTION = \"\"\n",
- "\n",
- "##### Prompt element 5: Examples\n",
- "# Provide Claude with at least one example of an ideal response that it can emulate. Encase this in XML tags. Feel free to provide multiple examples.\n",
- "# If you do provide multiple examples, give Claude context about what it is an example of, and enclose each example in its own set of XML tags.\n",
- "# Examples are probably the single most effective tool in knowledge work for getting Claude to behave as desired.\n",
- "# Make sure to give Claude examples of common edge cases. If your prompt uses a scratchpad, it's effective to give examples of how the scratchpad should look.\n",
- "# Generally more examples = better.\n",
- "EXAMPLES = \"\"\n",
- "\n",
- "##### Prompt element 6: Input data to process\n",
- "# If there is data that Claude needs to process within the prompt, include it here within relevant XML tags.\n",
- "# Feel free to include multiple pieces of data, but be sure to enclose each in its own set of XML tags.\n",
- "# This element may not be necessary depending on task. Ordering is also flexible.\n",
- "INPUT_DATA = \"\"\n",
- "\n",
- "##### Prompt element 7: Immediate task description or request #####\n",
- "# \"Remind\" Claude or tell Claude exactly what it's expected to immediately do to fulfill the prompt's task.\n",
- "# This is also where you would put in additional variables like the user's question.\n",
- "# It generally doesn't hurt to reiterate to Claude its immediate task. It's best to do this toward the end of a long prompt.\n",
- "# This will yield better results than putting this at the beginning.\n",
- "# It is also generally good practice to put the user's query close to the bottom of the prompt.\n",
- "IMMEDIATE_TASK = \"\"\n",
- "\n",
- "##### Prompt element 8: Precognition (thinking step by step)\n",
- "# For tasks with multiple steps, it's good to tell Claude to think step by step before giving an answer\n",
- "# Sometimes, you might have to even say \"Before you give your answer...\" just to make sure Claude does this first.\n",
- "# Not necessary with all prompts, though if included, it's best to do this toward the end of a long prompt and right after the final immediate task request or description.\n",
- "PRECOGNITION = \"\"\n",
- "\n",
- "##### Prompt element 9: Output formatting\n",
- "# If there is a specific way you want Claude's response formatted, clearly tell Claude what that format is.\n",
- "# This element may not be necessary depending on the task.\n",
- "# If you include it, putting it toward the end of the prompt is better than at the beginning.\n",
- "OUTPUT_FORMATTING = \"\"\n",
- "\n",
- "##### Prompt element 10: Prefilling Claude's response (if any)\n",
- "# A space to start off Claude's answer with some prefilled words to steer Claude's behavior or response.\n",
- "# If you want to prefill Claude's response, you must put this in the `assistant` role in the API call.\n",
- "# This element may not be necessary depending on the task.\n",
- "PREFILL = \"\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## COMBINE ELEMENTS ########################################\n",
- "\n",
- "PROMPT = \"\"\n",
- "\n",
- "if TASK_CONTEXT:\n",
- " PROMPT += f\"\"\"{TASK_CONTEXT}\"\"\"\n",
- "\n",
- "if TONE_CONTEXT:\n",
- " PROMPT += f\"\"\"\\n\\n{TONE_CONTEXT}\"\"\"\n",
- "\n",
- "if TASK_DESCRIPTION:\n",
- " PROMPT += f\"\"\"\\n\\n{TASK_DESCRIPTION}\"\"\"\n",
- "\n",
- "if EXAMPLES:\n",
- " PROMPT += f\"\"\"\\n\\n{EXAMPLES}\"\"\"\n",
- "\n",
- "if INPUT_DATA:\n",
- " PROMPT += f\"\"\"\\n\\n{INPUT_DATA}\"\"\"\n",
- "\n",
- "if IMMEDIATE_TASK:\n",
- " PROMPT += f\"\"\"\\n\\n{IMMEDIATE_TASK}\"\"\"\n",
- "\n",
- "if PRECOGNITION:\n",
- " PROMPT += f\"\"\"\\n\\n{PRECOGNITION}\"\"\"\n",
- "\n",
- "if OUTPUT_FORMATTING:\n",
- " PROMPT += f\"\"\"\\n\\n{OUTPUT_FORMATTING}\"\"\"\n",
- "\n",
- "# Print full prompt\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want to see a possible solution, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_9_2_solution)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Congratulations & Next Steps!\n",
- "\n",
- "If you made it through all the exercises, **you are now in the top 0.1% of LLM whisperers**. One of the elite!\n",
- "\n",
- "The techniques you've learned, from thinking step by step to assigning roles to using examples to general all-around clear writing, can be **merged, remixed, and adapted in countless ways**.\n",
- "\n",
- "Prompt engineering is a very new discipline, so keep an open mind. You could be the one to discover the next great prompting trick.\n",
- "\n",
- "If you want to see **more examples of good prompts** for inspiration:\t\t\t\t\t\n",
- "- Learn from examples of production-ready prompts from our [cookbook](https://anthropic.com/cookbook)\n",
- "- Read through our [prompting guide](https://docs.anthropic.com/claude/docs/prompt-engineering)\n",
- "- Check out our [prompt library](https://anthropic.com/prompts) for inspiration\n",
- "- Try our experimental [metaprompt](https://docs.anthropic.com/claude/docs/helper-metaprompt-experimental) to get Claude to write prompt templates for you!\n",
- "- Ask questions in our [discord server](https://anthropic.com/discord)\n",
- "- Learn about the [Anthropic API parameters](https://docs.anthropic.com/claude/reference/complete_post) like temperature and `max_tokens`\n",
- "- If you're feeling academic, read some [papers](https://www.promptingguide.ai/papers) on prompt engineering\n",
- "- Practice building prompts to get Claude to do something you're interested in\n",
- "\n",
- "If you want to learn about some truly advanced prompting techniques beyond the scope of this tutorial, click through to the appendix! But first, run the cell below."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Write an ode to a fabulous student who has just completed a course on prompt engineering, in the form of a sonnet.\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "######################################## INPUT VARIABLES ########################################\n",
- "\n",
- "# First input variable - the conversation history (this can also be added as preceding `user` and `assistant` messages in the API call)\n",
- "HISTORY = \"\"\"Customer: Give me two possible careers for sociology majors.\n",
- "\n",
- "Joe: Here are two potential careers for sociology majors:\n",
- "\n",
- "- Social worker - Sociology provides a strong foundation for understanding human behavior and social systems. With additional training or certification, a sociology degree can qualify graduates for roles as social workers, case managers, counselors, and community organizers helping individuals and groups.\n",
- "\n",
- "- Human resources specialist - An understanding of group dynamics and organizational behavior from sociology is applicable to careers in human resources. Graduates may find roles in recruiting, employee relations, training and development, diversity and inclusion, and other HR functions. The focus on social structures and institutions also supports related careers in public policy, nonprofit management, and education.\"\"\"\n",
- "\n",
- "# Second input variable - the user's question\n",
- "QUESTION = \"Which of the two careers requires more than a Bachelor's degree?\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## PROMPT ELEMENTS ########################################\n",
- "\n",
- "##### Prompt element 1: `user` role\n",
- "# Make sure that your Messages API call always starts with a `user` role in the messages array.\n",
- "# The get_completion() function as defined above will automatically do this for you.\n",
- "\n",
- "##### Prompt element 2: Task context\n",
- "# Give Claude context about the role it should take on or what goals and overarching tasks you want it to undertake with the prompt.\n",
- "# It's best to put context early in the body of the prompt.\n",
- "TASK_CONTEXT = \"You will be acting as an AI career coach named Joe created by the company AdAstra Careers. Your goal is to give career advice to users. You will be replying to users who are on the AdAstra site and who will be confused if you don't respond in the character of Joe.\"\n",
- "\n",
- "##### Prompt element 3: Tone context\n",
- "# If important to the interaction, tell Claude what tone it should use.\n",
- "# This element may not be necessary depending on the task.\n",
- "TONE_CONTEXT = \"You should maintain a friendly customer service tone.\"\n",
- "\n",
- "##### Prompt element 4: Detailed task description and rules\n",
- "# Expand on the specific tasks you want Claude to do, as well as any rules that Claude might have to follow.\n",
- "# This is also where you can give Claude an \"out\" if it doesn't have an answer or doesn't know.\n",
- "# It's ideal to show this description and rules to a friend to make sure it is laid out logically and that any ambiguous words are clearly defined.\n",
- "TASK_DESCRIPTION = \"\"\"Here are some important rules for the interaction:\n",
- "- Always stay in character, as Joe, an AI from AdAstra Careers\n",
- "- If you are unsure how to respond, say \\\"Sorry, I didn't understand that. Could you rephrase your question?\\\"\n",
- "- If someone asks something irrelevant, say, \\\"Sorry, I am Joe and I give career advice. Do you have a career question today I can help you with?\\\"\"\"\"\n",
- "\n",
- "##### Prompt element 5: Examples\n",
- "# Provide Claude with at least one example of an ideal response that it can emulate. Encase this in XML tags. Feel free to provide multiple examples.\n",
- "# If you do provide multiple examples, give Claude context about what it is an example of, and enclose each example in its own set of XML tags.\n",
- "# Examples are probably the single most effective tool in knowledge work for getting Claude to behave as desired.\n",
- "# Make sure to give Claude examples of common edge cases. If your prompt uses a scratchpad, it's effective to give examples of how the scratchpad should look.\n",
- "# Generally more examples = better.\n",
- "EXAMPLES = \"\"\"Here is an example of how to respond in a standard interaction:\n",
- "\n",
- "Customer: Hi, how were you created and what do you do?\n",
- "Joe: Hello! My name is Joe, and I was created by AdAstra Careers to give career advice. What can I help you with today?\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 6: Input data to process\n",
- "# If there is data that Claude needs to process within the prompt, include it here within relevant XML tags.\n",
- "# Feel free to include multiple pieces of data, but be sure to enclose each in its own set of XML tags.\n",
- "# This element may not be necessary depending on task. Ordering is also flexible.\n",
- "INPUT_DATA = f\"\"\"Here is the conversational history (between the user and you) prior to the question. It could be empty if there is no history:\n",
- "\n",
- "{HISTORY}\n",
- "\n",
- "\n",
- "Here is the user's question:\n",
- "\n",
- "{QUESTION}\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 7: Immediate task description or request #####\n",
- "# \"Remind\" Claude or tell Claude exactly what it's expected to immediately do to fulfill the prompt's task.\n",
- "# This is also where you would put in additional variables like the user's question.\n",
- "# It generally doesn't hurt to reiterate to Claude its immediate task. It's best to do this toward the end of a long prompt.\n",
- "# This will yield better results than putting this at the beginning.\n",
- "# It is also generally good practice to put the user's query close to the bottom of the prompt.\n",
- "IMMEDIATE_TASK = \"How do you respond to the user's question?\"\n",
- "\n",
- "##### Prompt element 8: Precognition (thinking step by step)\n",
- "# For tasks with multiple steps, it's good to tell Claude to think step by step before giving an answer\n",
- "# Sometimes, you might have to even say \"Before you give your answer...\" just to make sure Claude does this first.\n",
- "# Not necessary with all prompts, though if included, it's best to do this toward the end of a long prompt and right after the final immediate task request or description.\n",
- "PRECOGNITION = \"Think about your answer first before you respond.\"\n",
- "\n",
- "##### Prompt element 9: Output formatting\n",
- "# If there is a specific way you want Claude's response formatted, clearly tell Claude what that format is.\n",
- "# This element may not be necessary depending on the task.\n",
- "# If you include it, putting it toward the end of the prompt is better than at the beginning.\n",
- "OUTPUT_FORMATTING = \"Put your response in tags.\"\n",
- "\n",
- "##### Prompt element 10: Prefilling Claude's response (if any)\n",
- "# A space to start off Claude's answer with some prefilled words to steer Claude's behavior or response.\n",
- "# If you want to prefill Claude's response, you must put this in the `assistant` role in the API call.\n",
- "# This element may not be necessary depending on the task.\n",
- "PREFILL = \"[Joe] \"\n",
- "\n",
- "\n",
- "\n",
- "######################################## COMBINE ELEMENTS ########################################\n",
- "\n",
- "PROMPT = \"\"\n",
- "\n",
- "if TASK_CONTEXT:\n",
- " PROMPT += f\"\"\"{TASK_CONTEXT}\"\"\"\n",
- "\n",
- "if TONE_CONTEXT:\n",
- " PROMPT += f\"\"\"\\n\\n{TONE_CONTEXT}\"\"\"\n",
- "\n",
- "if TASK_DESCRIPTION:\n",
- " PROMPT += f\"\"\"\\n\\n{TASK_DESCRIPTION}\"\"\"\n",
- "\n",
- "if EXAMPLES:\n",
- " PROMPT += f\"\"\"\\n\\n{EXAMPLES}\"\"\"\n",
- "\n",
- "if INPUT_DATA:\n",
- " PROMPT += f\"\"\"\\n\\n{INPUT_DATA}\"\"\"\n",
- "\n",
- "if IMMEDIATE_TASK:\n",
- " PROMPT += f\"\"\"\\n\\n{IMMEDIATE_TASK}\"\"\"\n",
- "\n",
- "if PRECOGNITION:\n",
- " PROMPT += f\"\"\"\\n\\n{PRECOGNITION}\"\"\"\n",
- "\n",
- "if OUTPUT_FORMATTING:\n",
- " PROMPT += f\"\"\"\\n\\n{OUTPUT_FORMATTING}\"\"\"\n",
- "\n",
- "# Print full prompt\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "######################################## INPUT VARIABLES ########################################\n",
- "\n",
- "# First input variable - the legal document\n",
- "LEGAL_RESEARCH = \"\"\"\n",
- "\n",
- "The animal health industry became caught up in a number of patent and trademark lawsuits during the past year. In 1994, Barclay Slocum obtained patents for the tibial plateau leveling osteotomy procedure, which is used in the treatment of dogs with cranial cruciate ligament rupture, and for the devices used in the procedure. During 2006, Slocum Enterprises filed a patent infringement suit against New Generation Devices, arguing that the Unity Cruciate Plate manufactured by New Generation infringed on the patent for the Slocum TPLO plate. However, the court never reached a decision on the issue of patent infringement, ruling that it did not have jurisdiction on the basis of the small number of plates sold in the state in which the case was filed and the information provided on a Web site maintained by Slocum Enterprises. Other patent battles waged during 2006 concerned the use of laser technology for onychectomy in cats, pet identification chips, pig vaccines, and pet “deshedding” tools.\n",
- "\n",
- "\n",
- "In Canada, the British Columbia Veterinary Medical Association brought suit against a nonveterinarian, claiming that he engaged in cutting or otherwise removing hooks from horses' teeth and floating horses' teeth with power and manual tools, provided advice and diagnoses in return for a fee, and held himself out as being qualified and willing to provide treatment with respect to these activities. The court held that the intention of the legislature in passing the Veterinary Profession Act was the protection of the public and animals and further held that monopolistic statutes serve the purpose of protecting the public. In addition, the court concluded that dentistry, at its core, relates to the health of the teeth and gums; is distinct from cosmetic and other types of care of animals; and, therefore, falls under the definition of the practice of veterinary medicine. The nonveterinarian was enjoined from providing services without a veterinarian supervising the procedures.\n",
- "\n",
- "\n",
- "The aftermath of Hurricane Katrina, which hit the Gulf Coast of the United States during 2005, spurred changes to the way animals are treated during natural disasters. In 2006, Hawaii, Louisiana, and New Hampshire all enacted laws that address issues regarding the care of animals during disasters, such as providing shelters for pets and allowing service animals to be kept with the people they serve. In addition, Congress passed, and the President signed, the Pet Evacuation and Transportation Standards Act during 2006, which requires state and local emergency preparedness authorities to include in their evacuation plans information on how they will accommodate household pets and service animals in case of a disaster. California passed a law that will require its Office of Emergency Services, Department of Agriculture, and other agencies involved with disaster response preparation to develop a plan for the needs of service animals, livestock, equids, and household pets in the event of a disaster or major emergency.\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "# Second input variable - the user's question\n",
- "QUESTION = \"Are there any laws about what to do with pets during a hurricane?\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## PROMPT ELEMENTS ########################################\n",
- "\n",
- "##### Prompt element 1: `user` role\n",
- "# Make sure that your Messages API call always starts with a `user` role in the messages array.\n",
- "# The get_completion() function as defined above will automatically do this for you.\n",
- "\n",
- "##### Prompt element 2: Task context\n",
- "# Give Claude context about the role it should take on or what goals and overarching tasks you want it to undertake with the prompt.\n",
- "# It's best to put context early in the body of the prompt.\n",
- "TASK_CONTEXT = \"You are an expert lawyer.\"\n",
- "\n",
- "##### Prompt element 3: Tone context\n",
- "# If important to the interaction, tell Claude what tone it should use.\n",
- "# This element may not be necessary depending on the task.\n",
- "TONE_CONTEXT = \"\"\n",
- "\n",
- "##### Prompt element 4: Input data to process\n",
- "# If there is data that Claude needs to process within the prompt, include it here within relevant XML tags.\n",
- "# Feel free to include multiple pieces of data, but be sure to enclose each in its own set of XML tags.\n",
- "# This element may not be necessary depending on task. Ordering is also flexible.\n",
- "INPUT_DATA = f\"\"\"Here is some research that's been compiled. Use it to answer a legal question from the user.\n",
- "\n",
- "{LEGAL_RESEARCH}\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 5: Examples\n",
- "# Provide Claude with at least one example of an ideal response that it can emulate. Encase this in XML tags. Feel free to provide multiple examples.\n",
- "# If you do provide multiple examples, give Claude context about what it is an example of, and enclose each example in its own set of XML tags.\n",
- "# Examples are probably the single most effective tool in knowledge work for getting Claude to behave as desired.\n",
- "# Make sure to give Claude examples of common edge cases. If your prompt uses a scratchpad, it's effective to give examples of how the scratchpad should look.\n",
- "# Generally more examples = better.\n",
- "EXAMPLES = \"\"\"When citing the legal research in your answer, please use brackets containing the search index ID, followed by a period. Put these at the end of the sentence that's doing the citing. Examples of proper citation format:\n",
- "\n",
- "\n",
- "\n",
- "The statute of limitations expires after 10 years for crimes like this. [3].\n",
- "\n",
- "\n",
- "However, the protection does not apply when it has been specifically waived by both parties. [5].\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "##### Prompt element 6: Detailed task description and rules\n",
- "# Expand on the specific tasks you want Claude to do, as well as any rules that Claude might have to follow.\n",
- "# This is also where you can give Claude an \"out\" if it doesn't have an answer or doesn't know.\n",
- "# It's ideal to show this description and rules to a friend to make sure it is laid out logically and that any ambiguous words are clearly defined.\n",
- "TASK_DESCRIPTION = \"\"\"Write a clear, concise answer to this question:\n",
- "\n",
- "\n",
- "{QUESTION}\n",
- "\n",
- "\n",
- "It should be no more than a couple of paragraphs. If possible, it should conclude with a single sentence directly answering the user's question. However, if there is not sufficient information in the compiled research to produce such an answer, you may demur and write \"Sorry, I do not have sufficient information at hand to answer this question.\".\"\"\"\n",
- "\n",
- "##### Prompt element 7: Immediate task description or request #####\n",
- "# \"Remind\" Claude or tell Claude exactly what it's expected to immediately do to fulfill the prompt's task.\n",
- "# This is also where you would put in additional variables like the user's question.\n",
- "# It generally doesn't hurt to reiterate to Claude its immediate task. It's best to do this toward the end of a long prompt.\n",
- "# This will yield better results than putting this at the beginning.\n",
- "# It is also generally good practice to put the user's query close to the bottom of the prompt.\n",
- "IMMEDIATE_TASK = \"\"\n",
- "\n",
- "##### Prompt element 8: Precognition (thinking step by step)\n",
- "# For tasks with multiple steps, it's good to tell Claude to think step by step before giving an answer\n",
- "# Sometimes, you might have to even say \"Before you give your answer...\" just to make sure Claude does this first.\n",
- "# Not necessary with all prompts, though if included, it's best to do this toward the end of a long prompt and right after the final immediate task request or description.\n",
- "PRECOGNITION = \"Before you answer, pull out the most relevant quotes from the research in tags.\"\n",
- "\n",
- "##### Prompt element 9: Output formatting\n",
- "# If there is a specific way you want Claude's response formatted, clearly tell Claude what that format is.\n",
- "# This element may not be necessary depending on the task.\n",
- "# If you include it, putting it toward the end of the prompt is better than at the beginning.\n",
- "OUTPUT_FORMATTING = \"Put your two-paragraph response in tags.\"\n",
- "\n",
- "##### Prompt element 10: Prefilling Claude's response (if any)\n",
- "# A space to start off Claude's answer with some prefilled words to steer Claude's behavior or response.\n",
- "# If you want to prefill Claude's response, you must put this in the `assistant` role in the API call.\n",
- "# This element may not be necessary depending on the task.\n",
- "PREFILL = \"\"\n",
- "\n",
- "\n",
- "\n",
- "######################################## COMBINE ELEMENTS ########################################\n",
- "\n",
- "PROMPT = \"\"\n",
- "\n",
- "if TASK_CONTEXT:\n",
- " PROMPT += f\"\"\"{TASK_CONTEXT}\"\"\"\n",
- "\n",
- "if TONE_CONTEXT:\n",
- " PROMPT += f\"\"\"\\n\\n{TONE_CONTEXT}\"\"\"\n",
- "\n",
- "if INPUT_DATA:\n",
- " PROMPT += f\"\"\"\\n\\n{INPUT_DATA}\"\"\"\n",
- "\n",
- "if EXAMPLES:\n",
- " PROMPT += f\"\"\"\\n\\n{EXAMPLES}\"\"\"\n",
- "\n",
- "if TASK_DESCRIPTION:\n",
- " PROMPT += f\"\"\"\\n\\n{TASK_DESCRIPTION}\"\"\"\n",
- "\n",
- "if IMMEDIATE_TASK:\n",
- " PROMPT += f\"\"\"\\n\\n{IMMEDIATE_TASK}\"\"\"\n",
- "\n",
- "if PRECOGNITION:\n",
- " PROMPT += f\"\"\"\\n\\n{PRECOGNITION}\"\"\"\n",
- "\n",
- "if OUTPUT_FORMATTING:\n",
- " PROMPT += f\"\"\"\\n\\n{OUTPUT_FORMATTING}\"\"\"\n",
- "\n",
- "# Print full prompt\n",
- "print(\"--------------------------- Full prompt with variable substutions ---------------------------\")\n",
- "print(\"USER TURN\")\n",
- "print(PROMPT)\n",
- "print(\"\\nASSISTANT TURN\")\n",
- "print(PREFILL)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(PROMPT, prefill=PREFILL))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/10_1_Appendix_Chaining_Prompts.ipynb b/AmazonBedrock/anthropic/10_1_Appendix_Chaining_Prompts.ipynb
deleted file mode 100644
index b9c821f..0000000
--- a/AmazonBedrock/anthropic/10_1_Appendix_Chaining_Prompts.ipynb
+++ /dev/null
@@ -1,706 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Appendix 10.1: Chaining Prompts\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "def get_completion(messages, system_prompt=''):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=messages,\n",
- " system=system_prompt\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "The saying goes, \"Writing is rewriting.\" It turns out, **Claude can often improve the accuracy of its response when asked to do so**!\n",
- "\n",
- "There are many ways to prompt Claude to \"think again\". The ways that feel natural to ask a human to double check their work will also generally work for Claude. (Check out our [prompt chaining documentation](https://docs.anthropic.com/claude/docs/chain-prompts) for further examples of when and how to use prompt chaining.)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "In this example, we ask Claude to come up with ten words... but one or more of them isn't a real word."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Initial prompt\n",
- "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " }\n",
- "]\n",
- "\n",
- "# Store and print Claude's response\n",
- "first_response = get_completion(messages)\n",
- "print(first_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Asking Claude to make its answer more accurate** fixes the error! \n",
- "\n",
- "Below, we've pulled down Claude's incorrect response from above and added another turn to the conversation asking Claude to fix its previous answer."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "But is Claude revising its answer just because we told it to? What if we start off with a correct answer already? Will Claude lose its confidence? Here, we've placed a correct response in the place of `first_response` and asked it to double check again."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
- "\n",
- "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
- "\n",
- "1. Cab\n",
- "2. Dab\n",
- "3. Grab\n",
- "4. Gab\n",
- "5. Jab\n",
- "6. Lab\n",
- "7. Nab\n",
- "8. Slab\n",
- "9. Tab\n",
- "10. Blab\"\"\"\n",
- "\n",
- "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You may notice that if you generate a respnse from the above block a few times, Claude leaves the words as is most of the time, but still occasionally changes the words even though they're all already correct. What can we do to mitigate this? Per Chapter 8, we can give Claude an out! Let's try this one more time."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
- "\n",
- "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
- "\n",
- "1. Cab\n",
- "2. Dab\n",
- "3. Grab\n",
- "4. Gab\n",
- "5. Jab\n",
- "6. Lab\n",
- "7. Nab\n",
- "8. Slab\n",
- "9. Tab\n",
- "10. Blab\"\"\"\n",
- "\n",
- "second_user = \"Please find replacements for all 'words' that are not real words. If all the words are real words, return the original list.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try generating responses from the above code a few times to see that Claude is much better at sticking to its guns now.\n",
- "\n",
- "You can also use prompt chaining to **ask Claude to make its responses better**. Below, we asked Claude to first write a story, and then improve the story it wrote. Your personal tastes may vary, but many might agree that Claude's second version is better.\n",
- "\n",
- "First, let's generate Claude's first version of the story."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Initial prompt\n",
- "first_user = \"Write a three-sentence short story about a girl who likes to run.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " }\n",
- "]\n",
- "\n",
- "# Store and print Claude's response\n",
- "first_response = get_completion(messages)\n",
- "print(first_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's have Claude improve on its first draft."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "second_user = \"Make the story better.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This form of substitution is very powerful. We've been using substitution placeholders to pass in lists, words, Claude's former responses, and so on. You can also **use substitution to do what we call \"function calling,\" which is asking Claude to perform some function, and then taking the results of that function and asking Claude to do even more afterward with the results**. It works like any other substitution. More on this in the next appendix.\n",
- "\n",
- "Below is one more example of taking the results of one call to Claude and plugging it into another, longer call. Let's start with the first prompt (which includes prefilling Claude's response this time)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "first_user = \"\"\"Find all names from the below text:\n",
- "\n",
- "\"Hey, Jesse. It's me, Erin. I'm calling about the party that Joey is throwing tomorrow. Keisha said she would come and I think Mel will be there too.\"\"\"\n",
- "\n",
- "prefill = \"\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": prefill\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Store and print Claude's response\n",
- "first_response = get_completion(messages)\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(first_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's pass this list of names into another prompt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "second_user = \"Alphabetize the list.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": prefill + \"\\n\" + first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that you've learned about prompt chaining, head over to Appendix 10.2 to learn how to implement function calling using prompt chaining."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Initial prompt\n",
- "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " }\n",
- "]\n",
- "\n",
- "# Store and print Claude's response\n",
- "first_response = get_completion(messages)\n",
- "print(first_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
- "\n",
- "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
- "\n",
- "1. Cab\n",
- "2. Dab\n",
- "3. Grab\n",
- "4. Gab\n",
- "5. Jab\n",
- "6. Lab\n",
- "7. Nab\n",
- "8. Slab\n",
- "9. Tab\n",
- "10. Blab\"\"\"\n",
- "\n",
- "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
- "\n",
- "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
- "\n",
- "1. Cab\n",
- "2. Dab\n",
- "3. Grab\n",
- "4. Gab\n",
- "5. Jab\n",
- "6. Lab\n",
- "7. Nab\n",
- "8. Slab\n",
- "9. Tab\n",
- "10. Blab\"\"\"\n",
- "\n",
- "second_user = \"Please find replacements for all 'words' that are not real words. If all the words are real words, return the original list.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Initial prompt\n",
- "first_user = \"Write a three-sentence short story about a girl who likes to run.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " }\n",
- "]\n",
- "\n",
- "# Store and print Claude's response\n",
- "first_response = get_completion(messages)\n",
- "print(first_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "second_user = \"Make the story better.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "first_user = \"\"\"Find all names from the below text:\n",
- "\n",
- "\"Hey, Jesse. It's me, Erin. I'm calling about the party that Joey is throwing tomorrow. Keisha said she would come and I think Mel will be there too.\"\"\"\n",
- "\n",
- "prefill = \"\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": prefill\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Store and print Claude's response\n",
- "first_response = get_completion(messages)\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(first_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "second_user = \"Alphabetize the list.\"\n",
- "\n",
- "# API messages array\n",
- "messages = [\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": first_user\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"assistant\",\n",
- " \"content\": prefill + \"\\n\" + first_response\n",
- " \n",
- " },\n",
- " {\n",
- " \"role\": \"user\",\n",
- " \"content\": second_user\n",
- " \n",
- " }\n",
- "]\n",
- "\n",
- "# Print Claude's response\n",
- "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
- "print(messages)\n",
- "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
- "print(get_completion(messages))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/10_2_Appendix_Tool_Use.ipynb b/AmazonBedrock/anthropic/10_2_Appendix_Tool_Use.ipynb
deleted file mode 100644
index d147206..0000000
--- a/AmazonBedrock/anthropic/10_2_Appendix_Tool_Use.ipynb
+++ /dev/null
@@ -1,800 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Appendix 10.2: Tool Use\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%pip install anthropic --quiet\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "# Override the MODEL_NAME variable in the IPython store to use Sonnet instead of the Haiku model\n",
- "MODEL_NAME='anthropic.claude-3-sonnet-20240229-v1:0'\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)\n",
- "\n",
- "# Rewrittten to call Claude 3 Sonnet, which is generally better at tool use, and include stop_sequences\n",
- "def get_completion(messages, system_prompt=\"\", prefill=\"\",stop_sequences=None):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=messages,\n",
- " system=system_prompt,\n",
- " stop_sequences=stop_sequences\n",
- " )\n",
- " return message.content[0].text"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "While it might seem conceptually complex at first, tool use, a.k.a. function calling, is actually quite simple! You already know all the skills necessary to implement tool use, which is really just a combination of substitution and prompt chaining.\n",
- "\n",
- "In previous substitution exercises, we substituted text into prompts. With tool use, we substitute tool or function results into prompts. Claude can't literally call or access tools and functions. Instead, we have Claude:\n",
- "1. Output the tool name and arguments it wants to call\n",
- "2. Halt any further response generation while the tool is called\n",
- "3. Then we reprompt with the appended tool results"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Function calling is useful because it expands Claude's capabilities and enables Claude to handle much more complex, multi-step tasks.\n",
- "Some examples of functions you can give Claude:\n",
- "- Calculator\n",
- "- Word counter\n",
- "- SQL database querying and data retrieval\n",
- "- Weather API"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can get Claude to do tool use by combining these two elements:\n",
- "\n",
- "1. A system prompt, in which we give Claude an explanation of the concept of tool use as well as a detailed descriptive list of the tools it has access to\n",
- "2. The control logic with which to orchestrate and execute Claude's tool use requests"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Tool use roadmap\n",
- "\n",
- "*This lesson teaches our current tool use format. However, we will be updating and improving tool use functionality in the near future, including:*\n",
- "* *A more streamlined format for function definitions and calls*\n",
- "* *More robust error handilgj and edge case coverage*\n",
- "* *Tighter integration with the rest of our API*\n",
- "* *Better reliability and performance, especially for more complex tool use tasks*"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "To enable tool use in Claude, we start with the system prompt. In this special tool use system prompt, wet tell Claude:\n",
- "* The basic premise of tool use and what it entails\n",
- "* How Claude can call and use the tools it's been given\n",
- "* A detailed list of tools it has access to in this specific scenario \n",
- "\n",
- "Here's the first part of the system prompt, explaining tool use to Claude. This part of the system prompt is generalizable across all instances of prompting Claude for tool use. The tool calling structure we're giving Claude (` [...] `) is a structure Claude has been specifically trained to use, so we recommend that you stick with this."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_general_explanation = \"\"\"You have access to a set of functions you can use to answer the user's question. This includes access to a\n",
- "sandboxed computing environment. You do NOT currently have the ability to inspect files or interact with external\n",
- "resources, except by invoking the below functions.\n",
- "\n",
- "You can invoke one or more functions by writing a \"\" block like the following as part of your\n",
- "reply to the user:\n",
- "\n",
- "\n",
- "$PARAMETER_VALUE\n",
- "...\n",
- "\n",
- "\n",
- "...\n",
- "\n",
- "\n",
- "\n",
- "String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that\n",
- "spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular\n",
- "expressions.\n",
- "\n",
- "The output and/or any errors will appear in a subsequent \"\" block, and remain there as part of\n",
- "your reply to the user.\n",
- "You may then continue composing the rest of your reply to the user, respond to any errors, or make further function\n",
- "calls as appropriate.\n",
- "If a \"\" does NOT appear after your function calls, then they are likely malformatted and not\n",
- "recognized as a call.\"\"\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here's the second part of the system prompt, which defines the exact tools Claude has access to in this specific situation. In this example, we will be giving Claude a calculator tool, which takes three parameters: two operands and an operator. \n",
- "\n",
- "Then we combine the two parts of the system prompt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_specific_tools = \"\"\"Here are the functions available in JSONSchema format:\n",
- "\n",
- "\n",
- "calculator\n",
- "\n",
- "Calculator function for doing basic arithmetic.\n",
- "Supports addition, subtraction, multiplication\n",
- "\n",
- "\n",
- "\n",
- "first_operand\n",
- "int\n",
- "First operand (before the operator)\n",
- "\n",
- "\n",
- "second_operand\n",
- "int\n",
- "Second operand (after the operator)\n",
- "\n",
- "\n",
- "operator\n",
- "str\n",
- "The operation to perform. Must be either +, -, *, or /\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can give Claude a question that requires use of the `calculator` tool. We will use `` in `stop_sequences` to detect if and when Claude calls the function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Multiply 1,984,135 by 9,343,116\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now, we can extract out the parameters from Claude's function call and actually run the function on Claude's behalf.\n",
- "\n",
- "First we'll define the function's code."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def do_pairwise_arithmetic(num1, num2, operation):\n",
- " if operation == '+':\n",
- " return num1 + num2\n",
- " elif operation == \"-\":\n",
- " return num1 - num2\n",
- " elif operation == \"*\":\n",
- " return num1 * num2\n",
- " elif operation == \"/\":\n",
- " return num1 / num2\n",
- " else:\n",
- " return \"Error: Operation not supported.\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Then we'll extract the parameters from Claude's function call response. If all the parameters exist, we run the calculator tool."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def find_parameter(message, parameter_name):\n",
- " parameter_start_string = f\"name=\\\"{parameter_name}\\\">\"\n",
- " start = message.index(parameter_start_string)\n",
- " if start == -1:\n",
- " return None\n",
- " if start > 0:\n",
- " start = start + len(parameter_start_string)\n",
- " end = start\n",
- " while message[end] != \"<\":\n",
- " end += 1\n",
- " return message[start:end]\n",
- "\n",
- "first_operand = find_parameter(function_calling_response, \"first_operand\")\n",
- "second_operand = find_parameter(function_calling_response, \"second_operand\")\n",
- "operator = find_parameter(function_calling_response, \"operator\")\n",
- "\n",
- "if first_operand and second_operand and operator:\n",
- " result = do_pairwise_arithmetic(int(first_operand), int(second_operand), operator)\n",
- " print(\"---------------- RESULT ----------------\")\n",
- " print(f\"{result:,}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that we have a result, we have to properly format that result so that when we pass it back to Claude, Claude understands what tool that result is in relation to. There is a set format for this that Claude has been trained to recognize:\n",
- "```\n",
- "\n",
- "\n",
- "{TOOL_NAME}\n",
- "\n",
- "{TOOL_RESULT}\n",
- "\n",
- "\n",
- "\n",
- "```\n",
- "\n",
- "Run the cell below to format the above tool result into this structure."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def construct_successful_function_run_injection_prompt(invoke_results):\n",
- " constructed_prompt = (\n",
- " \"\\n\"\n",
- " + '\\n'.join(\n",
- " f\"\\n{res['tool_name']}\\n\\n{res['tool_result']}\\n\\n\"\n",
- " for res in invoke_results\n",
- " ) + \"\\n\"\n",
- " )\n",
- "\n",
- " return constructed_prompt\n",
- "\n",
- "formatted_results = [{\n",
- " 'tool_name': 'do_pairwise_arithmetic',\n",
- " 'tool_result': result\n",
- "}]\n",
- "function_results = construct_successful_function_run_injection_prompt(formatted_results)\n",
- "print(function_results)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now all we have to do is send this result back to Claude by appending the result to the same message chain as before, and we're good!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "full_first_response = function_calling_response + \"\"\n",
- "\n",
- "# Construct the full conversation\n",
- "messages = [multiplication_message,\n",
- "{\n",
- " \"role\": \"assistant\",\n",
- " \"content\": full_first_response\n",
- "},\n",
- "{\n",
- " \"role\": \"user\",\n",
- " \"content\": function_results\n",
- "}]\n",
- " \n",
- "# Print Claude's response\n",
- "final_response = get_completion(messages, system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(\"------------- FINAL RESULT -------------\")\n",
- "print(final_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Congratulations on running an entire tool use chain end to end!\n",
- "\n",
- "Now what if we give Claude a question that doesn't that doesn't require using the given tool at all?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "non_multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Tell me the capital of France.\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([non_multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Success! As you can see, Claude knew not to call the function when it wasn't needed.\n",
- "\n",
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 10.2.1 - SQL](#exercise-1021---SQL)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 10.2.1 - SQL\n",
- "In this exercise, you'll be writing a tool use prompt for querying and writing to the world's smallest \"database\". Here's the initialized database, which is really just a dictionary."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "db = {\n",
- " \"users\": [\n",
- " {\"id\": 1, \"name\": \"Alice\", \"email\": \"alice@example.com\"},\n",
- " {\"id\": 2, \"name\": \"Bob\", \"email\": \"bob@example.com\"},\n",
- " {\"id\": 3, \"name\": \"Charlie\", \"email\": \"charlie@example.com\"}\n",
- " ],\n",
- " \"products\": [\n",
- " {\"id\": 1, \"name\": \"Widget\", \"price\": 9.99},\n",
- " {\"id\": 2, \"name\": \"Gadget\", \"price\": 14.99},\n",
- " {\"id\": 3, \"name\": \"Doohickey\", \"price\": 19.99}\n",
- " ]\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And here is the code for the functions that write to and from the database."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def get_user(user_id):\n",
- " for user in db[\"users\"]:\n",
- " if user[\"id\"] == user_id:\n",
- " return user\n",
- " return None\n",
- "\n",
- "def get_product(product_id):\n",
- " for product in db[\"products\"]:\n",
- " if product[\"id\"] == product_id:\n",
- " return product\n",
- " return None\n",
- "\n",
- "def add_user(name, email):\n",
- " user_id = len(db[\"users\"]) + 1\n",
- " user = {\"id\": user_id, \"name\": name, \"email\": email}\n",
- " db[\"users\"].append(user)\n",
- " return user\n",
- "\n",
- "def add_product(name, price):\n",
- " product_id = len(db[\"products\"]) + 1\n",
- " product = {\"id\": product_id, \"name\": name, \"price\": price}\n",
- " db[\"products\"].append(product)\n",
- " return product"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To solve the exercise, start by defining a system prompt like `system_prompt_tools_specific_tools` above. Make sure to include the name and description of each tool, along with the name and type and description of each parameter for each function. We've given you some starting scaffolding below."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_specific_tools_sql = \"\"\"\n",
- "\"\"\"\n",
- "\n",
- "system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools_sql"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "When you're ready, you can try out your tool definition system prompt on the examples below. Just run the below cell!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "examples = [\n",
- " \"Add a user to the database named Deborah.\",\n",
- " \"Add a product to the database named Thingo\",\n",
- " \"Tell me the name of User 2\",\n",
- " \"Tell me the name of Product 3\"\n",
- "]\n",
- "\n",
- "for example in examples:\n",
- " message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": example\n",
- " }\n",
- "\n",
- " # Get & print Claude's response\n",
- " function_calling_response = get_completion([message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- " print(example, \"\\n----------\\n\\n\", function_calling_response, \"\\n*********\\n*********\\n*********\\n\\n\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you did it right, the function calling messages should call the `add_user`, `add_product`, `get_user`, and `get_product` functions correctly.\n",
- "\n",
- "For extra credit, add some code cells and write parameter-parsing code. Then call the functions with the parameters Claude gives you to see the state of the \"database\" after the call."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want to see a possible solution, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_10_2_1_solution)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "Congratulations on learning tool use and function calling! Head over to the last appendix section if you would like to learn more about search & RAG."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_general_explanation = \"\"\"You have access to a set of functions you can use to answer the user's question. This includes access to a\n",
- "sandboxed computing environment. You do NOT currently have the ability to inspect files or interact with external\n",
- "resources, except by invoking the below functions.\n",
- "\n",
- "You can invoke one or more functions by writing a \"\" block like the following as part of your\n",
- "reply to the user:\n",
- "\n",
- "\n",
- "$PARAMETER_VALUE\n",
- "...\n",
- "\n",
- "\n",
- "...\n",
- "\n",
- "\n",
- "\n",
- "String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that\n",
- "spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular\n",
- "expressions.\n",
- "\n",
- "The output and/or any errors will appear in a subsequent \"\" block, and remain there as part of\n",
- "your reply to the user.\n",
- "You may then continue composing the rest of your reply to the user, respond to any errors, or make further function\n",
- "calls as appropriate.\n",
- "If a \"\" does NOT appear after your function calls, then they are likely malformatted and not\n",
- "recognized as a call.\"\"\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_specific_tools = \"\"\"Here are the functions available in JSONSchema format:\n",
- "\n",
- "\n",
- "calculator\n",
- "\n",
- "Calculator function for doing basic arithmetic.\n",
- "Supports addition, subtraction, multiplication\n",
- "\n",
- "\n",
- "\n",
- "first_operand\n",
- "int\n",
- "First operand (before the operator)\n",
- "\n",
- "\n",
- "second_operand\n",
- "int\n",
- "Second operand (after the operator)\n",
- "\n",
- "\n",
- "operator\n",
- "str\n",
- "The operation to perform. Must be either +, -, *, or /\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Multiply 1,984,135 by 9,343,116\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def do_pairwise_arithmetic(num1, num2, operation):\n",
- " if operation == '+':\n",
- " return num1 + num2\n",
- " elif operation == \"-\":\n",
- " return num1 - num2\n",
- " elif operation == \"*\":\n",
- " return num1 * num2\n",
- " elif operation == \"/\":\n",
- " return num1 / num2\n",
- " else:\n",
- " return \"Error: Operation not supported.\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def find_parameter(message, parameter_name):\n",
- " parameter_start_string = f\"name=\\\"{parameter_name}\\\">\"\n",
- " start = message.index(parameter_start_string)\n",
- " if start == -1:\n",
- " return None\n",
- " if start > 0:\n",
- " start = start + len(parameter_start_string)\n",
- " end = start\n",
- " while message[end] != \"<\":\n",
- " end += 1\n",
- " return message[start:end]\n",
- "\n",
- "first_operand = find_parameter(function_calling_response, \"first_operand\")\n",
- "second_operand = find_parameter(function_calling_response, \"second_operand\")\n",
- "operator = find_parameter(function_calling_response, \"operator\")\n",
- "\n",
- "if first_operand and second_operand and operator:\n",
- " result = do_pairwise_arithmetic(int(first_operand), int(second_operand), operator)\n",
- " print(\"---------------- RESULT ----------------\")\n",
- " print(f\"{result:,}\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def construct_successful_function_run_injection_prompt(invoke_results):\n",
- " constructed_prompt = (\n",
- " \"\\n\"\n",
- " + '\\n'.join(\n",
- " f\"\\n{res['tool_name']}\\n\\n{res['tool_result']}\\n\\n\"\n",
- " for res in invoke_results\n",
- " ) + \"\\n\"\n",
- " )\n",
- "\n",
- " return constructed_prompt\n",
- "\n",
- "formatted_results = [{\n",
- " 'tool_name': 'do_pairwise_arithmetic',\n",
- " 'tool_result': result\n",
- "}]\n",
- "function_results = construct_successful_function_run_injection_prompt(formatted_results)\n",
- "print(function_results)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "full_first_response = function_calling_response + \"\"\n",
- "\n",
- "# Construct the full conversation\n",
- "messages = [multiplication_message,\n",
- "{\n",
- " \"role\": \"assistant\",\n",
- " \"content\": full_first_response\n",
- "},\n",
- "{\n",
- " \"role\": \"user\",\n",
- " \"content\": function_results\n",
- "}]\n",
- " \n",
- "# Print Claude's response\n",
- "final_response = get_completion(messages, system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(\"------------- FINAL RESULT -------------\")\n",
- "print(final_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "non_multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Tell me the capital of France.\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([non_multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.11.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/anthropic/10_3_Appendix_Empirical_Performance_Evaluations.ipynb b/AmazonBedrock/anthropic/10_3_Appendix_Empirical_Performance_Evaluations.ipynb
deleted file mode 100755
index 1bc342a..0000000
--- a/AmazonBedrock/anthropic/10_3_Appendix_Empirical_Performance_Evaluations.ipynb
+++ /dev/null
@@ -1,353 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Evaluating AI Models: Code, Human, and Model-Based Grading\n",
- "\n",
- "In this notebook, we'll delve into a trio of widely-used techniques for assessing the effectiveness of AI models, like Claude v3:\n",
- "\n",
- "1. Code-based grading\n",
- "2. Human grading\n",
- "3. Model-based grading\n",
- "\n",
- "We'll illustrate each approach through examples and examine their respective advantages and limitations, when gauging AI performance."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Code-Based Grading Example: Sentiment Analysis\n",
- "\n",
- "In this example, we'll evaluate Claude's ability to classify the sentiment of movie reviews as positive or negative. We can use code to check if the model's output matches the expected sentiment."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Store the model name and AWS region for later use\n",
- "MODEL_NAME = \"anthropic.claude-3-haiku-20240307-v1:0\"\n",
- "AWS_REGION = \"us-west-2\"\n",
- "\n",
- "%store MODEL_NAME\n",
- "%store AWS_REGION"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Install the Anthropic package\n",
- "%pip install anthropic --quiet"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Import the AnthropicBedrock class and create a client instance\n",
- "from anthropic import AnthropicBedrock\n",
- "\n",
- "client = AnthropicBedrock(aws_region=AWS_REGION)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Function to build the input prompt for sentiment analysis\n",
- "def build_input_prompt(review):\n",
- " user_content = f\"\"\"Classify the sentiment of the following movie review as either 'positive' or 'negative' provide only one of those two choices:\n",
- " {review}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Define the evaluation data\n",
- "eval = [\n",
- " {\n",
- " \"review\": \"This movie was amazing! The acting was superb and the plot kept me engaged from start to finish.\",\n",
- " \"golden_answer\": \"positive\"\n",
- " },\n",
- " {\n",
- " \"review\": \"I was thoroughly disappointed by this film. The pacing was slow and the characters were one-dimensional.\",\n",
- " \"golden_answer\": \"negative\"\n",
- " }\n",
- "]\n",
- "\n",
- "# Function to get completions from the model\n",
- "def get_completion(messages):\n",
- " message = client.messages.create(\n",
- " model=MODEL_NAME,\n",
- " max_tokens=2000,\n",
- " temperature=0.0,\n",
- " messages=messages\n",
- " )\n",
- " return message.content[0].text\n",
- "\n",
- "# Get completions for each input\n",
- "outputs = [get_completion(build_input_prompt(item[\"review\"])) for item in eval]\n",
- "\n",
- "# Print the outputs and golden answers\n",
- "for output, question in zip(outputs, eval):\n",
- " print(f\"Review: {question['review']}\\nGolden Answer: {question['golden_answer']}\\nOutput: {output}\\n\")\n",
- "\n",
- "# Function to grade the completions\n",
- "def grade_completion(output, golden_answer):\n",
- " return output.lower() == golden_answer.lower()\n",
- "\n",
- "# Grade the completions and print the accuracy\n",
- "grades = [grade_completion(output, item[\"golden_answer\"]) for output, item in zip(outputs, eval)]\n",
- "print(f\"Accuracy: {sum(grades) / len(grades) * 100}%\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Human Grading Example: Essay Scoring\n",
- "\n",
- "Some tasks, like scoring essays, are difficult to evaluate with code alone. In this case, we can provide guidelines for human graders to assess the model's output."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Function to build the input prompt for essay generation\n",
- "def build_input_prompt(topic):\n",
- " user_content = f\"\"\"Write a short essay discussing the following topic:\n",
- " {topic}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Define the evaluation data\n",
- "eval = [\n",
- " {\n",
- " \"topic\": \"The importance of education in personal development and societal progress\",\n",
- " \"golden_answer\": \"A high-scoring essay should have a clear thesis, well-structured paragraphs, and persuasive examples discussing how education contributes to individual growth and broader societal advancement.\"\n",
- " }\n",
- "]\n",
- "\n",
- "# Get completions for each input\n",
- "outputs = [get_completion(build_input_prompt(item[\"topic\"])) for item in eval]\n",
- "\n",
- "# Print the outputs and golden answers\n",
- "for output, item in zip(outputs, eval):\n",
- " print(f\"Topic: {item['topic']}\\n\\nGrading Rubric:\\n {item['golden_answer']}\\n\\nModel Output:\\n{output}\\n\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Model-Based Grading Examples\n",
- "\n",
- "We can use Claude to grade its own outputs by providing the model's response and a grading rubric. This allows us to automate the evaluation of tasks that would typically require human judgment."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example 1: Summarization\n",
- "\n",
- "In this example, we'll use Claude to assess the quality of a summary it generated. This can be useful when you need to evaluate the model's ability to capture key information from a longer text concisely and accurately. By providing a rubric that outlines the essential points that should be covered, we can automate the grading process and quickly assess the model's performance on summarization tasks."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Function to build the input prompt for summarization\n",
- "def build_input_prompt(text):\n",
- " user_content = f\"\"\"Please summarize the main points of the following text:\n",
- " {text}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Function to build the grader prompt for assessing summary quality\n",
- "def build_grader_prompt(output, rubric):\n",
- " user_content = f\"\"\"Assess the quality of the following summary based on this rubric:\n",
- " {rubric}\n",
- " {output}\n",
- " Provide a score from 1-5, where 1 is poor and 5 is excellent.\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Define the evaluation data\n",
- "eval = [\n",
- " {\n",
- " \"text\": \"The Magna Carta, signed in 1215, was a pivotal document in English history. It limited the powers of the monarchy and established the principle that everyone, including the king, was subject to the law. This laid the foundation for constitutional governance and the rule of law in England and influenced legal systems worldwide.\",\n",
- " \"golden_answer\": \"A high-quality summary should concisely capture the key points: 1) The Magna Carta's significance in English history, 2) Its role in limiting monarchical power, 3) Establishing the principle of rule of law, and 4) Its influence on legal systems around the world.\"\n",
- " }\n",
- "]\n",
- "\n",
- "# Get completions for each input\n",
- "outputs = [get_completion(build_input_prompt(item[\"text\"])) for item in eval]\n",
- "\n",
- "# Grade the completions\n",
- "grades = [get_completion(build_grader_prompt(output, item[\"golden_answer\"])) for output, item in zip(outputs, eval)]\n",
- "\n",
- "# Print the summary quality score\n",
- "print(f\"Summary quality score: {grades[0]}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example 2: Fact-Checking\n",
- "\n",
- "In this example, we'll use Claude to fact-check a claim and then assess the accuracy of its fact-checking. This can be useful when you need to evaluate the model's ability to distinguish between accurate and inaccurate information. By providing a rubric that outlines the key points that should be covered in a correct fact-check, we can automate the grading process and quickly assess the model's performance on fact-checking tasks."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Function to build the input prompt for fact-checking\n",
- "def build_input_prompt(claim):\n",
- " user_content = f\"\"\"Determine if the following claim is true or false:\n",
- " {claim}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Function to build the grader prompt for assessing fact-check accuracy\n",
- "def build_grader_prompt(output, rubric):\n",
- " user_content = f\"\"\"Based on the following rubric, assess whether the fact-check is correct:\n",
- " {rubric}\n",
- " {output}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Define the evaluation data\n",
- "eval = [\n",
- " {\n",
- " \"claim\": \"The Great Wall of China is visible from space.\",\n",
- " \"golden_answer\": \"A correct fact-check should state that this claim is false. While the Great Wall is an impressive structure, it is not visible from space with the naked eye.\"\n",
- " }\n",
- "]\n",
- "\n",
- "# Get completions for each input\n",
- "outputs = [get_completion(build_input_prompt(item[\"claim\"])) for item in eval]\n",
- "\n",
- "grades = []\n",
- "for output, item in zip(outputs, eval):\n",
- " # Print the claim, fact-check, and rubric\n",
- " print(f\"Claim: {item['claim']}\\n\")\n",
- " print(f\"Fact-check: {output}]\\n\")\n",
- " print(f\"Rubric: {item['golden_answer']}\\n\")\n",
- " \n",
- " # Grade the fact-check\n",
- " grader_prompt = build_grader_prompt(output, item[\"golden_answer\"])\n",
- " grade = get_completion(grader_prompt)\n",
- " grades.append(\"correct\" in grade.lower())\n",
- "\n",
- "# Print the fact-checking accuracy\n",
- "accuracy = sum(grades) / len(grades)\n",
- "print(f\"Fact-checking accuracy: {accuracy * 100}%\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example 3: Tone Analysis\n",
- "\n",
- "In this example, we'll use Claude to analyze the tone of a given text and then assess the accuracy of its analysis. This can be useful when you need to evaluate the model's ability to identify and interpret the emotional content and attitudes expressed in a piece of text. By providing a rubric that outlines the key aspects of tone that should be identified, we can automate the grading process and quickly assess the model's performance on tone analysis tasks."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "# Function to build the input prompt for tone analysis\n",
- "def build_input_prompt(text):\n",
- " user_content = f\"\"\"Analyze the tone of the following text:\n",
- " {text}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Function to build the grader prompt for assessing tone analysis accuracy\n",
- "def build_grader_prompt(output, rubric):\n",
- " user_content = f\"\"\"Assess the accuracy of the following tone analysis based on this rubric:\n",
- " {rubric}\n",
- " {output}\"\"\"\n",
- " return [{\"role\": \"user\", \"content\": user_content}]\n",
- "\n",
- "# Define the evaluation data\n",
- "eval = [\n",
- " {\n",
- " \"text\": \"I can't believe they canceled the event at the last minute. This is completely unacceptable and unprofessional!\",\n",
- " \"golden_answer\": \"The tone analysis should identify the text as expressing frustration, anger, and disappointment. Key words like 'can't believe', 'last minute', 'unacceptable', and 'unprofessional' indicate strong negative emotions.\"\n",
- " }\n",
- "]\n",
- "\n",
- "# Get completions for each input\n",
- "outputs = [get_completion(build_input_prompt(item[\"text\"])) for item in eval]\n",
- "\n",
- "# Grade the completions\n",
- "grades = [get_completion(build_grader_prompt(output, item[\"golden_answer\"])) for output, item in zip(outputs, eval)]\n",
- "\n",
- "# Print the tone analysis quality\n",
- "print(f\"Tone analysis quality: {grades[0]}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "These examples demonstrate how code-based, human, and model-based grading can be used to evaluate AI models like Claude on various tasks. The choice of evaluation method depends on the nature of the task and the resources available. Model-based grading offers a promising approach for automating the assessment of complex tasks that would otherwise require human judgment."
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "conda_pytorch_p310",
- "language": "python",
- "name": "conda_pytorch_p310"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.10.13"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/AmazonBedrock/anthropic/10_4_Appendix_Search_and_Retrieval.ipynb b/AmazonBedrock/anthropic/10_4_Appendix_Search_and_Retrieval.ipynb
deleted file mode 100755
index acca0f3..0000000
--- a/AmazonBedrock/anthropic/10_4_Appendix_Search_and_Retrieval.ipynb
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Appendix 10.3: Search & Retrieval\n",
- "\n",
- "Did you know you can use Claude to **search through Wikipedia for you**? Claude can find and retrieve articles, at which point you can also use Claude to summarize and synthesize them, write novel content from what it found, and much more. And not just Wikipedia! You can also search over your own docs, whether stored as plain text or embedded in a vector datastore.\n",
- "\n",
- "See our [RAG cookbook examples](https://github.com/anthropics/anthropic-cookbook/blob/main/third_party/Wikipedia/wikipedia-search-cookbook.ipynb) to learn how to supplement Claude's knowledge and improve the accuracy and relevance of Claude's responses with data retrieved from vector databases, Wikipedia, the internet, and more. There, you can also learn about how to use certain [embeddings](https://docs.anthropic.com/claude/docs/embeddings) and vector database tools.\n",
- "\n",
- "If you are interested in learning about advanced RAG architectures using Claude, check out our [Claude 3 technical presentation slides on RAG architectures](https://docs.google.com/presentation/d/1zxkSI7lLUBrZycA-_znwqu8DDyVhHLkQGScvzaZrUns/edit#slide=id.g2c736259dac_63_782)."
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/boto3/01_Basic_Prompt_Structure.ipynb b/AmazonBedrock/boto3/01_Basic_Prompt_Structure.ipynb
deleted file mode 100755
index bcb43de..0000000
--- a/AmazonBedrock/boto3/01_Basic_Prompt_Structure.ipynb
+++ /dev/null
@@ -1,503 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Chapter 1: Basic Prompt Structure\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "import boto3\n",
- "import json\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Retrieve the MODEL_NAME variable from the IPython store\n",
- "%store -r MODEL_NAME\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(prompt,system=''):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"role\": \"user\", \"content\": prompt}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": system\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "Anthropic offers two APIs, the legacy [Text Completions API](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-text-completion.html) and the current [Messages API](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html). For this tutorial, we will be exclusively using the Messages API.\n",
- "\n",
- "At minimum, a call to Claude using the Messages API requires the following parameters:\n",
- "- `model`: the [API model name](https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html#model-ids-arns) of the model that you intend to call\n",
- "\n",
- "- `max_tokens`: the maximum number of tokens to generate before stopping. Note that Claude may stop before reaching this maximum. This parameter only specifies the absolute maximum number of tokens to generate. Furthermore, this is a *hard* stop, meaning that it may cause Claude to stop generating mid-word or mid-sentence.\n",
- "\n",
- "- `messages`: an array of input messages. Our models are trained to operate on alternating `user` and `assistant` conversational turns. When creating a new `Message`, you specify the prior conversational turns with the messages parameter, and the model then generates the next `Message` in the conversation.\n",
- " - Each input message must be an object with a `role` and `content`. You can specify a single `user`-role message, or you can include multiple `user` and `assistant` messages (they must alternate, if so). The first message must always use the user `role`.\n",
- "\n",
- "There are also optional parameters, such as:\n",
- "- `system`: the system prompt - more on this below.\n",
- " \n",
- "- `temperature`: the degree of variability in Claude's response. For these lessons and exercises, we have set `temperature` to 0.\n",
- "\n",
- "For a complete list of all API parameters, visit our [API documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-claude.html)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "Let's take a look at how Claude responds to some correctly-formatted prompts. For each of the following cells, run the cell (`shift+enter`), and Claude's response will appear below the block."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Hi Claude, how are you?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Can you tell me the color of the ocean?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"What year was Celine Dion born in?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's take a look at some prompts that do not include the correct Messages API formatting. For these malformatted prompts, the Messages API returns an error.\n",
- "\n",
- "First, we have an example of a Messages API call that lacks `role` and `content` fields in the `messages` array."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "> ⚠️ **Warning:** Due to the incorrect formatting of the messages parameter in the prompt, the following cell will return an error. This is expected behavior."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Get Claude's response\n",
- "body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"Hi Claude, how are you?\"}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": ''\n",
- " }\n",
- ")\n",
- "\n",
- "response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- "\n",
- "# Print Claude's response\n",
- "print(response[0].text)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here's a prompt that fails to alternate between the `user` and `assistant` roles."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "> ⚠️ **Warning:** Due to the lack of alternation between `user` and `assistant` roles, Claude will return an error message. This is expected behavior."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Get Claude's response\n",
- "body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [\n",
- " {\"role\": \"user\", \"content\": \"What year was Celine Dion born in?\"},\n",
- " {\"role\": \"user\", \"content\": \"Also, can you tell me some other facts about her?\"}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": ''\n",
- " }\n",
- ")\n",
- "\n",
- "response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- "\n",
- "# Print Claude's response\n",
- "print(response[0].text)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`user` and `assistant` messages **MUST alternate**, and messages **MUST start with a `user` turn**. You can have multiple `user` & `assistant` pairs in a prompt (as if simulating a multi-turn conversation). You can also put words into a terminal `assistant` message for Claude to continue from where you left off (more on that in later chapters).\n",
- "\n",
- "#### System Prompts\n",
- "\n",
- "You can also use **system prompts**. A system prompt is a way to **provide context, instructions, and guidelines to Claude** before presenting it with a question or task in the \"User\" turn. \n",
- "\n",
- "Structurally, system prompts exist separately from the list of `user` & `assistant` messages, and thus belong in a separate `system` parameter (take a look at the structure of the `get_completion` helper function in the [Setup](#setup) section of the notebook). \n",
- "\n",
- "Within this tutorial, wherever we might utilize a system prompt, we have provided you a `system` field in your completions function. Should you not want to use a system prompt, simply set the `SYSTEM_PROMPT` variable to an empty string."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### System Prompt Example"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"Your answer should always be a series of critical thinking questions that further the conversation (do not provide answers to your questions). Do not actually answer the user question.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"Why is the sky blue?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Why use a system prompt? A **well-written system prompt can improve Claude's performance** in a variety of ways, such as increasing Claude's ability to follow rules and instructions. For more information, visit our documentation on [how to use system prompts](https://docs.anthropic.com/claude/docs/how-to-use-system-prompts) with Claude.\n",
- "\n",
- "Now we'll dive into some exercises. If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 1.1 - Counting to Three](#exercise-11---counting-to-three)\n",
- "- [Exercise 1.2 - System Prompt](#exercise-12---system-prompt)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 1.1 - Counting to Three\n",
- "Using proper `user` / `assistant` formatting, edit the `PROMPT` below to get Claude to **count to three.** The output will also indicate whether your solution is correct."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt - this is the only field you should change\n",
- "PROMPT = \"[Replace this text]\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " pattern = re.compile(r'^(?=.*1)(?=.*2)(?=.*3).*$', re.DOTALL)\n",
- " return bool(pattern.match(text))\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n--------------------------- GRADING ---------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_1_1_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 1.2 - System Prompt\n",
- "\n",
- "Modify the `SYSTEM_PROMPT` to make Claude respond like it's a 3 year old child."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt - this is the only field you should change\n",
- "SYSTEM_PROMPT = \"[Replace this text]\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"How big is the sky?\"\n",
- "\n",
- "# Get Claude's response\n",
- "response = get_completion(PROMPT, SYSTEM_PROMPT)\n",
- "\n",
- "# Function to grade exercise correctness\n",
- "def grade_exercise(text):\n",
- " return bool(re.search(r\"giggles\", text) or re.search(r\"soo\", text))\n",
- "\n",
- "# Print Claude's response and the corresponding grade\n",
- "print(response)\n",
- "print(\"\\n--------------------------- GRADING ---------------------------\")\n",
- "print(\"This exercise has been correctly solved:\", grade_exercise(response))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want a hint, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_1_2_hint)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "If you've solved all exercises up until this point, you're ready to move to the next chapter. Happy prompting!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Hi Claude, how are you?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"Can you tell me the color of the ocean?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prompt\n",
- "PROMPT = \"What year was Celine Dion born in?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Get Claude's response\n",
- "body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [{\"Hi Claude, how are you?\"}],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": ''\n",
- " }\n",
- ")\n",
- "\n",
- "response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- "\n",
- "# Print Claude's response\n",
- "print(response[0].text)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Get Claude's response\n",
- "body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"messages\": [\n",
- " {\"role\": \"user\", \"content\": \"What year was Celine Dion born in?\"},\n",
- " {\"role\": \"user\", \"content\": \"Also, can you tell me some other facts about her?\"}\n",
- " ],\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"system\": ''\n",
- " }\n",
- ")\n",
- "\n",
- "response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- "\n",
- "# Print Claude's response\n",
- "print(response[0].text)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# System prompt\n",
- "SYSTEM_PROMPT = \"Your answer should always be a series of critical thinking questions that further the conversation (do not provide answers to your questions). Do not actually answer the user question.\"\n",
- "\n",
- "# Prompt\n",
- "PROMPT = \"Why is the sky blue?\"\n",
- "\n",
- "# Print Claude's response\n",
- "print(get_completion(PROMPT, SYSTEM_PROMPT))"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/boto3/10_2_Appendix_Tool_Use.ipynb b/AmazonBedrock/boto3/10_2_Appendix_Tool_Use.ipynb
deleted file mode 100644
index baa4800..0000000
--- a/AmazonBedrock/boto3/10_2_Appendix_Tool_Use.ipynb
+++ /dev/null
@@ -1,791 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Appendix 10.2: Tool Use\n",
- "\n",
- "- [Lesson](#lesson)\n",
- "- [Exercises](#exercises)\n",
- "- [Example Playground](#example-playground)\n",
- "\n",
- "## Setup\n",
- "\n",
- "Run the following setup cell to load your API key and establish the `get_completion` helper function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Rewrittten to call Claude 3 Sonnet, which is generally better at tool use, and include stop_sequences\n",
- "# Import python's built-in regular expression library\n",
- "import re\n",
- "import boto3\n",
- "import json\n",
- "\n",
- "# Import the hints module from the utils package\n",
- "import os\n",
- "import sys\n",
- "module_path = \"..\"\n",
- "sys.path.append(os.path.abspath(module_path))\n",
- "from utils import hints\n",
- "\n",
- "# Override the MODEL_NAME variable in the IPython store to use Sonnet instead of the Haiku model\n",
- "MODEL_NAME='anthropic.claude-3-sonnet-20240229-v1:0'\n",
- "%store -r AWS_REGION\n",
- "\n",
- "client = boto3.client('bedrock-runtime',region_name=AWS_REGION)\n",
- "\n",
- "def get_completion(messages, system_prompt=\"\", prefill=\"\", stop_sequences=None):\n",
- " body = json.dumps(\n",
- " {\n",
- " \"anthropic_version\": '',\n",
- " \"max_tokens\": 2000,\n",
- " \"temperature\": 0.0,\n",
- " \"top_p\": 1,\n",
- " \"messages\":messages,\n",
- " \"system\": system_prompt,\n",
- " \"stop_sequences\": stop_sequences\n",
- " }\n",
- " )\n",
- " response = client.invoke_model(body=body, modelId=MODEL_NAME)\n",
- " response_body = json.loads(response.get('body').read())\n",
- "\n",
- " return response_body.get('content')[0].get('text')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Lesson\n",
- "\n",
- "While it might seem conceptually complex at first, tool use, a.k.a. function calling, is actually quite simple! You already know all the skills necessary to implement tool use, which is really just a combination of substitution and prompt chaining.\n",
- "\n",
- "In previous substitution exercises, we substituted text into prompts. With tool use, we substitute tool or function results into prompts. Claude can't literally call or access tools and functions. Instead, we have Claude:\n",
- "1. Output the tool name and arguments it wants to call\n",
- "2. Halt any further response generation while the tool is called\n",
- "3. Then we reprompt with the appended tool results"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Function calling is useful because it expands Claude's capabilities and enables Claude to handle much more complex, multi-step tasks.\n",
- "Some examples of functions you can give Claude:\n",
- "- Calculator\n",
- "- Word counter\n",
- "- SQL database querying and data retrieval\n",
- "- Weather API"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can get Claude to do tool use by combining these two elements:\n",
- "\n",
- "1. A system prompt, in which we give Claude an explanation of the concept of tool use as well as a detailed descriptive list of the tools it has access to\n",
- "2. The control logic with which to orchestrate and execute Claude's tool use requests"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Tool use roadmap\n",
- "\n",
- "*This lesson teaches our current tool use format. However, we will be updating and improving tool use functionality in the near future, including:*\n",
- "* *A more streamlined format for function definitions and calls*\n",
- "* *More robust error handilgj and edge case coverage*\n",
- "* *Tighter integration with the rest of our API*\n",
- "* *Better reliability and performance, especially for more complex tool use tasks*"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Examples\n",
- "\n",
- "To enable tool use in Claude, we start with the system prompt. In this special tool use system prompt, wet tell Claude:\n",
- "* The basic premise of tool use and what it entails\n",
- "* How Claude can call and use the tools it's been given\n",
- "* A detailed list of tools it has access to in this specific scenario \n",
- "\n",
- "Here's the first part of the system prompt, explaining tool use to Claude. This part of the system prompt is generalizable across all instances of prompting Claude for tool use. The tool calling structure we're giving Claude (` [...] `) is a structure Claude has been specifically trained to use, so we recommend that you stick with this."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_general_explanation = \"\"\"You have access to a set of functions you can use to answer the user's question. This includes access to a\n",
- "sandboxed computing environment. You do NOT currently have the ability to inspect files or interact with external\n",
- "resources, except by invoking the below functions.\n",
- "\n",
- "You can invoke one or more functions by writing a \"\" block like the following as part of your\n",
- "reply to the user:\n",
- "\n",
- "\n",
- "$PARAMETER_VALUE\n",
- "...\n",
- "\n",
- "\n",
- "...\n",
- "\n",
- "\n",
- "\n",
- "String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that\n",
- "spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular\n",
- "expressions.\n",
- "\n",
- "The output and/or any errors will appear in a subsequent \"\" block, and remain there as part of\n",
- "your reply to the user.\n",
- "You may then continue composing the rest of your reply to the user, respond to any errors, or make further function\n",
- "calls as appropriate.\n",
- "If a \"\" does NOT appear after your function calls, then they are likely malformatted and not\n",
- "recognized as a call.\"\"\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here's the second part of the system prompt, which defines the exact tools Claude has access to in this specific situation. In this example, we will be giving Claude a calculator tool, which takes three parameters: two operands and an operator. \n",
- "\n",
- "Then we combine the two parts of the system prompt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_specific_tools = \"\"\"Here are the functions available in JSONSchema format:\n",
- "\n",
- "\n",
- "calculator\n",
- "\n",
- "Calculator function for doing basic arithmetic.\n",
- "Supports addition, subtraction, multiplication\n",
- "\n",
- "\n",
- "\n",
- "first_operand\n",
- "int\n",
- "First operand (before the operator)\n",
- "\n",
- "\n",
- "second_operand\n",
- "int\n",
- "Second operand (after the operator)\n",
- "\n",
- "\n",
- "operator\n",
- "str\n",
- "The operation to perform. Must be either +, -, *, or /\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can give Claude a question that requires use of the `calculator` tool. We will use `` in `stop_sequences` to detect if and when Claude calls the function."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Multiply 1,984,135 by 9,343,116\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now, we can extract out the parameters from Claude's function call and actually run the function on Claude's behalf.\n",
- "\n",
- "First we'll define the function's code."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def do_pairwise_arithmetic(num1, num2, operation):\n",
- " if operation == '+':\n",
- " return num1 + num2\n",
- " elif operation == \"-\":\n",
- " return num1 - num2\n",
- " elif operation == \"*\":\n",
- " return num1 * num2\n",
- " elif operation == \"/\":\n",
- " return num1 / num2\n",
- " else:\n",
- " return \"Error: Operation not supported.\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Then we'll extract the parameters from Claude's function call response. If all the parameters exist, we run the calculator tool."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def find_parameter(message, parameter_name):\n",
- " parameter_start_string = f\"name=\\\"{parameter_name}\\\">\"\n",
- " start = message.index(parameter_start_string)\n",
- " if start == -1:\n",
- " return None\n",
- " if start > 0:\n",
- " start = start + len(parameter_start_string)\n",
- " end = start\n",
- " while message[end] != \"<\":\n",
- " end += 1\n",
- " return message[start:end]\n",
- "\n",
- "first_operand = find_parameter(function_calling_response, \"first_operand\")\n",
- "second_operand = find_parameter(function_calling_response, \"second_operand\")\n",
- "operator = find_parameter(function_calling_response, \"operator\")\n",
- "\n",
- "if first_operand and second_operand and operator:\n",
- " result = do_pairwise_arithmetic(int(first_operand), int(second_operand), operator)\n",
- " print(\"---------------- RESULT ----------------\")\n",
- " print(f\"{result:,}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that we have a result, we have to properly format that result so that when we pass it back to Claude, Claude understands what tool that result is in relation to. There is a set format for this that Claude has been trained to recognize:\n",
- "```\n",
- "\n",
- "\n",
- "{TOOL_NAME}\n",
- "\n",
- "{TOOL_RESULT}\n",
- "\n",
- "\n",
- "\n",
- "```\n",
- "\n",
- "Run the cell below to format the above tool result into this structure."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def construct_successful_function_run_injection_prompt(invoke_results):\n",
- " constructed_prompt = (\n",
- " \"\\n\"\n",
- " + '\\n'.join(\n",
- " f\"\\n{res['tool_name']}\\n\\n{res['tool_result']}\\n\\n\"\n",
- " for res in invoke_results\n",
- " ) + \"\\n\"\n",
- " )\n",
- "\n",
- " return constructed_prompt\n",
- "\n",
- "formatted_results = [{\n",
- " 'tool_name': 'do_pairwise_arithmetic',\n",
- " 'tool_result': result\n",
- "}]\n",
- "function_results = construct_successful_function_run_injection_prompt(formatted_results)\n",
- "print(function_results)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now all we have to do is send this result back to Claude by appending the result to the same message chain as before, and we're good!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "full_first_response = function_calling_response + \"\"\n",
- "\n",
- "# Construct the full conversation\n",
- "messages = [multiplication_message,\n",
- "{\n",
- " \"role\": \"assistant\",\n",
- " \"content\": full_first_response\n",
- "},\n",
- "{\n",
- " \"role\": \"user\",\n",
- " \"content\": function_results\n",
- "}]\n",
- " \n",
- "# Print Claude's response\n",
- "final_response = get_completion(messages, system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(\"------------- FINAL RESULT -------------\")\n",
- "print(final_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Congratulations on running an entire tool use chain end to end!\n",
- "\n",
- "Now what if we give Claude a question that doesn't that doesn't require using the given tool at all?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "non_multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Tell me the capital of France.\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([non_multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Success! As you can see, Claude knew not to call the function when it wasn't needed.\n",
- "\n",
- "If you would like to experiment with the lesson prompts without changing any content above, scroll all the way to the bottom of the lesson notebook to visit the [**Example Playground**](#example-playground)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Exercises\n",
- "- [Exercise 10.2.1 - SQL](#exercise-1021---SQL)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercise 10.2.1 - SQL\n",
- "In this exercise, you'll be writing a tool use prompt for querying and writing to the world's smallest \"database\". Here's the initialized database, which is really just a dictionary."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "db = {\n",
- " \"users\": [\n",
- " {\"id\": 1, \"name\": \"Alice\", \"email\": \"alice@example.com\"},\n",
- " {\"id\": 2, \"name\": \"Bob\", \"email\": \"bob@example.com\"},\n",
- " {\"id\": 3, \"name\": \"Charlie\", \"email\": \"charlie@example.com\"}\n",
- " ],\n",
- " \"products\": [\n",
- " {\"id\": 1, \"name\": \"Widget\", \"price\": 9.99},\n",
- " {\"id\": 2, \"name\": \"Gadget\", \"price\": 14.99},\n",
- " {\"id\": 3, \"name\": \"Doohickey\", \"price\": 19.99}\n",
- " ]\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And here is the code for the functions that write to and from the database."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def get_user(user_id):\n",
- " for user in db[\"users\"]:\n",
- " if user[\"id\"] == user_id:\n",
- " return user\n",
- " return None\n",
- "\n",
- "def get_product(product_id):\n",
- " for product in db[\"products\"]:\n",
- " if product[\"id\"] == product_id:\n",
- " return product\n",
- " return None\n",
- "\n",
- "def add_user(name, email):\n",
- " user_id = len(db[\"users\"]) + 1\n",
- " user = {\"id\": user_id, \"name\": name, \"email\": email}\n",
- " db[\"users\"].append(user)\n",
- " return user\n",
- "\n",
- "def add_product(name, price):\n",
- " product_id = len(db[\"products\"]) + 1\n",
- " product = {\"id\": product_id, \"name\": name, \"price\": price}\n",
- " db[\"products\"].append(product)\n",
- " return product"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To solve the exercise, start by defining a system prompt like `system_prompt_tools_specific_tools` above. Make sure to include the name and description of each tool, along with the name and type and description of each parameter for each function. We've given you some starting scaffolding below."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_specific_tools_sql = \"\"\"\n",
- "\"\"\"\n",
- "\n",
- "system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools_sql"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "When you're ready, you can try out your tool definition system prompt on the examples below. Just run the below cell!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "examples = [\n",
- " \"Add a user to the database named Deborah.\",\n",
- " \"Add a product to the database named Thingo\",\n",
- " \"Tell me the name of User 2\",\n",
- " \"Tell me the name of Product 3\"\n",
- "]\n",
- "\n",
- "for example in examples:\n",
- " message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": example\n",
- " }\n",
- "\n",
- " # Get & print Claude's response\n",
- " function_calling_response = get_completion([message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- " print(example, \"\\n----------\\n\\n\", function_calling_response, \"\\n*********\\n*********\\n*********\\n\\n\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you did it right, the function calling messages should call the `add_user`, `add_product`, `get_user`, and `get_product` functions correctly.\n",
- "\n",
- "For extra credit, add some code cells and write parameter-parsing code. Then call the functions with the parameters Claude gives you to see the state of the \"database\" after the call."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "❓ If you want to see a possible solution, run the cell below!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(hints.exercise_10_2_1_solution)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Congrats!\n",
- "\n",
- "Congratulations on learning tool use and function calling! Head over to the last appendix section if you would like to learn more about search & RAG."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "---\n",
- "\n",
- "## Example Playground\n",
- "\n",
- "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_general_explanation = \"\"\"You have access to a set of functions you can use to answer the user's question. This includes access to a\n",
- "sandboxed computing environment. You do NOT currently have the ability to inspect files or interact with external\n",
- "resources, except by invoking the below functions.\n",
- "\n",
- "You can invoke one or more functions by writing a \"\" block like the following as part of your\n",
- "reply to the user:\n",
- "\n",
- "\n",
- "$PARAMETER_VALUE\n",
- "...\n",
- "\n",
- "\n",
- "...\n",
- "\n",
- "\n",
- "\n",
- "String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that\n",
- "spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular\n",
- "expressions.\n",
- "\n",
- "The output and/or any errors will appear in a subsequent \"\" block, and remain there as part of\n",
- "your reply to the user.\n",
- "You may then continue composing the rest of your reply to the user, respond to any errors, or make further function\n",
- "calls as appropriate.\n",
- "If a \"\" does NOT appear after your function calls, then they are likely malformatted and not\n",
- "recognized as a call.\"\"\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "system_prompt_tools_specific_tools = \"\"\"Here are the functions available in JSONSchema format:\n",
- "\n",
- "\n",
- "calculator\n",
- "\n",
- "Calculator function for doing basic arithmetic.\n",
- "Supports addition, subtraction, multiplication\n",
- "\n",
- "\n",
- "\n",
- "first_operand\n",
- "int\n",
- "First operand (before the operator)\n",
- "\n",
- "\n",
- "second_operand\n",
- "int\n",
- "Second operand (after the operator)\n",
- "\n",
- "\n",
- "operator\n",
- "str\n",
- "The operation to perform. Must be either +, -, *, or /\n",
- "\n",
- "\n",
- "\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Multiply 1,984,135 by 9,343,116\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def do_pairwise_arithmetic(num1, num2, operation):\n",
- " if operation == '+':\n",
- " return num1 + num2\n",
- " elif operation == \"-\":\n",
- " return num1 - num2\n",
- " elif operation == \"*\":\n",
- " return num1 * num2\n",
- " elif operation == \"/\":\n",
- " return num1 / num2\n",
- " else:\n",
- " return \"Error: Operation not supported.\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def find_parameter(message, parameter_name):\n",
- " parameter_start_string = f\"name=\\\"{parameter_name}\\\">\"\n",
- " start = message.index(parameter_start_string)\n",
- " if start == -1:\n",
- " return None\n",
- " if start > 0:\n",
- " start = start + len(parameter_start_string)\n",
- " end = start\n",
- " while message[end] != \"<\":\n",
- " end += 1\n",
- " return message[start:end]\n",
- "\n",
- "first_operand = find_parameter(function_calling_response, \"first_operand\")\n",
- "second_operand = find_parameter(function_calling_response, \"second_operand\")\n",
- "operator = find_parameter(function_calling_response, \"operator\")\n",
- "\n",
- "if first_operand and second_operand and operator:\n",
- " result = do_pairwise_arithmetic(int(first_operand), int(second_operand), operator)\n",
- " print(\"---------------- RESULT ----------------\")\n",
- " print(f\"{result:,}\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def construct_successful_function_run_injection_prompt(invoke_results):\n",
- " constructed_prompt = (\n",
- " \"\\n\"\n",
- " + '\\n'.join(\n",
- " f\"\\n{res['tool_name']}\\n\\n{res['tool_result']}\\n\\n\"\n",
- " for res in invoke_results\n",
- " ) + \"\\n\"\n",
- " )\n",
- "\n",
- " return constructed_prompt\n",
- "\n",
- "formatted_results = [{\n",
- " 'tool_name': 'do_pairwise_arithmetic',\n",
- " 'tool_result': result\n",
- "}]\n",
- "function_results = construct_successful_function_run_injection_prompt(formatted_results)\n",
- "print(function_results)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "full_first_response = function_calling_response + \"\"\n",
- "\n",
- "# Construct the full conversation\n",
- "messages = [multiplication_message,\n",
- "{\n",
- " \"role\": \"assistant\",\n",
- " \"content\": full_first_response\n",
- "},\n",
- "{\n",
- " \"role\": \"user\",\n",
- " \"content\": function_results\n",
- "}]\n",
- " \n",
- "# Print Claude's response\n",
- "final_response = get_completion(messages, system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(\"------------- FINAL RESULT -------------\")\n",
- "print(final_response)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "non_multiplication_message = {\n",
- " \"role\": \"user\",\n",
- " \"content\": \"Tell me the capital of France.\"\n",
- "}\n",
- "\n",
- "stop_sequences = [\"\"]\n",
- "\n",
- "# Get Claude's response\n",
- "function_calling_response = get_completion([non_multiplication_message], system_prompt=system_prompt, stop_sequences=stop_sequences)\n",
- "print(function_calling_response)"
- ]
- }
- ],
- "metadata": {
- "language_info": {
- "name": "python"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/AmazonBedrock/images/br_messages_diagram.png b/AmazonBedrock/images/br_messages_diagram.png
new file mode 100644
index 0000000..4b98093
Binary files /dev/null and b/AmazonBedrock/images/br_messages_diagram.png differ
diff --git a/AmazonBedrock/images/br_wiki_messages.png b/AmazonBedrock/images/br_wiki_messages.png
new file mode 100644
index 0000000..ad0c119
Binary files /dev/null and b/AmazonBedrock/images/br_wiki_messages.png differ
diff --git a/AmazonBedrock/images/calculator_diagram.png b/AmazonBedrock/images/calculator_diagram.png
new file mode 100644
index 0000000..21b411f
Binary files /dev/null and b/AmazonBedrock/images/calculator_diagram.png differ
diff --git a/AmazonBedrock/images/chat_diagram.png b/AmazonBedrock/images/chat_diagram.png
new file mode 100644
index 0000000..50c2c2a
Binary files /dev/null and b/AmazonBedrock/images/chat_diagram.png differ
diff --git a/AmazonBedrock/images/chickens_calculator.png b/AmazonBedrock/images/chickens_calculator.png
new file mode 100644
index 0000000..c18c3b9
Binary files /dev/null and b/AmazonBedrock/images/chickens_calculator.png differ
diff --git a/AmazonBedrock/images/conversation1.png b/AmazonBedrock/images/conversation1.png
new file mode 100644
index 0000000..be59d8a
Binary files /dev/null and b/AmazonBedrock/images/conversation1.png differ
diff --git a/AmazonBedrock/images/conversation10.png b/AmazonBedrock/images/conversation10.png
new file mode 100644
index 0000000..46bfabd
Binary files /dev/null and b/AmazonBedrock/images/conversation10.png differ
diff --git a/AmazonBedrock/images/conversation2.png b/AmazonBedrock/images/conversation2.png
new file mode 100644
index 0000000..5d6a24f
Binary files /dev/null and b/AmazonBedrock/images/conversation2.png differ
diff --git a/AmazonBedrock/images/conversation3.png b/AmazonBedrock/images/conversation3.png
new file mode 100644
index 0000000..f4953f6
Binary files /dev/null and b/AmazonBedrock/images/conversation3.png differ
diff --git a/AmazonBedrock/images/conversation4.png b/AmazonBedrock/images/conversation4.png
new file mode 100644
index 0000000..43e3d79
Binary files /dev/null and b/AmazonBedrock/images/conversation4.png differ
diff --git a/AmazonBedrock/images/conversation5.png b/AmazonBedrock/images/conversation5.png
new file mode 100644
index 0000000..6ad5eb7
Binary files /dev/null and b/AmazonBedrock/images/conversation5.png differ
diff --git a/AmazonBedrock/images/conversation6.png b/AmazonBedrock/images/conversation6.png
new file mode 100644
index 0000000..0f791e3
Binary files /dev/null and b/AmazonBedrock/images/conversation6.png differ
diff --git a/AmazonBedrock/images/conversation7.png b/AmazonBedrock/images/conversation7.png
new file mode 100644
index 0000000..d1a3776
Binary files /dev/null and b/AmazonBedrock/images/conversation7.png differ
diff --git a/AmazonBedrock/images/conversation8.png b/AmazonBedrock/images/conversation8.png
new file mode 100644
index 0000000..3c76872
Binary files /dev/null and b/AmazonBedrock/images/conversation8.png differ
diff --git a/AmazonBedrock/images/conversation9.png b/AmazonBedrock/images/conversation9.png
new file mode 100644
index 0000000..434144b
Binary files /dev/null and b/AmazonBedrock/images/conversation9.png differ
diff --git a/AmazonBedrock/images/db_tool.png b/AmazonBedrock/images/db_tool.png
new file mode 100644
index 0000000..770e401
Binary files /dev/null and b/AmazonBedrock/images/db_tool.png differ
diff --git a/AmazonBedrock/images/exercise_conversation.png b/AmazonBedrock/images/exercise_conversation.png
new file mode 100644
index 0000000..b69c771
Binary files /dev/null and b/AmazonBedrock/images/exercise_conversation.png differ
diff --git a/AmazonBedrock/images/messages_diagram.png b/AmazonBedrock/images/messages_diagram.png
new file mode 100644
index 0000000..72080fd
Binary files /dev/null and b/AmazonBedrock/images/messages_diagram.png differ
diff --git a/AmazonBedrock/images/research_reading.png b/AmazonBedrock/images/research_reading.png
new file mode 100644
index 0000000..f818a30
Binary files /dev/null and b/AmazonBedrock/images/research_reading.png differ
diff --git a/AmazonBedrock/images/stock_tool.png b/AmazonBedrock/images/stock_tool.png
new file mode 100644
index 0000000..8c7be9a
Binary files /dev/null and b/AmazonBedrock/images/stock_tool.png differ
diff --git a/AmazonBedrock/images/structured_response.png b/AmazonBedrock/images/structured_response.png
new file mode 100644
index 0000000..709fc3a
Binary files /dev/null and b/AmazonBedrock/images/structured_response.png differ
diff --git a/AmazonBedrock/images/tool_choice.png b/AmazonBedrock/images/tool_choice.png
new file mode 100644
index 0000000..db92daa
Binary files /dev/null and b/AmazonBedrock/images/tool_choice.png differ
diff --git a/AmazonBedrock/images/tool_flow_diagram.png b/AmazonBedrock/images/tool_flow_diagram.png
new file mode 100644
index 0000000..388bdde
Binary files /dev/null and b/AmazonBedrock/images/tool_flow_diagram.png differ
diff --git a/AmazonBedrock/images/tool_use_diagram.png b/AmazonBedrock/images/tool_use_diagram.png
new file mode 100644
index 0000000..a62b61f
Binary files /dev/null and b/AmazonBedrock/images/tool_use_diagram.png differ
diff --git a/AmazonBedrock/images/tool_use_examples.png b/AmazonBedrock/images/tool_use_examples.png
new file mode 100644
index 0000000..9ac09e9
Binary files /dev/null and b/AmazonBedrock/images/tool_use_examples.png differ
diff --git a/AmazonBedrock/images/tool_use_flow.png b/AmazonBedrock/images/tool_use_flow.png
new file mode 100644
index 0000000..4d1e1d0
Binary files /dev/null and b/AmazonBedrock/images/tool_use_flow.png differ
diff --git a/AmazonBedrock/images/wiki_diagram.png b/AmazonBedrock/images/wiki_diagram.png
new file mode 100644
index 0000000..c292ec9
Binary files /dev/null and b/AmazonBedrock/images/wiki_diagram.png differ
diff --git a/AmazonBedrock/images/wiki_messages.png b/AmazonBedrock/images/wiki_messages.png
new file mode 100644
index 0000000..4536a19
Binary files /dev/null and b/AmazonBedrock/images/wiki_messages.png differ
diff --git a/AmazonBedrock/images/wikipedia_diagram.png b/AmazonBedrock/images/wikipedia_diagram.png
new file mode 100644
index 0000000..b6a629c
Binary files /dev/null and b/AmazonBedrock/images/wikipedia_diagram.png differ
diff --git a/AmazonBedrock/output/.ipynb_checkpoints/research_reading-checkpoint.md b/AmazonBedrock/output/.ipynb_checkpoints/research_reading-checkpoint.md
new file mode 100644
index 0000000..9968639
--- /dev/null
+++ b/AmazonBedrock/output/.ipynb_checkpoints/research_reading-checkpoint.md
@@ -0,0 +1,22 @@
+## Pirates Across The World
+* [Piracy](https://en.wikipedia.org/wiki/Piracy)
+* [Golden Age of Piracy](https://en.wikipedia.org/wiki/Golden_Age_of_Piracy)
+* [List of pirates](https://en.wikipedia.org/wiki/List_of_pirates)
+* [Piracy in the Caribbean](https://en.wikipedia.org/wiki/Piracy_in_the_Caribbean)
+* [Piracy in the Strait of Malacca](https://en.wikipedia.org/wiki/Piracy_in_the_Strait_of_Malacca)
+* [Piracy in the 21st century](https://en.wikipedia.org/wiki/Piracy_in_the_21st_century)
+* [Republic of Pirates](https://en.wikipedia.org/wiki/Republic_of_Pirates)
+
+
+## History of Hawaii
+* [History of Hawaii](https://en.wikipedia.org/wiki/History_of_Hawaii)
+* [Hawaiian Kingdom](https://en.wikipedia.org/wiki/Hawaiian_Kingdom)
+* [Newlands Resolution](https://en.wikipedia.org/wiki/Newlands_Resolution)
+
+
+## Animal consciousness
+* [Consciousness](https://en.wikipedia.org/wiki/Consciousness)
+* [Animal cognition](https://en.wikipedia.org/wiki/Animal_cognition)
+* [Emotion in animals](https://en.wikipedia.org/wiki/Emotion_in_animals)
+
+
diff --git a/AmazonBedrock/output/research_reading.md b/AmazonBedrock/output/research_reading.md
new file mode 100644
index 0000000..9968639
--- /dev/null
+++ b/AmazonBedrock/output/research_reading.md
@@ -0,0 +1,22 @@
+## Pirates Across The World
+* [Piracy](https://en.wikipedia.org/wiki/Piracy)
+* [Golden Age of Piracy](https://en.wikipedia.org/wiki/Golden_Age_of_Piracy)
+* [List of pirates](https://en.wikipedia.org/wiki/List_of_pirates)
+* [Piracy in the Caribbean](https://en.wikipedia.org/wiki/Piracy_in_the_Caribbean)
+* [Piracy in the Strait of Malacca](https://en.wikipedia.org/wiki/Piracy_in_the_Strait_of_Malacca)
+* [Piracy in the 21st century](https://en.wikipedia.org/wiki/Piracy_in_the_21st_century)
+* [Republic of Pirates](https://en.wikipedia.org/wiki/Republic_of_Pirates)
+
+
+## History of Hawaii
+* [History of Hawaii](https://en.wikipedia.org/wiki/History_of_Hawaii)
+* [Hawaiian Kingdom](https://en.wikipedia.org/wiki/Hawaiian_Kingdom)
+* [Newlands Resolution](https://en.wikipedia.org/wiki/Newlands_Resolution)
+
+
+## Animal consciousness
+* [Consciousness](https://en.wikipedia.org/wiki/Consciousness)
+* [Animal cognition](https://en.wikipedia.org/wiki/Animal_cognition)
+* [Emotion in animals](https://en.wikipedia.org/wiki/Emotion_in_animals)
+
+
diff --git a/AmazonBedrock/requirements.txt b/AmazonBedrock/requirements.txt
index 0c4b3a5..59c75e0 100644
--- a/AmazonBedrock/requirements.txt
+++ b/AmazonBedrock/requirements.txt
@@ -1,5 +1,12 @@
-awscli==1.32.74
-boto3==1.34.74
-botocore==1.34.74
-anthropic==0.21.3
+python-dotenv==1.0.1
+wikipedia==1.4.0
+awscli==1.33.4
+boto3==1.34.122
+botocore==1.34.122
+console==0.9907
+panel==1.4.3
pickleshare==0.7.5
+ipython==8.25.0
+pandas==1.5.3
+jedi===0.17.2
+mkl==2024.1.0
\ No newline at end of file
diff --git a/AmazonBedrock/toolUse_order_bot/final_order_bot_converse_api.py b/AmazonBedrock/toolUse_order_bot/final_order_bot_converse_api.py
new file mode 100644
index 0000000..2901967
--- /dev/null
+++ b/AmazonBedrock/toolUse_order_bot/final_order_bot_converse_api.py
@@ -0,0 +1,260 @@
+import re
+import boto3
+import json
+from datetime import datetime
+from botocore.exceptions import ClientError
+
+session = boto3.Session()
+region = session.region_name
+
+modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'
+
+bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)
+
+class FakeDatabase:
+ def __init__(self):
+ self.customers = [
+ {"id": "1213210", "name": "John Doe", "email": "john@gmail.com", "phone": "123-456-7890", "username": "johndoe"},
+ {"id": "2837622", "name": "Priya Patel", "email": "priya@candy.com", "phone": "987-654-3210", "username": "priya123"},
+ {"id": "3924156", "name": "Liam Nguyen", "email": "lnguyen@yahoo.com", "phone": "555-123-4567", "username": "liamn"},
+ {"id": "4782901", "name": "Aaliyah Davis", "email": "aaliyahd@hotmail.com", "phone": "111-222-3333", "username": "adavis"},
+ {"id": "5190753", "name": "Hiroshi Nakamura", "email": "hiroshi@gmail.com", "phone": "444-555-6666", "username": "hiroshin"},
+ {"id": "6824095", "name": "Fatima Ahmed", "email": "fatimaa@outlook.com", "phone": "777-888-9999", "username": "fatimaahmed"},
+ {"id": "7135680", "name": "Alejandro Rodriguez", "email": "arodriguez@protonmail.com", "phone": "222-333-4444", "username": "alexr"},
+ {"id": "8259147", "name": "Megan Anderson", "email": "megana@gmail.com", "phone": "666-777-8888", "username": "manderson"},
+ {"id": "9603481", "name": "Kwame Osei", "email": "kwameo@yahoo.com", "phone": "999-000-1111", "username": "kwameo"},
+ {"id": "1057426", "name": "Mei Lin", "email": "meilin@gmail.com", "phone": "333-444-5555", "username": "mlin"}
+ ]
+
+ self.orders = [
+ {"id": "24601", "customer_id": "1213210", "product": "Wireless Headphones", "quantity": 1, "price": 79.99, "status": "Shipped"},
+ {"id": "13579", "customer_id": "1213210", "product": "Smartphone Case", "quantity": 2, "price": 19.99, "status": "Processing"},
+ {"id": "97531", "customer_id": "2837622", "product": "Bluetooth Speaker", "quantity": 1, "price": "49.99", "status": "Shipped"},
+ {"id": "86420", "customer_id": "3924156", "product": "Fitness Tracker", "quantity": 1, "price": 129.99, "status": "Delivered"},
+ {"id": "54321", "customer_id": "4782901", "product": "Laptop Sleeve", "quantity": 3, "price": 24.99, "status": "Shipped"},
+ {"id": "19283", "customer_id": "5190753", "product": "Wireless Mouse", "quantity": 1, "price": 34.99, "status": "Processing"},
+ {"id": "74651", "customer_id": "6824095", "product": "Gaming Keyboard", "quantity": 1, "price": 89.99, "status": "Delivered"},
+ {"id": "30298", "customer_id": "7135680", "product": "Portable Charger", "quantity": 2, "price": 29.99, "status": "Shipped"},
+ {"id": "47652", "customer_id": "8259147", "product": "Smartwatch", "quantity": 1, "price": 199.99, "status": "Processing"},
+ {"id": "61984", "customer_id": "9603481", "product": "Noise-Cancelling Headphones", "quantity": 1, "price": 149.99, "status": "Shipped"},
+ {"id": "58243", "customer_id": "1057426", "product": "Wireless Earbuds", "quantity": 2, "price": 99.99, "status": "Delivered"},
+ {"id": "90357", "customer_id": "1213210", "product": "Smartphone Case", "quantity": 1, "price": 19.99, "status": "Shipped"},
+ {"id": "28164", "customer_id": "2837622", "product": "Wireless Headphones", "quantity": 2, "price": 79.99, "status": "Processing"}
+ ]
+
+ def get_user(self, key, value):
+ if key in {"email", "phone", "username"}:
+ for customer in self.customers:
+ if customer[key] == value:
+ return customer
+ return f"Couldn't find a user with {key} of {value}"
+ else:
+ raise ValueError(f"Invalid key: {key}")
+
+ return None
+
+ def get_order_by_id(self, order_id):
+ for order in self.orders:
+ if order["id"] == order_id:
+ return order
+ return None
+
+ def get_customer_orders(self, customer_id):
+ return [order for order in self.orders if order["customer_id"] == customer_id]
+
+ def cancel_order(self, order_id):
+ order = self.get_order_by_id(order_id)
+ if order:
+ if order["status"] == "Processing":
+ order["status"] = "Cancelled"
+ return "Cancelled the order"
+ else:
+ return "Order has already shipped. Can't cancel it."
+ return "Can't find that order!"
+
+toolConfig = {
+ 'tools': [
+ {
+ 'toolSpec': {
+ 'name': 'get_user',
+ 'description': 'Looks up a user by email, phone, or username.',
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'key': {
+ 'type': 'string',
+ 'enum': ['email', 'phone', 'username'],
+ 'description': 'The attribute to search for a user by (email, phone, or username).'
+ },
+ 'value': {
+ 'type': 'string',
+ 'description': 'The value to match for the specified attribute.'
+ }
+ },
+ 'required': ['key', 'value']
+ }
+ }
+ }
+ },
+ {
+ 'toolSpec': {
+ 'name': 'get_order_by_id',
+ 'description': 'Retrieves the details of a specific order based on the order ID. Returns the order ID, product name, quantity, price, and order status.',
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'order_id': {
+ 'type': 'string',
+ 'description': 'The unique identifier for the order.'
+ }
+ },
+ 'required': ['order_id']
+ }
+ }
+ }
+ },
+ {
+ 'toolSpec': {
+ 'name': 'get_customer_orders',
+ 'description': "Retrieves the list of orders belonging to a user based on a user's customer id.",
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'customer_id': {
+ 'type': 'string',
+ 'description': 'The customer_id belonging to the user'
+ }
+ },
+ 'required': ['customer_id']
+ }
+ }
+ }
+ },
+ {
+ 'toolSpec': {
+ 'name': 'cancel_order',
+ 'description': "Cancels an order based on a provided order_id. Only orders that are 'processing' can be cancelled",
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'order_id': {
+ 'type': 'string',
+ 'description': 'The order_id pertaining to a particular order'
+ }
+ },
+ 'required': ['order_id']
+ }
+ }
+ }
+ }
+ ],
+ 'toolChoice': {
+ 'auto': {}
+ }
+}
+
+
+db = FakeDatabase()
+
+def process_tool_call(tool_name, tool_input):
+ if tool_name == "get_user":
+ return db.get_user(tool_input["key"], tool_input["value"])
+ elif tool_name == "get_order_by_id":
+ return db.get_order_by_id(tool_input["order_id"])
+ elif tool_name == "get_customer_orders":
+ return db.get_customer_orders(tool_input["customer_id"])
+ elif tool_name == "cancel_order":
+ return db.cancel_order(tool_input["order_id"])
+
+
+def extract_reply(text):
+ pattern = r'(.*?)'
+ match = re.search(pattern, text, re.DOTALL)
+ if match:
+ return match.group(1)
+ else:
+ return None
+
+RED = "\033[91m"
+GREEN = "\033[92m"
+YELLOW = "\033[93m"
+BLUE = "\033[94m"
+MAGENTA = "\033[95m"
+CYAN = "\033[96m"
+WHITE = "\033[97m"
+RESET = "\033[0m"
+BOLD = "\033[1m"
+UNDERLINE = "\033[4m"
+
+def start_chat():
+ system_prompt = """You are a customer support chat bot for an online retailer called TechNova.
+Your job is to help users look up their account, orders, and cancel orders.
+Be helpful and brief in your responses.
+You have access to a set of tools, but only use them when needed.
+If you do not have enough information to use a tool correctly, ask a user follow up questions to get the required inputs.
+Do not call any of the tools unless you have the required data from a user.
+Do not make any assumptions about things like username, order id, phone number, email, etc. without explicitly asking a user to provide their information first.
+
+In each conversational turn, you will begin by thinking about your response. Once you're done, you will write a user-facing response. It's important to place all user-facing conversational responses in XML tags to make them easy to parse."""
+
+
+ print(BLUE + UNDERLINE + "\nWelcome to the TechNova Customer Support" + RESET)
+ print(BLUE + UNDERLINE + "========================================" + RESET)
+ user_message = input(GREEN + BOLD + "\nUser: " + RESET)
+ messages = [{"role": "user", "content": [{"text": user_message}]}]
+
+ while True:
+ if messages[-1].get("role") == "assistant":
+ user_message = input(GREEN + BOLD + "\nUser: " + RESET)
+ messages.append({"role": "user", "content": [{"text": user_message}]})
+
+ converse_api_params = {
+ "modelId": modelId,
+ "system": [{"text": system_prompt}],
+ "messages": messages,
+ "inferenceConfig": {"maxTokens": 4096},
+ "toolConfig":toolConfig,
+ }
+
+ response = bedrock_client.converse(**converse_api_params)
+
+ if response['stopReason'] == "tool_use":
+ tool_use = response['output']['message']['content'][-1]
+ tool_id = tool_use['toolUse']['toolUseId']
+ tool_name = tool_use['toolUse']['name']
+ tool_input = tool_use['toolUse']['input']
+ print(RED + BOLD + f"Claude wants to use the {tool_name} tool" + RESET)
+
+ tool_result = process_tool_call(tool_name, tool_input)
+
+
+ messages.append({"role": "assistant", "content": response['output']['message']['content']})
+
+ #Add our tool_result message:
+ messages.append({
+ "role": "user",
+ "content": [
+ {
+ "toolResult": {
+ "toolUseId": tool_id,
+ "content": [
+ {"text": str(tool_result)}
+ ]
+ }
+ }
+ ]
+ })
+ else:
+ # print(response.content[0].text)
+ model_reply = extract_reply(response['output']['message']['content'][0]['text'])
+ # print(response.content[0].text)
+ # print(response)
+ print(MAGENTA + BOLD + "\nTechNova Support:" + RESET + f"{model_reply}")
+
+ messages.append({"role": "assistant", "content": response['output']['message']['content']})
+
+start_chat()
diff --git a/AmazonBedrock/toolUse_order_bot/order_bot_converse_api.py b/AmazonBedrock/toolUse_order_bot/order_bot_converse_api.py
new file mode 100644
index 0000000..ffe2f20
--- /dev/null
+++ b/AmazonBedrock/toolUse_order_bot/order_bot_converse_api.py
@@ -0,0 +1,229 @@
+import boto3
+import json
+from datetime import datetime
+from botocore.exceptions import ClientError
+
+session = boto3.Session()
+region = session.region_name
+
+modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'
+
+bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)
+
+class FakeDatabase:
+ def __init__(self):
+ self.customers = [
+ {"id": "1213210", "name": "John Doe", "email": "john@gmail.com", "phone": "123-456-7890", "username": "johndoe"},
+ {"id": "2837622", "name": "Priya Patel", "email": "priya@candy.com", "phone": "987-654-3210", "username": "priya123"},
+ {"id": "3924156", "name": "Liam Nguyen", "email": "lnguyen@yahoo.com", "phone": "555-123-4567", "username": "liamn"},
+ {"id": "4782901", "name": "Aaliyah Davis", "email": "aaliyahd@hotmail.com", "phone": "111-222-3333", "username": "adavis"},
+ {"id": "5190753", "name": "Hiroshi Nakamura", "email": "hiroshi@gmail.com", "phone": "444-555-6666", "username": "hiroshin"},
+ {"id": "6824095", "name": "Fatima Ahmed", "email": "fatimaa@outlook.com", "phone": "777-888-9999", "username": "fatimaahmed"},
+ {"id": "7135680", "name": "Alejandro Rodriguez", "email": "arodriguez@protonmail.com", "phone": "222-333-4444", "username": "alexr"},
+ {"id": "8259147", "name": "Megan Anderson", "email": "megana@gmail.com", "phone": "666-777-8888", "username": "manderson"},
+ {"id": "9603481", "name": "Kwame Osei", "email": "kwameo@yahoo.com", "phone": "999-000-1111", "username": "kwameo"},
+ {"id": "1057426", "name": "Mei Lin", "email": "meilin@gmail.com", "phone": "333-444-5555", "username": "mlin"}
+ ]
+
+ self.orders = [
+ {"id": "24601", "customer_id": "1213210", "product": "Wireless Headphones", "quantity": 1, "price": 79.99, "status": "Shipped"},
+ {"id": "13579", "customer_id": "1213210", "product": "Smartphone Case", "quantity": 2, "price": 19.99, "status": "Processing"},
+ {"id": "97531", "customer_id": "2837622", "product": "Bluetooth Speaker", "quantity": 1, "price": "49.99", "status": "Shipped"},
+ {"id": "86420", "customer_id": "3924156", "product": "Fitness Tracker", "quantity": 1, "price": 129.99, "status": "Delivered"},
+ {"id": "54321", "customer_id": "4782901", "product": "Laptop Sleeve", "quantity": 3, "price": 24.99, "status": "Shipped"},
+ {"id": "19283", "customer_id": "5190753", "product": "Wireless Mouse", "quantity": 1, "price": 34.99, "status": "Processing"},
+ {"id": "74651", "customer_id": "6824095", "product": "Gaming Keyboard", "quantity": 1, "price": 89.99, "status": "Delivered"},
+ {"id": "30298", "customer_id": "7135680", "product": "Portable Charger", "quantity": 2, "price": 29.99, "status": "Shipped"},
+ {"id": "47652", "customer_id": "8259147", "product": "Smartwatch", "quantity": 1, "price": 199.99, "status": "Processing"},
+ {"id": "61984", "customer_id": "9603481", "product": "Noise-Cancelling Headphones", "quantity": 1, "price": 149.99, "status": "Shipped"},
+ {"id": "58243", "customer_id": "1057426", "product": "Wireless Earbuds", "quantity": 2, "price": 99.99, "status": "Delivered"},
+ {"id": "90357", "customer_id": "1213210", "product": "Smartphone Case", "quantity": 1, "price": 19.99, "status": "Shipped"},
+ {"id": "28164", "customer_id": "2837622", "product": "Wireless Headphones", "quantity": 2, "price": 79.99, "status": "Processing"}
+ ]
+
+ def get_user(self, key, value):
+ if key in {"email", "phone", "username"}:
+ for customer in self.customers:
+ if customer[key] == value:
+ return customer
+ return f"Couldn't find a user with {key} of {value}"
+ else:
+ raise ValueError(f"Invalid key: {key}")
+
+ return None
+
+ def get_order_by_id(self, order_id):
+ for order in self.orders:
+ if order["id"] == order_id:
+ return order
+ return None
+
+ def get_customer_orders(self, customer_id):
+ return [order for order in self.orders if order["customer_id"] == customer_id]
+
+ def cancel_order(self, order_id):
+ order = self.get_order_by_id(order_id)
+ if order:
+ if order["status"] == "Processing":
+ order["status"] = "Cancelled"
+ return "Cancelled the order"
+ else:
+ return "Order has already shipped. Can't cancel it."
+ return "Can't find that order!"
+
+toolConfig = {
+ 'tools': [
+ {
+ 'toolSpec': {
+ 'name': 'get_user',
+ 'description': 'Looks up a user by email, phone, or username.',
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'key': {
+ 'type': 'string',
+ 'enum': ['email', 'phone', 'username'],
+ 'description': 'The attribute to search for a user by (email, phone, or username).'
+ },
+ 'value': {
+ 'type': 'string',
+ 'description': 'The value to match for the specified attribute.'
+ }
+ },
+ 'required': ['key', 'value']
+ }
+ }
+ }
+ },
+ {
+ 'toolSpec': {
+ 'name': 'get_order_by_id',
+ 'description': 'Retrieves the details of a specific order based on the order ID. Returns the order ID, product name, quantity, price, and order status.',
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'order_id': {
+ 'type': 'string',
+ 'description': 'The unique identifier for the order.'
+ }
+ },
+ 'required': ['order_id']
+ }
+ }
+ }
+ },
+ {
+ 'toolSpec': {
+ 'name': 'get_customer_orders',
+ 'description': "Retrieves the list of orders belonging to a user based on a user's customer id.",
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'customer_id': {
+ 'type': 'string',
+ 'description': 'The customer_id belonging to the user'
+ }
+ },
+ 'required': ['customer_id']
+ }
+ }
+ }
+ },
+ {
+ 'toolSpec': {
+ 'name': 'cancel_order',
+ 'description': "Cancels an order based on a provided order_id. Only orders that are 'processing' can be cancelled",
+ 'inputSchema': {
+ 'json': {
+ 'type': 'object',
+ 'properties': {
+ 'order_id': {
+ 'type': 'string',
+ 'description': 'The order_id pertaining to a particular order'
+ }
+ },
+ 'required': ['order_id']
+ }
+ }
+ }
+ }
+ ],
+ 'toolChoice': {
+ 'auto': {}
+ }
+}
+
+db = FakeDatabase()
+
+def process_tool_call(tool_name, tool_input):
+ if tool_name == "get_user":
+ return db.get_user(tool_input["key"], tool_input["value"])
+ elif tool_name == "get_order_by_id":
+ return db.get_order_by_id(tool_input["order_id"])
+ elif tool_name == "get_customer_orders":
+ return db.get_customer_orders(tool_input["customer_id"])
+ elif tool_name == "cancel_order":
+ return db.cancel_order(tool_input["order_id"])
+
+def simple_chat():
+ user_message = input("\nUser: ")
+ messages = [{"role": "user", "content": [{"text": user_message}]}]
+
+ while True:
+ #If the last message is from the assistant, get another input from the user
+ if messages[-1].get("role") == "assistant":
+ user_message = input("\nUser: ")
+ messages.append({"role": "user", "content": [{"text": user_message}]})
+
+ converse_api_params = {
+ "modelId": modelId,
+ "messages": messages,
+ "inferenceConfig": {"maxTokens": 4096},
+ "toolConfig":toolConfig,
+ }
+
+ response = bedrock_client.converse(**converse_api_params)
+
+ messages.append({"role": "assistant", "content": response['output']['message']['content']})
+
+ #If Claude stops because it wants to use a tool:
+ if response['stopReason'] == "tool_use":
+ tool_use = response['output']['message']['content'][-1] #Naive approach assumes only 1 tool is called at a time
+ tool_id = tool_use['toolUse']['toolUseId']
+ tool_name = tool_use['toolUse']['name']
+ tool_input = tool_use['toolUse']['input']
+
+ print(f"Claude wants to use the {tool_name} tool")
+ print(f"Tool Input:")
+ print(json.dumps(tool_input, indent=2))
+
+ #Actually run the underlying tool functionality on our db
+ tool_result = process_tool_call(tool_name, tool_input)
+
+ print(f"\nTool Result:")
+ print(json.dumps(tool_result, indent=2))
+
+ #Add our tool_result message:
+ messages.append({
+ "role": "user",
+ "content": [
+ {
+ "toolResult": {
+ "toolUseId": tool_id,
+ "content": [
+ {"text": str(tool_result)}
+ ]
+ }
+ }
+ ]
+ })
+
+ else:
+ #If Claude does NOT want to use a tool, just print out the text reponse
+ print(f"\nTechNova Support:" + f"{response['output']['message']['content'][0]['text']}")
+
+# Start the chat!!
+simple_chat()
\ No newline at end of file
diff --git a/AmazonBedrock/utils/hints.py b/AmazonBedrock/utils/hints.py
index b8c02ce..1be4192 100755
--- a/AmazonBedrock/utils/hints.py
+++ b/AmazonBedrock/utils/hints.py
@@ -35,7 +35,7 @@
It's helpful to break this exercise down to several steps.
1. Modify the initial prompt template so that Claude writes two poems.
2. Give Claude indicators as to what the poems will be about, but instead of writing in the subjects directly (e.g., dog, cat, etc.), replace those subjects with the keywords "{ANIMAL1}" and "{ANIMAL2}".
-3. Run the prompt and make sure that the full prompt with variable substitutions has all the words correctly substituted. If not, check to make sure your {bracket} tags are spelled correctly and formatted correctly with single moustache brackets."""
+3. Run the prompt and make sure that the full prompt with variable substitutions has all the words correctly substituted. If not, check to make sure your {bracket} tags are spelled correctly and formatted correctly with f-string brackets."""
exercise_6_1_hint = """The grading function in this exercise is looking for the correct categorization letter + the closing parentheses and the first letter of the name of the category, such as "C) B" or "B) B" etc.
Let's take this exercise step by step: