|
2 | 2 | "cells": [
|
3 | 3 | {
|
4 | 4 | "cell_type": "code",
|
5 |
| - "execution_count": 1, |
| 5 | + "execution_count": 10, |
6 | 6 | "metadata": {},
|
7 | 7 | "outputs": [],
|
8 | 8 | "source": [
|
9 | 9 | "import os\n",
|
10 | 10 | "from dotenv import load_dotenv\n",
|
| 11 | + "from pydantic import BaseModel, ValidationError, Field\n", |
11 | 12 | "\n",
|
| 13 | + "import json \n", |
12 | 14 | "\n",
|
13 |
| - "from typing import Annotated\n", |
| 15 | + "from typing import Annotated, List\n", |
14 | 16 | "from openai import AsyncOpenAI\n",
|
15 | 17 | "\n",
|
16 | 18 | "\n",
|
17 | 19 | "from semantic_kernel.kernel import Kernel\n",
|
18 |
| - "from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion\n", |
| 20 | + "from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, OpenAIChatPromptExecutionSettings\n", |
19 | 21 | "from semantic_kernel.agents import ChatCompletionAgent\n",
|
20 | 22 | "from semantic_kernel.contents import ChatHistory\n",
|
21 | 23 | "\n",
|
|
33 | 35 | },
|
34 | 36 | {
|
35 | 37 | "cell_type": "code",
|
36 |
| - "execution_count": 4, |
| 38 | + "execution_count": 11, |
37 | 39 | "metadata": {},
|
38 | 40 | "outputs": [],
|
39 | 41 | "source": [
|
40 | 42 | "load_dotenv()\n",
|
41 | 43 | "client = AsyncOpenAI(\n",
|
42 | 44 | " api_key=os.environ.get(\"GITHUB_TOKEN\"), base_url=\"https://models.inference.ai.azure.com/\")\n",
|
43 | 45 | "\n",
|
| 46 | + "kernel = Kernel()\n", |
| 47 | + "\n", |
44 | 48 | "\n",
|
45 | 49 | "chat_completion_service = OpenAIChatCompletion(\n",
|
46 | 50 | " ai_model_id=\"gpt-4o-mini\",\n",
|
|
52 | 56 | },
|
53 | 57 | {
|
54 | 58 | "cell_type": "code",
|
55 |
| - "execution_count": 6, |
| 59 | + "execution_count": 12, |
| 60 | + "metadata": {}, |
| 61 | + "outputs": [], |
| 62 | + "source": [ |
| 63 | + "class SubTask(BaseModel):\n", |
| 64 | + " assigned_agent: str = Field(\n", |
| 65 | + " description=\"The specific agent assigned to handle this subtask\")\n", |
| 66 | + " task_details: str = Field(\n", |
| 67 | + " description=\"Detailed description of what needs to be done for this subtask\")\n", |
| 68 | + "\n", |
| 69 | + "\n", |
| 70 | + "class TravelPlan(BaseModel):\n", |
| 71 | + " main_task: str = Field(\n", |
| 72 | + " description=\"The overall travel request from the user\")\n", |
| 73 | + " subtasks: List[SubTask] = Field(\n", |
| 74 | + " description=\"List of subtasks broken down from the main task, each assigned to a specialized agent\")" |
| 75 | + ] |
| 76 | + }, |
| 77 | + { |
| 78 | + "cell_type": "code", |
| 79 | + "execution_count": 13, |
56 | 80 | "metadata": {},
|
57 | 81 | "outputs": [],
|
58 | 82 | "source": [
|
|
67 | 91 | " - DestinationInfo: For providing information about destinations\n",
|
68 | 92 | " - DefaultAgent: For handling general requests\"\"\"\n",
|
69 | 93 | "\n",
|
| 94 | + "# Get prompt execution settings and configure response format\n", |
| 95 | + "settings = kernel.get_prompt_execution_settings_from_service_id(\"default\")\n", |
| 96 | + "assert isinstance(settings, OpenAIChatPromptExecutionSettings)\n", |
| 97 | + "settings.response_format = TravelPlan\n", |
70 | 98 | "\n",
|
71 | 99 | "agent = ChatCompletionAgent(\n",
|
72 | 100 | " kernel=kernel,\n",
|
73 | 101 | " name=AGENT_NAME,\n",
|
74 | 102 | " instructions=AGENT_INSTRUCTIONS,\n",
|
| 103 | + " arguments=KernelArguments(settings) \n", |
75 | 104 | ")"
|
76 | 105 | ]
|
77 | 106 | },
|
78 | 107 | {
|
79 | 108 | "cell_type": "code",
|
80 |
| - "execution_count": 7, |
| 109 | + "execution_count": 20, |
81 | 110 | "metadata": {},
|
82 | 111 | "outputs": [
|
83 | 112 | {
|
84 | 113 | "data": {
|
85 | 114 | "text/html": [
|
86 |
| - "<div style='margin-bottom:10px'><div style='font-weight:bold'>User:</div><div style='margin-left:20px'>Create a travel plan for a family of 2 kids from Singapore to Melboune</div></div><div style='margin-bottom:20px'><div style='font-weight:bold'>TravelAgent:</div><div style='margin-left:20px; white-space:pre-wrap'>To create a comprehensive travel plan for a family of four traveling from Singapore to Melbourne, I will need to run the following agents:\n", |
87 |
| - "\n", |
88 |
| - "1. **FlightBooking**: To find and book flights from Singapore to Melbourne.\n", |
89 |
| - "2. **HotelBooking**: To find and book family-friendly accommodations in Melbourne.\n", |
90 |
| - "3. **CarRental**: To arrange a rental car for easy transportation within Melbourne.\n", |
91 |
| - "4. **ActivitiesBooking**: To find activities suitable for a family with kids in Melbourne.\n", |
92 |
| - "5. **DestinationInfo**: To provide information about Melbourne, including attractions and tips for families.\n", |
93 |
| - "\n", |
94 |
| - "Let me proceed with these agents to create your travel plan!</div></div><hr>" |
| 115 | + "<div style='margin-bottom:10px'><div style='font-weight:bold'>User:</div><div style='margin-left:20px'>Create a travel plan for a family of 2 kids from Singapore to Melboune</div></div><div style='margin-bottom:20px'><div style='font-weight:bold'>Validated Travel Plan:</div><pre style='margin-left:20px; padding:10px; border-radius:5px;'>{\n", |
| 116 | + " \"main_task\": \"Travel plan for a family trip from Singapore to Melbourne\",\n", |
| 117 | + " \"subtasks\": [\n", |
| 118 | + " {\n", |
| 119 | + " \"assigned_agent\": \"FlightBooking\",\n", |
| 120 | + " \"task_details\": \"Book round-trip flights from Singapore to Melbourne for a family of four (2 adults, 2 kids) including preferred flight times and airlines.\"\n", |
| 121 | + " },\n", |
| 122 | + " {\n", |
| 123 | + " \"assigned_agent\": \"HotelBooking\",\n", |
| 124 | + " \"task_details\": \"Find and book family-friendly accommodation in Melbourne for four guests, ideally near local attractions and amenities.\"\n", |
| 125 | + " },\n", |
| 126 | + " {\n", |
| 127 | + " \"assigned_agent\": \"CarRental\",\n", |
| 128 | + " \"task_details\": \"Arrange for a rental car in Melbourne for family use during the stay, including options for child car seats.\"\n", |
| 129 | + " },\n", |
| 130 | + " {\n", |
| 131 | + " \"assigned_agent\": \"ActivitiesBooking\",\n", |
| 132 | + " \"task_details\": \"Plan and book family-friendly activities and attractions in Melbourne suitable for kids, such as zoos, parks, and museums.\"\n", |
| 133 | + " },\n", |
| 134 | + " {\n", |
| 135 | + " \"assigned_agent\": \"DestinationInfo\",\n", |
| 136 | + " \"task_details\": \"Provide detailed information about Melbourne, including weather, local cuisine, and family-friendly tips.\"\n", |
| 137 | + " }\n", |
| 138 | + " ]\n", |
| 139 | + "}</pre></div><hr>" |
95 | 140 | ],
|
96 | 141 | "text/plain": [
|
97 | 142 | "<IPython.core.display.HTML object>"
|
|
131 | 176 | " async for content in agent.invoke_stream(chat_history):\n",
|
132 | 177 | " if not agent_name and hasattr(content, 'name'):\n",
|
133 | 178 | " agent_name = content.name\n",
|
134 |
| - "\n", |
135 |
| - " # Add content to response\n", |
136 |
| - " if hasattr(content, 'content') and content.content and content.content.strip():\n", |
| 179 | + " # Add this line to collect the response content\n", |
| 180 | + " if hasattr(content, 'content') and content.content is not None:\n", |
137 | 181 | " full_response += content.content\n",
|
138 | 182 | "\n",
|
139 |
| - " # Add agent response to HTML\n", |
140 |
| - " html_output += f\"<div style='margin-bottom:20px'>\"\n", |
141 |
| - " html_output += f\"<div style='font-weight:bold'>{agent_name or 'Assistant'}:</div>\"\n", |
142 |
| - " html_output += f\"<div style='margin-left:20px; white-space:pre-wrap'>{full_response}</div>\"\n", |
143 |
| - " html_output += f\"</div>\"\n", |
| 183 | + " try:\n", |
| 184 | + " # Try to validate the response as a TravelPlan\n", |
| 185 | + " travel_plan = TravelPlan.model_validate_json(full_response)\n", |
| 186 | + "\n", |
| 187 | + " # Display the validated model as formatted JSON\n", |
| 188 | + " formatted_json = json.dumps(travel_plan.model_dump(), indent=2)\n", |
| 189 | + " html_output += f\"<div style='margin-bottom:20px'>\"\n", |
| 190 | + " html_output += f\"<div style='font-weight:bold'>Validated Travel Plan:</div>\"\n", |
| 191 | + " html_output += f\"<pre style='margin-left:20px; padding:10px; border-radius:5px;'>{formatted_json}</pre>\"\n", |
| 192 | + " html_output += f\"</div>\"\n", |
| 193 | + " except ValidationError as e:\n", |
| 194 | + " # Handle validation errors\n", |
| 195 | + " html_output += f\"<div style='margin-bottom:20px; color:red;'>\"\n", |
| 196 | + " html_output += f\"<div style='font-weight:bold'>Validation Error:</div>\"\n", |
| 197 | + " html_output += f\"<pre style='margin-left:20px;'>{str(e)}</pre>\"\n", |
| 198 | + " html_output += f\"</div>\"\n", |
| 199 | + " # Add this to see what the response contains for debugging\n", |
| 200 | + " html_output += f\"<div style='margin-bottom:20px;'>\"\n", |
| 201 | + " html_output += f\"<div style='font-weight:bold'>Raw Response:</div>\"\n", |
| 202 | + " html_output += f\"<div style='margin-left:20px; white-space:pre-wrap'>{full_response}</div>\"\n", |
| 203 | + " html_output += f\"</div>\"\n", |
| 204 | + "\n", |
144 | 205 | " html_output += \"<hr>\"\n",
|
145 | 206 | "\n",
|
146 | 207 | " # Display formatted HTML\n",
|
|
0 commit comments