2-notebooks/2-agent_service/1-basics.ipynb (384 lines of code) (raw):

{ "cells": [ { "cell_type": "markdown", "id": "72d4ac29", "metadata": {}, "source": [ "# ๐Ÿ Fun & Fit Health Advisor Agent Tutorial ๐ŸŽ\n", "\n", "Welcome to our **Fun & Fit Health Advisor Agent** tutorial, where you'll use **Azure AI Foundry** SDKs to create a playful (yet carefully disclaimed!) health and fitness assistant. We'll:\n", "\n", "1. **Initialize** our project using **azure-ai-projects**.\n", "2. **Create an Agent** specialized in providing general wellness and nutritional advice (with disclaimers!).\n", "3. **Manage conversations** about fitness, nutrition, and general health topics.\n", "4. **Showcase logging and tracing** with **OpenTelemetry**.\n", "5. **Demonstrate** how to incorporate tools, safety disclaimers, and basic best practices.\n", "\n", "### โš ๏ธ Important Medical Disclaimer โš ๏ธ\n", "> **The health information provided by this notebook is for general educational and entertainment purposes only and is not intended as a substitute for professional medical advice, diagnosis, or treatment.** Always seek the advice of your physician or other qualified health provider with any questions you may have regarding a medical condition. Never disregard professional medical advice or delay seeking it because of something you read or receive from this notebook.\n", "\n", "\n", "## Prerequisites\n", "\n", "Complete [the notebooks in introduction](../../1-introduction/3-quick_start.ipynb)\n", "\n", "## Let's Get Started\n", "We'll walk you through each cell with notes and diagrams to keep it fun. Let's begin!\n", "\n", "<img src=\"./seq-diagrams/1-basics.png\" width=\"30%\"/>\n", "\n", "\n" ] }, { "cell_type": "markdown", "id": "e2e31c56", "metadata": {}, "source": [ "## 1. Initial Setup\n", "We'll start by importing needed libraries, loading environment variables, and initializing an **AIProjectClient** so we can do all the agent-related actions. Let's do it! ๐ŸŽ‰\n" ] }, { "cell_type": "code", "execution_count": null, "id": "bc2b306e", "metadata": {}, "outputs": [], "source": [ "# Import required libraries\n", "import os # For environment variables and path operations\n", "import time # For adding delays if needed\n", "from pathlib import Path # For cross-platform path handling\n", "\n", "# Import Azure and utility libraries\n", "from dotenv import load_dotenv # For loading environment variables from .env file\n", "from azure.identity import DefaultAzureCredential # For Azure authentication\n", "from azure.ai.projects import AIProjectClient # Main client for AI Projects\n", "from azure.ai.projects.models import MessageTextContent # For handling message content\n", "\n", "# Get the path to the .env file which is in the parent directory\n", "notebook_path = Path().absolute() # Get absolute path of current notebook\n", "parent_dir = notebook_path.parent # Get parent directory\n", "load_dotenv(parent_dir.parent / '.env') # Load environment variables from .env file\n", "\n", "# Initialize the AI Project Client using connection string from environment variables\n", "try:\n", " project_client = AIProjectClient.from_connection_string(\n", " # Use default Azure credentials for authentication\n", " credential=DefaultAzureCredential(),\n", " # Get the project connection string from environment variables\n", " conn_str=os.environ.get(\"PROJECT_CONNECTION_STRING\")\n", " )\n", " print(\"โœ… Successfully initialized AIProjectClient\")\n", "except Exception as e:\n", " # Print error message if client initialization fails\n", " print(f\"โŒ Error initializing project client: {str(e)}\")" ] }, { "cell_type": "markdown", "id": "7f5aceb0", "metadata": {}, "source": [ "## 2. Creating our Fun & Fit Health Advisor Agent ๐Ÿ‹๏ธ\n", "\n", "We'll create an Agent specialized in general health and wellness. We'll explicitly mention disclaimers in its instructions, so it never forgets to keep it safe! The instructions also ask the agent to focus on general fitness, dietary tips, and always encourage the user to seek professional advice.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "157d067c", "metadata": { "execution": {} }, "outputs": [], "source": [ "def create_health_advisor_agent():\n", " \"\"\"Create a health advisor agent with disclaimers and basic instructions.\"\"\"\n", " try:\n", " # Get the model name from environment variables, default to gpt-4o-mini if not set\n", " model_name = os.environ.get(\"MODEL_DEPLOYMENT_NAME\", \"gpt-4o-mini\")\n", "\n", " # Create a new agent using the AIProjectClient\n", " # The agent will use the specified model and follow the given instructions\n", " agent = project_client.agents.create_agent(\n", " model=model_name,\n", " name=\"fun-fit-health-advisor\",\n", " # Define the agent's behavior and responsibilities\n", " instructions=\"\"\"\n", " You are a friendly AI Health Advisor.\n", " You provide general health, fitness, and nutrition information, but always:\n", " 1. Include medical disclaimers.\n", " 2. Encourage the user to consult healthcare professionals.\n", " 3. Provide general, non-diagnostic advice around wellness, diet, and fitness.\n", " 4. Clearly remind them you're not a doctor.\n", " 5. Encourage safe and balanced approaches to exercise and nutrition.\n", " \"\"\"\n", " )\n", " # Log success and return the created agent\n", " print(f\"๐ŸŽ‰ Created health advisor agent, ID: {agent.id}\")\n", " return agent\n", " except Exception as e:\n", " # Handle any errors during agent creation\n", " print(f\"โŒ Error creating agent: {str(e)}\")\n", " return None\n", "\n", "# Create an instance of our health advisor agent\n", "health_advisor = create_health_advisor_agent()" ] }, { "cell_type": "markdown", "id": "5fb1cb05", "metadata": {}, "source": [ "## 3. Managing Our Health Conversations ๐Ÿ’ฌ\n", "A conversation (or *thread*) is where we'll store the user's messages and the agent's responses about health topics. Let's create a new thread dedicated to Health & Fitness Q&A.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "955161b9", "metadata": {}, "outputs": [], "source": [ "# Function to create a new conversation thread for health discussions\n", "def start_health_conversation():\n", " \"\"\"Create a new thread for health & fitness discussions.\"\"\"\n", " try:\n", " # Create a new empty thread using the project client\n", " # A thread stores the back-and-forth messages between user and agent\n", " thread = project_client.agents.create_thread()\n", " \n", " # Print success message with the thread ID for reference\n", " print(f\"๐Ÿ“ Created a new conversation thread, ID: {thread.id}\")\n", " \n", " # Return the created thread object so we can use it later\n", " return thread\n", " except Exception as e:\n", " # If thread creation fails, print error and return None\n", " print(f\"โŒ Error creating thread: {str(e)}\")\n", " return None\n", "\n", "# Initialize a new conversation thread that we'll use for our health Q&A\n", "health_thread = start_health_conversation()" ] }, { "cell_type": "markdown", "id": "1bb2ad90", "metadata": {}, "source": [ "## 4. Asking Health & Fitness Questions ๐Ÿƒ‍โ™‚๏ธ\n", "We'll create messages from the user about typical health questions. For example, **\"How do I calculate my BMI?\"** or **\"What's a balanced meal for an active lifestyle?\"**. We'll let our Health Advisor Agent respond, always remembering that disclaimer!\n" ] }, { "cell_type": "code", "execution_count": null, "id": "235b237b", "metadata": {}, "outputs": [], "source": [ "def ask_health_question(thread_id, user_question):\n", " \"\"\"Add a user message to the conversation thread.\n", " \n", " Args:\n", " thread_id: ID of the conversation thread\n", " user_question: The health/fitness question from the user\n", " \n", " Returns:\n", " Message object if successful, None if error occurs\n", " \"\"\"\n", " try:\n", " # Create a new message in the thread from the user's perspective\n", " # The role=\"user\" indicates this is a user message (vs assistant)\n", " return project_client.agents.create_message(\n", " thread_id=thread_id,\n", " role=\"user\", \n", " content=user_question\n", " )\n", " except Exception as e:\n", " print(f\"โŒ Error adding user message: {e}\")\n", " return None\n", "\n", "def process_thread_run(thread_id, agent_id):\n", " \"\"\"Ask the agent to process the thread and generate a response.\n", " \n", " Args:\n", " thread_id: ID of the conversation thread\n", " agent_id: ID of the health advisor agent\n", " \n", " Returns:\n", " Run object if successful, None if error occurs\n", " \"\"\"\n", " try:\n", " # Create a new run to have the agent process the thread\n", " run = project_client.agents.create_run(\n", " thread_id=thread_id,\n", " agent_id=agent_id\n", " )\n", "\n", " # Poll the run status until completion or error\n", " # Status can be: queued, in_progress, requires_action, completed, failed\n", " while run.status in [\"queued\", \"in_progress\", \"requires_action\"]:\n", " time.sleep(1) # Wait 1 second between status checks\n", " run = project_client.agents.get_run(\n", " thread_id=thread_id,\n", " run_id=run.id\n", " )\n", "\n", " print(f\"๐Ÿค– Run completed with status: {run.status}\")\n", " return run\n", " except Exception as e:\n", " print(f\"โŒ Error processing thread run: {str(e)}\")\n", " return None\n", "\n", "def view_thread_messages(thread_id):\n", " \"\"\"Display all messages in the conversation thread in chronological order.\n", " \n", " Args:\n", " thread_id: ID of the conversation thread to display\n", " \"\"\"\n", " try:\n", " # Get all messages in the thread\n", " messages = project_client.agents.list_messages(thread_id=thread_id)\n", " print(\"\\n๐Ÿ—ฃ๏ธ Conversation so far (oldest to newest):\")\n", " \n", " # Loop through messages in reverse order to show oldest first\n", " for m in reversed(messages.data):\n", " if m.content:\n", " # Extract the text content from the message\n", " # We only handle text messages for now (not images etc)\n", " last_content = m.content[-1]\n", " if isinstance(last_content, MessageTextContent):\n", " print(f\"{m.role.upper()}: {last_content.text.value}\\n\")\n", " print(\"-----------------------------------\\n\")\n", " except Exception as e:\n", " print(f\"โŒ Error viewing thread: {str(e)}\")" ] }, { "cell_type": "markdown", "id": "d0865cdf", "metadata": {}, "source": [ "### Example Queries\n", "Let's do some quick queries now to see the agent's disclaimers and how it handles typical health questions. We'll ask about **BMI** and about **balanced meal** for an active lifestyle.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "8357bc8f", "metadata": {}, "outputs": [], "source": [ "# First verify that we have valid agent and thread objects before proceeding\n", "if health_advisor and health_thread:\n", " # 1) Ask about BMI calculation and interpretation\n", " # This demonstrates how the agent handles technical health questions\n", " msg1 = ask_health_question(health_thread.id, \"How do I calculate my BMI, and what does it mean?\")\n", " # Process the BMI question and wait for agent's response\n", " run1 = process_thread_run(health_thread.id, health_advisor.id)\n", "\n", " # 2) Ask about personalized meal planning\n", " # This shows how the agent provides customized nutrition advice\n", " msg2 = ask_health_question(health_thread.id, \"Can you give me a balanced meal plan for someone who exercises 3x a week?\")\n", " # Process the meal plan question and wait for agent's response\n", " run2 = process_thread_run(health_thread.id, health_advisor.id)\n", "\n", " # Display the full conversation history to see both Q&As\n", " # This will show the agent's responses including any health disclaimers\n", " view_thread_messages(health_thread.id)\n", "else:\n", " # Error handling if agent or thread initialization failed\n", " print(\"โŒ Could not run example queries because agent or thread is None.\")" ] }, { "cell_type": "markdown", "id": "b2729872", "metadata": {}, "source": [ "## 5. Cleanup ๐Ÿงน\n", "If you'd like to remove your agent from the service once finished, you can do so below. (In production, you might keep your agent around for stateful experiences!)" ] }, { "cell_type": "code", "execution_count": null, "id": "820fa511", "metadata": {}, "outputs": [], "source": [ "# Function to clean up and delete the agent when we're done\n", "def cleanup(agent):\n", " # Only attempt cleanup if we have a valid agent\n", " if agent:\n", " try:\n", " # Delete the agent using the project client\n", " project_client.agents.delete_agent(agent.id)\n", " # Print confirmation message with the agent name\n", " print(f\"๐Ÿ—‘๏ธ Deleted health advisor agent: {agent.name}\")\n", " except Exception as e:\n", " # Handle any errors that occur during deletion\n", " print(f\"Error cleaning up agent: {e}\")\n", " else:\n", " # If no agent was provided, inform the user\n", " print(\"No agent to clean up.\")\n", "\n", "# Call cleanup function to delete our health advisor agent\n", "cleanup(health_advisor)" ] }, { "cell_type": "markdown", "id": "5263afbe", "metadata": {}, "source": [ "# Congratulations! ๐Ÿ†\n", "You've successfully built a **Fun & Fit Health Advisor** that can:\n", "1. **Respond** to basic health and fitness questions.\n", "2. **Use disclaimers** to encourage safe, professional consultation.\n", "3. **Provide** general diet and wellness information.\n", "4. **Use** the synergy of **Azure AI Foundry** modules to power the conversation.\n", "\n", "## Next Steps\n", "- Explore adding more advanced tools (like **FileSearchTool** or **CodeInterpreterTool**) to provide more specialized info.\n", "- Evaluate your AI's performance with **azure-ai-evaluation**!\n", "- Add **OpenTelemetry** or Azure Monitor for deeper insights.\n", "- Incorporate **function calling** if you want to handle things like advanced calculation or direct data analysis.\n", "\n", "#### Let's proceed to [2-code_interpreter.ipynb](2-code_interpreter.ipynb)\n", "\n", "Happy (healthy) coding! ๐Ÿ’ช" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.11" } }, "nbformat": 4, "nbformat_minor": 5 }