diff --git a/Basic_Samples/Functions/functions_to_perform_actions.ipynb b/Basic_Samples/Functions/functions_to_perform_actions.ipynb new file mode 100644 index 00000000..f46a87c8 --- /dev/null +++ b/Basic_Samples/Functions/functions_to_perform_actions.ipynb @@ -0,0 +1,360 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Working with Functions To Perform a Service\n", + "\n", + "This notebook shows how you can use functions to perform external tasks such as sending an email. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## API Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import openai\n", + "import json\n", + "import os\n", + "\n", + "# Load config values\n", + "with open(r'config.json') as config_file:\n", + " config_details = json.load(config_file)\n", + "\n", + "# The API key for your Azure OpenAI resource.\n", + "openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n", + "\n", + "# Currently Chat Completion API have the following versions available: 2023-07-01-preview\n", + "openai.api_version = config_details['OPENAI_API_VERSION']\n", + "\n", + "# This is set to `azure`\n", + "openai.api_type = \"azure\"\n", + "\n", + "# The base URL for your Azure OpenAI resource. e.g. \"https://.openai.azure.com\"\n", + "openai.api_base = config_details['OPENAI_API_BASE']\n", + "\n", + "# Setting up the deployment name\n", + "deployment_id = config_details['DEPLOYMENT_NAME'] # You need to use the 0613 version of gpt-35-turbo or gpt-4 to work with functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define the function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Send Email" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import smtplib \n", + "from email.mime.multipart import MIMEMultipart \n", + "from email.mime.text import MIMEText \n", + "\n", + "def send_email(smtp_server, smtp_port, sender_email, sender_password, recipient_email, subject, body): \n", + " msg = MIMEMultipart() \n", + " msg['From'] = sender_email \n", + " msg['To'] = recipient_email \n", + " msg['Subject'] = subject \n", + " msg.attach(MIMEText(body, 'plain')) \n", + "\n", + " try: \n", + " server = smtplib.SMTP(smtp_server, smtp_port) \n", + " server.starttls() # Secure the connection \n", + " server.login(sender_email, sender_password) \n", + " text = msg.as_string() \n", + " server.sendmail(sender_email, recipient_email, text) \n", + " server.quit() \n", + " return \"Email sent successfully!\" \n", + "\n", + " except Exception as e: \n", + " return f\"Failed to send email: {str(e)}\" " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"Failed to send email: (535, b'5.7.8 Username and Password not accepted. Learn more at\\\\n5.7.8 https://support.google.com/mail/?p=BadCredentials f22-20020a17090ac29600b00263f41a655esm237986pjt.43 - gsmtp')\"" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Define your SMTP server details \n", + "smtp_server = 'smtp.gmail.com' # Replace with your SMTP server this is for gmail \n", + "smtp_port = 587 # Replace with your SMTP server port number this is the port for gmail \n", + "\n", + "# Define your email details \n", + "sender_email = 'sender@email.com' # Replace with your email username \n", + "sender_password = 'yourpassword' # Replace with your email password. For gmail accounts, you need to create an app password \n", + "recipient_email = 'recipient@email.com' # Replace with recipient's email address \n", + "\n", + "# Define your email content \n", + "subject = 'Hello!' # Replace with your subject line \n", + "body = 'This is a test email' # Replace with your email body text \n", + "\n", + "# Call the send_email function \n", + "send_email(smtp_server, smtp_port, sender_email, sender_password, recipient_email, subject, body) \n", + "\n", + "# Steps to create an app password for your gmail account \n", + "# Visit this page: https://myaccount.google.com/security \n", + "# Under the section \"2-Step Verification\", click on \"App passwords\". \n", + "# Under \"Select app\", choose \"Mail\". \n", + "# Under \"Select device\", choose the one you're using. \n", + "# Click on \"Generate\". You will see a 16-digit password. Use this password in your Python script where you'd normally use your Gmail password." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using GPT to perform a service \n", + "In this example, GPT is used to call a function that sends an email. Before the email is sent, the user must confirm it likes the content generated by the model." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Helper Method\n", + "Checks for invalid arguments." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import inspect\n", + "\n", + "# helper method used to check if the correct arguments are provided to a function\n", + "def check_args(function, args):\n", + " sig = inspect.signature(function)\n", + " params = sig.parameters\n", + "\n", + " # Check if there are extra arguments\n", + " for name in args:\n", + " if name not in params:\n", + " return False\n", + " # Check if the required arguments are provided \n", + " for name, param in params.items():\n", + " if param.default is param.empty and name not in args:\n", + " return False\n", + "\n", + " return True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Replace the user message with your email, your password, the recipient email, the subject, and the body." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Response from GPT:\n", + "{\n", + " \"role\": \"assistant\",\n", + " \"content\": \"Of course! Please provide me with the necessary details.\"\n", + "}\n", + "\n", + "The subject of the email is: Fun Facts of the Day\n", + "The body of the email is: Here are some fun facts for you:\n", + "\n", + "1. A single strand of spaghetti is called a spaghetto.\n", + "2. The average person spends about 6 months of their life waiting for red lights to turn green.\n", + "3. Only 2% of the world's population has green eyes.\n", + "4. The shortest war in history lasted only 38 to 45 minutes.\n", + "\n", + "Enjoy!\n", + "\n", + "Do you want to send this email? (yes/no)\n" + ] + } + ], + "source": [ + "def perform_service(): \n", + " # Step 1: send the conversation and available functions to GPT \n", + " messages = [] \n", + " messages.append({\"role\": \"system\", \"content\": \"Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous. You are able to help send emails using a function.\"}) \n", + " messages.append({\"role\": \"system\", \"content\": \"After you generate the content of the email ask the user to confirm the draft before sending it.\"}) \n", + "\n", + " messages = [{\"role\": \"user\", \"content\": \"Can you send an email for me?\"}] \n", + " functions = [ \n", + " { \n", + " \"name\": \"send_email\", \n", + " \"description\": \"Send an email\", \n", + " \"parameters\": { \n", + " \"type\": \"object\", \n", + " \"properties\": { \n", + " \"smtp_server\": { \n", + " \"type\": \"string\", \n", + " \"description\": \"The SMTP server to use to send the email. For example, smtp.office365.com is the server for outlook accounts, smtp.gmail.com is the server for gmail accounts, and smtp.mail.att.net is for AT&T accounts.\", \n", + " }, \n", + " \"smtp_port\": { \n", + " \"type\": \"integer\", \n", + " \"description\": \"The SMTP port to use to send the email. For example, 587 is the port for outlook and gmail accounts. 465 is the port for AT&T accounts.\", \n", + " }, \n", + " \"sender_email\": { \n", + " \"type\": \"string\", \n", + " \"description\": \"The email address of the sender.\", \n", + " }, \n", + " \"sender_password\": { \n", + " \"type\": \"string\", \n", + " \"description\": \"The password of the sender.\", \n", + " }, \n", + " \"recipient_email\": { \n", + " \"type\": \"string\", \n", + " \"description\": \"The email address of the recipient.\", \n", + " }, \n", + " \"subject\": { \n", + " \"type\": \"string\", \n", + " \"description\": \"The subject of the email.\", \n", + " }, \n", + " \"body\": { \n", + " \"type\": \"string\", \n", + " \"description\": \"The body of the email.\", \n", + " }, \n", + " }, \n", + " \"required\": [\"smtp_server\", \"smtp_port\", \"sender_email\", \"sender_password\", \"recipient_email\", \"subject\", \"body\"], \n", + " }, \n", + " } \n", + " ] \n", + " response = openai.ChatCompletion.create( \n", + " deployment_id=deployment_id, \n", + " messages=messages, \n", + " functions=functions, \n", + " function_call=\"auto\", \n", + " ) \n", + " response_message = response[\"choices\"][0][\"message\"] \n", + "\n", + " print(\"Response from GPT:\") \n", + " print(response_message) \n", + " print() \n", + "\n", + " # Provide more details to GPT about the email to send\n", + " # Replace the sender email, sender password, and recipient email with the user's actual email addresses\n", + " # Replace the subject and body with whatever you want\n", + " messages.append({\"role\": \"user\", \"content\": \"My email is sender@email.com. My password is yourpassword. I am sending an email to recipient@email.com. I want the subject line to be Fun Facts of the Day. For the body of the email I want you to generate fun facts.\"}) \n", + "\n", + " response = openai.ChatCompletion.create( \n", + " deployment_id=deployment_id, \n", + " messages=messages, \n", + " functions=functions, \n", + " function_call={\"name\": \"send_email\"}, \n", + " ) \n", + " response_message = response[\"choices\"][0][\"message\"] \n", + "\n", + " # Parsing out the generated email parts\n", + " email_args = response_message[\"function_call\"][\"arguments\"]\n", + " arguments_dict = json.loads(email_args)\n", + " email_subject = arguments_dict[\"subject\"]\n", + " email_body = arguments_dict[\"body\"]\n", + " print(\"The subject of the email is: \" + email_subject)\n", + " print(\"The body of the email is: \" + email_body)\n", + " print()\n", + "\n", + " # Verifying user wants to send the generated email\n", + " print(\"Do you want to send this email? (yes/no)\")\n", + " user_response = input()\n", + " user_response.lower()\n", + "\n", + " # Step 2: check if user confirmed they want to call the function\n", + " if response_message.get(\"function_call\"): \n", + " if user_response == \"yes\":\n", + " print(\"Recommended Function call:\") \n", + " print(response_message.get(\"function_call\")) \n", + " print() \n", + "\n", + " # Step 3: call the function \n", + " # Note: the JSON response may not always be valid; be sure to handle errors \n", + " available_functions = { \n", + " \"send_email\": send_email, \n", + " } \n", + " function_name = response_message[\"function_call\"][\"name\"] \n", + "\n", + " # verify function exists \n", + " if function_name not in available_functions: \n", + " return \"Function \" + function_name + \" does not exist\" \n", + " fuction_to_call = available_functions[function_name] \n", + "\n", + " # verify function has correct number of arguments \n", + " function_args = json.loads(response_message[\"function_call\"][\"arguments\"]) \n", + " if check_args(fuction_to_call, function_args) is False: \n", + " return \"Invalid number of arguments for function: \" + function_name \n", + "\n", + " # Call the function and return the response \n", + " function_response = fuction_to_call(**function_args) \n", + " print(function_response) \n", + " return function_response \n", + " else:\n", + " return \"Email not sent.\"\n", + "service_response = perform_service() " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}