|
20 | 20 | },
|
21 | 21 | {
|
22 | 22 | "cell_type": "code",
|
23 |
| - "execution_count": null, |
| 23 | + "execution_count": 4, |
24 | 24 | "metadata": {},
|
25 | 25 | "outputs": [],
|
26 | 26 | "source": [
|
| 27 | + "import os \n", |
27 | 28 | "from typing import Annotated\n",
|
28 | 29 | "from openai import AsyncOpenAI\n",
|
29 | 30 | "\n",
|
| 31 | + "from dotenv import load_dotenv\n", |
| 32 | + "\n", |
| 33 | + "\n", |
30 | 34 | "\n",
|
31 | 35 | "from semantic_kernel.kernel import Kernel\n",
|
32 | 36 | "from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion\n",
|
|
62 | 66 | },
|
63 | 67 | {
|
64 | 68 | "cell_type": "code",
|
65 |
| - "execution_count": null, |
| 69 | + "execution_count": 5, |
66 | 70 | "metadata": {},
|
67 | 71 | "outputs": [],
|
68 | 72 | "source": [
|
|
108 | 112 | },
|
109 | 113 | {
|
110 | 114 | "cell_type": "code",
|
111 |
| - "execution_count": null, |
| 115 | + "execution_count": 6, |
112 | 116 | "metadata": {},
|
113 | 117 | "outputs": [],
|
114 | 118 | "source": [
|
115 | 119 | "load_dotenv()\n",
|
116 | 120 | "client = AsyncOpenAI(\n",
|
117 |
| - " api_key=os.getenv(\"GITHUB_TOKEN\"), base_url=\"https://models.inference.ai.azure.com/\")\n", |
| 121 | + " api_key=os.environ.get(\"GITHUB_TOKEN\"), base_url=\"https://models.inference.ai.azure.com/\")\n", |
118 | 122 | "\n",
|
119 | 123 | "kernel = Kernel()\n",
|
120 | 124 | "kernel.add_plugin(DestinationsPlugin(), plugin_name=\"destinations\")\n",
|
|
142 | 146 | },
|
143 | 147 | {
|
144 | 148 | "cell_type": "code",
|
145 |
| - "execution_count": null, |
| 149 | + "execution_count": 7, |
146 | 150 | "metadata": {},
|
147 | 151 | "outputs": [],
|
148 | 152 | "source": [
|
|
153 | 157 | },
|
154 | 158 | {
|
155 | 159 | "cell_type": "code",
|
156 |
| - "execution_count": null, |
| 160 | + "execution_count": 8, |
157 | 161 | "metadata": {},
|
158 | 162 | "outputs": [],
|
159 | 163 | "source": [
|
|
183 | 187 | },
|
184 | 188 | {
|
185 | 189 | "cell_type": "code",
|
186 |
| - "execution_count": null, |
| 190 | + "execution_count": 9, |
187 | 191 | "metadata": {},
|
188 |
| - "outputs": [], |
| 192 | + "outputs": [ |
| 193 | + { |
| 194 | + "data": { |
| 195 | + "text/html": [ |
| 196 | + "<div style='margin-bottom:10px'><div style='font-weight:bold'>User:</div><div style='margin-left:20px'>Plan me a day trip.</div></div><div style='margin-bottom:10px'><details><summary style='cursor:pointer; font-weight:bold; color:#0066cc;'>Function Calls (click to expand)</summary><div style='margin:10px; padding:10px; background-color:#f8f8f8; border:1px solid #ddd; border-radius:4px; white-space:pre-wrap;'>Calling: get_random_destination()<br>Calling: ({})<br>Result: Rio de Janeiro, Brazil</div></details></div><div style='margin-bottom:20px'><div style='font-weight:bold'>TravelAgent:</div><div style='margin-left:20px; white-space:pre-wrap'>I've planned a day trip to the beautiful city of Rio de Janeiro, Brazil! Here’s a suggested itinerary for your day:\n", |
| 197 | + "\n", |
| 198 | + "### Morning- **Breakfast**: Start your day with a traditional Brazilian breakfast of pão de queijo (cheese bread) and fresh tropical fruit at a local café.\n", |
| 199 | + "- **Visit Christ the Redeemer**: Head to the iconic Christ the Redeemer statue. You can take a train through the Tijuca Forest to reach the summit, and enjoy stunning views of the city along the way.\n", |
| 200 | + "\n", |
| 201 | + "### Midday- **Lunch**: Enjoy a leisurely lunch at a local restaurant in the Santa Teresa neighborhood. Try some feijoada, a hearty Brazilian stew.\n", |
| 202 | + "- **Explore Santa Teresa**: Stroll through the charming streets of Santa Teresa, filled with art galleries, colorful houses, and beautiful views.\n", |
| 203 | + "\n", |
| 204 | + "### Afternoon- **Sugarloaf Mountain**: Take the cable car to the top of Sugarloaf Mountain for panoramic views of Rio, including Copacabana and the sprawling coastline.\n", |
| 205 | + "- **Relax at Copacabana Beach**: Spend some time relaxing on the famous Copacabana Beach. If you're up for it, you can enjoy a refreshing swim or try out beach volleyball with locals.\n", |
| 206 | + "\n", |
| 207 | + "### Evening- **Dinner**: Dine at a seafood restaurant with a view of the beach, enjoying fresh catch of the day and a caipirinha cocktail, a Brazilian favorite.\n", |
| 208 | + "- **Nightlife**: If you’re up for it, explore the lively nightlife of Rio in Lapa, where you can find samba clubs and live music.\n", |
| 209 | + "\n", |
| 210 | + "Enjoy your day trip to Rio de Janeiro!</div></div><hr>" |
| 211 | + ], |
| 212 | + "text/plain": [ |
| 213 | + "<IPython.core.display.HTML object>" |
| 214 | + ] |
| 215 | + }, |
| 216 | + "metadata": {}, |
| 217 | + "output_type": "display_data" |
| 218 | + }, |
| 219 | + { |
| 220 | + "data": { |
| 221 | + "text/html": [ |
| 222 | + "<div style='margin-bottom:10px'><div style='font-weight:bold'>User:</div><div style='margin-left:20px'>I don't like that destination. Plan me another vacation.</div></div><div style='margin-bottom:10px'><details><summary style='cursor:pointer; font-weight:bold; color:#0066cc;'>Function Calls (click to expand)</summary><div style='margin:10px; padding:10px; background-color:#f8f8f8; border:1px solid #ddd; border-radius:4px; white-space:pre-wrap;'>Calling: get_random_destination()<br>Calling: ({})<br>Result: Cape Town, South Africa</div></details></div><div style='margin-bottom:20px'><div style='font-weight:bold'>TravelAgent:</div><div style='margin-left:20px; white-space:pre-wrap'>How about a day trip to stunning Cape Town, South Africa? Here's a suggested itinerary:\n", |
| 223 | + "\n", |
| 224 | + "### Morning- **Breakfast**: Start your day with a hearty breakfast at a café along the V&A Waterfront, enjoying views of the harbor and Table Mountain.\n", |
| 225 | + "- **Table Mountain**: Take the cable car up to Table Mountain for breathtaking panoramic views of the city and the ocean. Don’t forget your camera!\n", |
| 226 | + "\n", |
| 227 | + "### Midday- **Lunch**: Enjoy lunch at one of the waterfront restaurants, where you can savor fresh seafood or local South African dishes.\n", |
| 228 | + "- **Visit Kirstenbosch National Botanical Garden**: Explore these beautiful gardens nestled at the foot of Table Mountain. Walk along the treetop canopy walkway for a unique perspective of the flora.\n", |
| 229 | + "\n", |
| 230 | + "### Afternoon- **Explore the Cape Peninsula**: Take a scenic drive along Chapman's Peak Drive to Cape Point. Here, you can hike to the lighthouse and enjoy spectacular ocean views.\n", |
| 231 | + "- **Boulders Beach**: Afterward, head to Boulders Beach to see the famous African penguin colony.\n", |
| 232 | + "\n", |
| 233 | + "### Evening- **Dinner**: Return to Cape Town for dinner at a restaurant in the city center or along the waterfront, where you can enjoy a fine dining experience featuring local wines and cuisine.\n", |
| 234 | + "- **Sunset at Signal Hill**: End your day by watching the sunset from Signal Hill, offering a stunning view of the city and the ocean.\n", |
| 235 | + "\n", |
| 236 | + "Enjoy your day trip in Cape Town!</div></div><hr>" |
| 237 | + ], |
| 238 | + "text/plain": [ |
| 239 | + "<IPython.core.display.HTML object>" |
| 240 | + ] |
| 241 | + }, |
| 242 | + "metadata": {}, |
| 243 | + "output_type": "display_data" |
| 244 | + } |
| 245 | + ], |
189 | 246 | "source": [
|
190 | 247 | "from IPython.display import display, HTML\n",
|
191 | 248 | "\n",
|
|
212 | 269 | "\n",
|
213 | 270 | " agent_name: str | None = None\n",
|
214 | 271 | " full_response = \"\"\n",
|
| 272 | + " function_calls = []\n", |
| 273 | + " function_results = {}\n", |
215 | 274 | "\n",
|
216 |
| - " # Collect the agent's response silently (no printing)\n", |
| 275 | + " # Collect the agent's response with function call tracking\n", |
217 | 276 | " async for content in agent.invoke_stream(chat_history):\n",
|
218 |
| - " if not agent_name:\n", |
| 277 | + " if not agent_name and hasattr(content, 'name'):\n", |
219 | 278 | " agent_name = content.name\n",
|
220 |
| - " if (\n", |
| 279 | + "\n", |
| 280 | + " # Track function calls and results\n", |
| 281 | + " for item in content.items:\n", |
| 282 | + " if isinstance(item, FunctionCallContent):\n", |
| 283 | + " call_info = f\"Calling: {item.function_name}({item.arguments})\"\n", |
| 284 | + " function_calls.append(call_info)\n", |
| 285 | + " elif isinstance(item, FunctionResultContent):\n", |
| 286 | + " result_info = f\"Result: {item.result}\"\n", |
| 287 | + " function_calls.append(result_info)\n", |
| 288 | + " # Store function results\n", |
| 289 | + " function_results[item.function_name] = item.result\n", |
| 290 | + "\n", |
| 291 | + " # Add content to response if it's not a function-related message\n", |
| 292 | + " if (hasattr(content, 'content') and content.content and content.content.strip() and\n", |
221 | 293 | " not any(isinstance(item, (FunctionCallContent, FunctionResultContent))\n",
|
222 |
| - " for item in content.items)\n", |
223 |
| - " and content.content.strip()\n", |
224 |
| - " ):\n", |
| 294 | + " for item in content.items)):\n", |
225 | 295 | " full_response += content.content\n",
|
226 | 296 | "\n",
|
| 297 | + " # Add function calls to HTML if any occurred\n", |
| 298 | + " if function_calls:\n", |
| 299 | + " html_output += f\"<div style='margin-bottom:10px'>\"\n", |
| 300 | + " html_output += f\"<details>\"\n", |
| 301 | + " html_output += f\"<summary style='cursor:pointer; font-weight:bold; color:#0066cc;'>Function Calls (click to expand)</summary>\"\n", |
| 302 | + " html_output += f\"<div style='margin:10px; padding:10px; background-color:#f8f8f8; border:1px solid #ddd; border-radius:4px; white-space:pre-wrap;'>\"\n", |
| 303 | + " html_output += \"<br>\".join(function_calls)\n", |
| 304 | + " html_output += f\"</div></details></div>\"\n", |
| 305 | + "\n", |
227 | 306 | " # Add agent response to HTML\n",
|
228 | 307 | " html_output += f\"<div style='margin-bottom:20px'>\"\n",
|
229 | 308 | " html_output += f\"<div style='font-weight:bold'>{agent_name or 'Assistant'}:</div>\"\n",
|
|
0 commit comments