From c8eb1c6dc9f3033164d24262fc76c1a557b6bcf8 Mon Sep 17 00:00:00 2001 From: DanielMeixner Date: Wed, 22 May 2024 11:28:13 +0000 Subject: [PATCH 1/3] jpnb for phase 3 with sample function --- src-agents/phase3/notebook.ipynb | 305 +++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 src-agents/phase3/notebook.ipynb diff --git a/src-agents/phase3/notebook.ipynb b/src-agents/phase3/notebook.ipynb new file mode 100644 index 0000000..483a183 --- /dev/null +++ b/src-agents/phase3/notebook.ipynb @@ -0,0 +1,305 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Phase 3 - Function Calling\n", + "If not already done run this in the top level folder:\n", + "```\n", + "pip install -r requirements.txt\n", + "```\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found Azure OpenAI API Base Endpoint: https://cog-fkplarx5db7we.openai.azure.com/\n" + ] + } + ], + "source": [ + "import json\n", + "import requests\n", + "import os\n", + "import openai\n", + "from enum import Enum\n", + "from pydantic import BaseModel\n", + "from openai import AzureOpenAI\n", + "from dotenv import load_dotenv\n", + "\n", + "# Load environment variables\n", + "if load_dotenv():\n", + " print(\"Found Azure OpenAI API Base Endpoint: \" + os.getenv(\"AZURE_OPENAI_ENDPOINT\"))\n", + "else: \n", + " print(\"Azure OpenAI API Base Endpoint not found. Have you configured the .env file?\")\n", + " \n", + "API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", + "API_VERSION = os.getenv(\"OPENAI_API_VERSION\")\n", + "RESOURCE_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "\n", + "\n", + "client = AzureOpenAI(\n", + " azure_endpoint = os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n", + " api_key = os.getenv(\"AZURE_OPENAI_API_KEY\"),\n", + " api_version = os.getenv(\"AZURE_OPENAI_VERSION\")\n", + ")\n", + "deployment_name = os.getenv(\"AZURE_OPENAI_COMPLETION_DEPLOYMENT_NAME\")\n", + "model_name = os.getenv(\"AZURE_OPENAI_COMPLETION_MODEL\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is the object model for receiving questions." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "class QuestionType(str, Enum):\n", + " multiple_choice = \"multiple_choice\"\n", + " true_false = \"true_false\"\n", + " popular_choice = \"popular_choice\"\n", + " estimation = \"estimation\"\n", + "\n", + "class Ask(BaseModel):\n", + " question: str | None = None\n", + " type: QuestionType\n", + " correlationToken: str | None = None\n", + "\n", + "class Answer(BaseModel):\n", + " answer: str\n", + " correlationToken: str | None = None\n", + " promptTokensUsed: int | None = None\n", + " completionTokensUsed: int | None = None\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sample Function " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import pytz\n", + "from datetime import datetime\n", + "\n", + "def get_current_time(location):\n", + " try:\n", + " # Get the timezone for the city\n", + " timezone = pytz.timezone(location)\n", + "\n", + " # Get the current time in the timezone\n", + " now = datetime.now(timezone)\n", + " current_time = now.strftime(\"%I:%M:%S %p\")\n", + "\n", + " return current_time\n", + " except:\n", + " return \"Sorry, I couldn't find the timezone for that location.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the model aware of the function\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "functions = [\n", + " {\n", + " \"type\": \"function\",\n", + " \"function\": {\n", + " \"name\": \"get_current_time\",\n", + " \"description\": \"Get the current time in a given location\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"location\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The location name. The pytz is used to get the timezone for that location. Location names should be in a format like America/New_York, Asia/Bangkok, Europe/London\",\n", + " }\n", + " },\n", + " \"required\": [\"location\"],\n", + " },\n", + " }\n", + " }\n", + " ] \n", + "available_functions = {\n", + " \"get_current_time\": get_current_time \n", + " } " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "YOUR Mission: Adjust the function below and reuse it in the main.py file later to deploy to Azure and to update your service\n" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "async def ask_question(ask: Ask):\n", + " \"\"\"\n", + " Ask a question\n", + " \"\"\"\n", + " \n", + " question = ask.question\n", + " messages= [{\"role\" : \"assistant\", \"content\" : question}\n", + " , { \"role\" : \"system\", \"content\" : \"if asked for time answer in the format HH:MM:SS AM/PM only. Do not answer with a full sentence.\"}\n", + " ]\n", + " first_response = client.chat.completions.create(\n", + " model = deployment_name,\n", + " messages = messages,\n", + " tools = functions,\n", + " tool_choice = \"auto\",\n", + " )\n", + "\n", + " print(first_response)\n", + " response_message = first_response.choices[0].message\n", + " tool_calls = response_message.tool_calls\n", + "\n", + " # Step 2: check if GPT wanted to call a function\n", + " if tool_calls:\n", + " print(\"Recommended Function call:\")\n", + " print(tool_calls)\n", + " print()\n", + " \n", + " # Step 3: call the function\n", + " messages.append(response_message)\n", + "\n", + " for tool_call in tool_calls:\n", + " function_name = tool_call.function.name\n", + " # verify function exists\n", + " if function_name not in available_functions:\n", + " return \"Function \" + function_name + \" does not exist\"\n", + " else:\n", + " print(\"Calling function: \" + function_name)\n", + " function_to_call = available_functions[function_name]\n", + " function_args = json.loads(tool_call.function.arguments)\n", + " print(function_args)\n", + " function_response = function_to_call(**function_args)\n", + " messages.append(\n", + " {\n", + " \"tool_call_id\": tool_call.id,\n", + " \"role\": \"tool\",\n", + " \"name\": function_name,\n", + " \"content\": function_response,\n", + " }\n", + " ) \n", + " print(\"Addding this message to the next prompt:\") \n", + " print (messages)\n", + " \n", + " # extend conversation with function response\n", + " second_response = client.chat.completions.create(\n", + " model = model_name,\n", + " messages = messages) # get a new response from the model where it can see the function response\n", + " \n", + " print(\"second_response\")\n", + " \n", + " return second_response.choices[0].message.content\n", + " \n", + "\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use this snippet to try your method with several questions." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ChatCompletion(id='chatcmpl-9RdGE2UGDgpqzctH0fdccMvs5HOkO', choices=[Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_ChFZdPaRNIYcXxUU7HYH6gU5', function=Function(arguments='{\\n \"location\": \"America/New_York\"\\n}', name='get_current_time'), type='function')]), content_filter_results={})], created=1716372802, model='gpt-35-turbo', object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=19, prompt_tokens=114, total_tokens=133), prompt_filter_results=[{'prompt_index': 0, 'content_filter_results': {'hate': {'filtered': False, 'severity': 'safe'}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}}])\n", + "Recommended Function call:\n", + "[ChatCompletionMessageToolCall(id='call_ChFZdPaRNIYcXxUU7HYH6gU5', function=Function(arguments='{\\n \"location\": \"America/New_York\"\\n}', name='get_current_time'), type='function')]\n", + "\n", + "Calling function: get_current_time\n", + "{'location': 'America/New_York'}\n", + "Addding this message to the next prompt:\n", + "[{'role': 'assistant', 'content': 'What time is it in New York?'}, {'role': 'system', 'content': 'if asked for time answer in the format HH:MM:SS'}, ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_ChFZdPaRNIYcXxUU7HYH6gU5', function=Function(arguments='{\\n \"location\": \"America/New_York\"\\n}', name='get_current_time'), type='function')]), {'tool_call_id': 'call_ChFZdPaRNIYcXxUU7HYH6gU5', 'role': 'tool', 'name': 'get_current_time', 'content': '06:13:23 AM'}]\n", + "second_response\n", + "Answer: The current time in New York is 06:13:23 AM.\n" + ] + } + ], + "source": [ + "\n", + "ask = Ask(question=\"What time is it in New York?\", type=QuestionType.estimation)\n", + "answer = await ask_question(ask)\n", + "print('Answer:', answer )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make sure you transfer your code changes into main.py (or additional files). Then redeploy your container using this command.\n", + "```\n", + "bash ./azd-hooks/deploy.sh phase1 $AZURE_ENV_NAME\n", + "```\n", + "Make sure to provide the URL of your endpoint in the team portal!" + ] + } + ], + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 73d033420d81a1c495192729f91af3f539d079ab Mon Sep 17 00:00:00 2001 From: DanielMeixner Date: Wed, 22 May 2024 11:40:24 +0000 Subject: [PATCH 2/3] cleared output --- src-agents/phase3/notebook.ipynb | 41 +++++++------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/src-agents/phase3/notebook.ipynb b/src-agents/phase3/notebook.ipynb index 483a183..2866c5f 100644 --- a/src-agents/phase3/notebook.ipynb +++ b/src-agents/phase3/notebook.ipynb @@ -15,17 +15,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Found Azure OpenAI API Base Endpoint: https://cog-fkplarx5db7we.openai.azure.com/\n" - ] - } - ], + "outputs": [], "source": [ "import json\n", "import requests\n", @@ -65,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -97,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -127,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -164,7 +156,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -242,26 +234,9 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ChatCompletion(id='chatcmpl-9RdGE2UGDgpqzctH0fdccMvs5HOkO', choices=[Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_ChFZdPaRNIYcXxUU7HYH6gU5', function=Function(arguments='{\\n \"location\": \"America/New_York\"\\n}', name='get_current_time'), type='function')]), content_filter_results={})], created=1716372802, model='gpt-35-turbo', object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=19, prompt_tokens=114, total_tokens=133), prompt_filter_results=[{'prompt_index': 0, 'content_filter_results': {'hate': {'filtered': False, 'severity': 'safe'}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}}])\n", - "Recommended Function call:\n", - "[ChatCompletionMessageToolCall(id='call_ChFZdPaRNIYcXxUU7HYH6gU5', function=Function(arguments='{\\n \"location\": \"America/New_York\"\\n}', name='get_current_time'), type='function')]\n", - "\n", - "Calling function: get_current_time\n", - "{'location': 'America/New_York'}\n", - "Addding this message to the next prompt:\n", - "[{'role': 'assistant', 'content': 'What time is it in New York?'}, {'role': 'system', 'content': 'if asked for time answer in the format HH:MM:SS'}, ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_ChFZdPaRNIYcXxUU7HYH6gU5', function=Function(arguments='{\\n \"location\": \"America/New_York\"\\n}', name='get_current_time'), type='function')]), {'tool_call_id': 'call_ChFZdPaRNIYcXxUU7HYH6gU5', 'role': 'tool', 'name': 'get_current_time', 'content': '06:13:23 AM'}]\n", - "second_response\n", - "Answer: The current time in New York is 06:13:23 AM.\n" - ] - } - ], + "outputs": [], "source": [ "\n", "ask = Ask(question=\"What time is it in New York?\", type=QuestionType.estimation)\n", From be6ad5d24dfde760576e073ad8e25613268c4a0a Mon Sep 17 00:00:00 2001 From: DanielMeixner Date: Wed, 22 May 2024 12:01:20 +0000 Subject: [PATCH 3/3] counting tokens --- requirements.txt | 1 + src-agents/phase4/notebook.ipynb | 231 +++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 src-agents/phase4/notebook.ipynb diff --git a/requirements.txt b/requirements.txt index 5f46f68..d468198 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ pydantic==2.7.1 python-dotenv==1.0.1 quadrant==1.0 requests==2.32.0 +tiktoken==0.7.0 diff --git a/src-agents/phase4/notebook.ipynb b/src-agents/phase4/notebook.ipynb new file mode 100644 index 0000000..eefad28 --- /dev/null +++ b/src-agents/phase4/notebook.ipynb @@ -0,0 +1,231 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Phase 4 - Efficiency\n", + "If not already done run this in the top level folder:\n", + "```\n", + "pip install -r requirements.txt\n", + "```\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found Azure OpenAI API Base Endpoint: https://cog-fkplarx5db7we.openai.azure.com/\n" + ] + } + ], + "source": [ + "import json\n", + "import requests\n", + "import os\n", + "import openai\n", + "import tiktoken\n", + "from enum import Enum\n", + "from pydantic import BaseModel\n", + "from openai import AzureOpenAI\n", + "from dotenv import load_dotenv\n", + "\n", + "# Load environment variables\n", + "if load_dotenv():\n", + " print(\"Found Azure OpenAI API Base Endpoint: \" + os.getenv(\"AZURE_OPENAI_ENDPOINT\"))\n", + "else: \n", + " print(\"Azure OpenAI API Base Endpoint not found. Have you configured the .env file?\")\n", + " \n", + "API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", + "API_VERSION = os.getenv(\"OPENAI_API_VERSION\")\n", + "RESOURCE_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "\n", + "\n", + "client = AzureOpenAI(\n", + " azure_endpoint = os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n", + " api_key = os.getenv(\"AZURE_OPENAI_API_KEY\"),\n", + " api_version = os.getenv(\"AZURE_OPENAI_VERSION\")\n", + ")\n", + "deployment_name = os.getenv(\"AZURE_OPENAI_COMPLETION_DEPLOYMENT_NAME\")\n", + "model_name = os.getenv(\"AZURE_OPENAI_COMPLETION_MODEL\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is the object model for receiving questions." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "class QuestionType(str, Enum):\n", + " multiple_choice = \"multiple_choice\"\n", + " true_false = \"true_false\"\n", + " popular_choice = \"popular_choice\"\n", + " estimation = \"estimation\"\n", + "\n", + "class Ask(BaseModel):\n", + " question: str | None = None\n", + " type: QuestionType\n", + " correlationToken: str | None = None\n", + "\n", + "class Answer(BaseModel):\n", + " answer: str\n", + " correlationToken: str | None = None\n", + " promptTokensUsed: int | None = None\n", + " completionTokensUsed: int | None = None\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get the number of tokens\n", + "tiktoken is a library which allows you to get the number of tokens. \n", + "Ensure you pick the correct encoding for your model based on this list. https://github.com/openai/tiktoken/blob/c0ba74c238d18b4824c25f3c27fc8698055b9a76/tiktoken/model.py#L20\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of tokens in the string: 7\n" + ] + } + ], + "source": [ + "def get_num_tokens_from_string(string: str, encoding_name: str='p50k_base') -> int:\n", + " \"\"\"Returns the number of tokens in a text by a given encoding.\"\"\"\n", + " encoding = tiktoken.get_encoding(encoding_name)\n", + " return len(encoding.encode(string))\n", + "\n", + "number_of_tokens=get_num_tokens_from_string(\"Hello, Azure AI Adventure Day!\")\n", + "print(f\"Number of tokens in the string: {number_of_tokens}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "YOUR Mission: Adjust the function below and reuse it in the main.py file later to deploy to Azure and to update your service\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "async def ask_question(ask: Ask):\n", + " \"\"\"\n", + " Ask a question\n", + " \"\"\"\n", + "\n", + " # Send a completion call to generate an answer\n", + " print('Sending a request to openai')\n", + " start_phrase = ask.question\n", + " messages= [{\"role\" : \"assistant\", \"content\" : start_phrase}]\n", + " number_of_tokens_in= get_num_tokens_from_string(messages[0]['content']);\n", + " \n", + " response = client.chat.completions.create(\n", + " model = deployment_name,\n", + " messages =messages,\n", + " )\n", + "\n", + " number_of_tokens_out= get_num_tokens_from_string(response.choices[0].message.content);\n", + "\n", + " print(f\"Number of tokens in the input: {number_of_tokens_in}\")\n", + " print(f\"Number of tokens in the output: {number_of_tokens_out}\")\n", + " print('Total Tokens Used: ' + str(number_of_tokens_in + number_of_tokens_out))\n", + "\n", + " answer = Answer(answer=response.choices[0].message.content)\n", + " answer.correlationToken = ask.correlationToken\n", + " answer.promptTokensUsed = response.usage.prompt_tokens\n", + " answer.completionTokensUsed = response.usage.completion_tokens\n", + "\n", + " return answer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use this snippet to try your method with several questions." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sending a request to openai\n", + "Number of tokens in the input: 17\n", + "Number of tokens in the output: 3\n", + "Total Tokens Used: 20\n", + "Answer: answer='c. Green' correlationToken=None promptTokensUsed=24 completionTokensUsed=3\n" + ] + } + ], + "source": [ + "\n", + "ask = Ask(question=\"Which of the following is a color? a. Tree b. Flower c. Green\", type=QuestionType.multiple_choice)\n", + "answer = await ask_question(ask)\n", + "print('Answer:', answer)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make sure you transfer your code changes into main.py (or additional files). Then redeploy your container using this command.\n", + "```\n", + "bash ./azd-hooks/deploy.sh phase1 $AZURE_ENV_NAME\n", + "```\n", + "Make sure to provide the URL of your endpoint in the team portal!" + ] + } + ], + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}