From 095ddd03f6a7058f0f26d2fd7a2c2687c3112a25 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 30 Nov 2023 09:52:39 -0500 Subject: [PATCH 01/25] add complex plan sample --- KernelMemory/Memories.cs | 4 +- notebook.ipynb | 493 +++++++++++++++++++++++++++++++++++---- 2 files changed, 451 insertions(+), 46 deletions(-) diff --git a/KernelMemory/Memories.cs b/KernelMemory/Memories.cs index ca2084d..c3c3d24 100644 --- a/KernelMemory/Memories.cs +++ b/KernelMemory/Memories.cs @@ -24,6 +24,8 @@ static async void LoadTextMemories() { await memory.ImportTextAsync("El súper héroe favorito de Gisela es Batman", documentId: "gis01", tags: new TagCollection { { "type", "people" } }); await memory.ImportTextAsync("La última película que Gisela vio de súper héroes fue Guardianes de la Galaxia Vol. 3 ", documentId: "gis02", tags: new TagCollection { { "type", "people" } }); + await memory.ImportTextAsync("El súper héroe favorito de Bruno es Invencible", documentId: "bru01", tags: new TagCollection { { "type", "people" } }); + await memory.ImportTextAsync("La última película que Bruno vio de súper héroes fue Batman de Tim Burton ", documentId: "bru02", tags: new TagCollection { { "type", "people" } }); } static async void LoadDocs() @@ -49,7 +51,7 @@ public static async Task AboutTheDocuments(string ask) return JsonSerializer.Serialize(new { answer = answer.Result, references = answer.RelevantSources.Select(x => x.SourceName) }); } - [SKFunction, Description("Responde preguntas sobre Gisela")] + [SKFunction, Description("Responde preguntas sobre Bruno y Gisela")] public static async Task AboutMe(string ask) { var answer = await memory.AskAsync(ask, filter: new MemoryFilter().ByTag("type", "people")); diff --git a/notebook.ipynb b/notebook.ipynb index caf6816..936c2d1 100644 --- a/notebook.ipynb +++ b/notebook.ipynb @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -74,7 +74,7 @@ }, "outputs": [], "source": [ - "az account set -n \"Internal Azure Subscription Gisela\"" + "az account set -n \"Visual Studio Enterprise Subscription\"" ] }, { @@ -86,7 +86,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -235,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -281,7 +281,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -293,7 +293,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 1.0.0-beta8
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.0.0-beta8\"" ] @@ -307,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -338,7 +348,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -366,7 +376,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -423,7 +433,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -449,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -476,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -559,7 +569,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -571,7 +581,19 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Claro, aquí tienes un chiste:\n", + "\n", + "¿Por qué Batman se metió al boxeo?\n", + "\n", + "Porque quería ser un \"golpe-ador\" nocturno.\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -585,7 +607,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -600,7 +622,7 @@ "outputs": [], "source": [ "var variables = new ContextVariables{\n", - " [\"input\"] = \"Cuentame un chiste sobre Halloween\",\n", + " [\"input\"] = \"Cuentame un chiste sobre Navidad\",\n", " [\"hero\"] = \"Ironman\"\n", "};" ] @@ -614,7 +636,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -640,7 +662,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -652,7 +674,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "¿Por qué Ironman no usa su traje en Navidad?\n", + "\n", + "Porque ya tiene suficiente con el hierro de los turrones.\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -666,7 +698,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -693,7 +725,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -705,7 +737,27 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Había una vez, en una fría noche de Navidad 🎄, Hulk 💪, nuestro héroe verde y gigante, estaba solo en su casa. A pesar de su fuerza y coraje, sentía un vacío en su corazón 💔.\n", + "\n", + "En medio de la noche 🌙, Hulk escuchó un ruido proveniente del techo. Se levantó y vio a Santa Claus 🎅 atascado en la chimenea. \"¡Oh no! ¡Estoy atrapado!\", gritó Santa.\n", + "\n", + "Hulk, con su fuerza sobrehumana, liberó a Santa de la chimenea. \"¡Gracias, Hulk!\", dijo Santa aliviado. Pero había un problema: el trineo 🛷 de Santa estaba roto.\n", + "\n", + "Hulk, decidido a salvar la Navidad, usó sus habilidades para reparar el trineo. Con un poco de esfuerzo y mucha cinta adhesiva, el trineo estaba listo para volar nuevamente.\n", + "\n", + "Santa le agradeció a Hulk y le ofreció un regalo 🎁: \"Hulk, has salvado la Navidad. ¿Qué te gustaría como regalo?\" Hulk pensó por un momento y luego respondió: \"Quiero amigos con quienes compartir estas fiestas\".\n", + "\n", + "Santa sonrió y asintió. Esa noche, Hulk no estuvo solo. Los Vengadores se reunieron en su casa para celebrar la Navidad juntos. Fue una noche llena de risas 😂, regalos 🎁 y buenos momentos.\n", + "\n", + "Desde\r\n" + ] + } + ], "source": [ "var result = await kernel.RunAsync(\"Cuentame una historia sobre las navidades\", writerPluginFunctions[\"StoryGen\"]);\n", "Console.WriteLine(result);" @@ -720,7 +772,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -732,7 +784,27 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "¡Hola! 🐾\n", + "\n", + "Soy Catwoman, tu heroína de confianza. Quiero informarte que estaré fuera de la ciudad desde el 24 de diciembre hasta el 1 de enero, disfrutando de unas merecidas vacaciones navideñas. 🎄🎅\n", + "\n", + "Durante mi ausencia, no podré utilizar mis habilidades de agilidad felina, ni mi astucia para resolver los problemas que puedan surgir. Pero no te preocupes, no te dejaré desprotegido. 🦸‍♀️\n", + "\n", + "En mi lugar, Batman estará vigilando la ciudad. Con su fuerza, inteligencia y tecnología avanzada, estoy segura de que podrá manejar cualquier situación que se presente. 🦇💪\n", + "\n", + "Si necesitas ayuda, no dudes en contactar a Batman. Él estará más que dispuesto a ayudarte en mi ausencia. \n", + "\n", + "Gracias por tu comprensión. Espero que tengas unas felices fiestas y un próspero año nuevo. Nos vemos en enero! 🎉🎊\n", + "\n", + "Adiós y cu\r\n" + ] + } + ], "source": [ "var result = await kernel.RunAsync(\"Crea un out of office para los días de Navidades\", writerPluginFunctions[\"OOF\"]);\n", "Console.WriteLine(result.GetValue());" @@ -779,7 +851,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -805,7 +877,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -835,7 +907,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -847,7 +919,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Selina Kyle\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -878,7 +958,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -930,7 +1010,7 @@ "source": [ "using System.Text.Json;\n", "\n", - "var ask = \"Me gustaría que me contaras un chiste sobre Batman y un out of office para las vacaciones de Navidad.\";\n", + "var ask = \"Me gustaría que me contaras un chiste sobre Batman, y con el chiste que hicieras un out of office con el chiste.\";\n", "var plan = await planner.CreatePlanAsync(ask);\n", "\n", "Console.WriteLine(\"Plan:\\n\");\n", @@ -946,7 +1026,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -958,7 +1038,29 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plan result:\n", + "\n", + "¡Hola! 🦇\n", + "\n", + "Soy Batman, tu héroe de confianza. Actualmente estoy fuera de la oficina, mejorando mis habilidades en un curso de música para perfeccionar mi \"Bat-acorde\". 🎵🎶\n", + "\n", + "Durante mi ausencia, no te preocupes, la ciudad de Gotham no quedará desprotegida. Mi buen amigo Superman estará vigilando y manteniendo la paz en mi lugar. 🦸‍♂️💪\n", + "\n", + "Si tienes alguna emergencia, no dudes en contactar a Superman. Él tiene la velocidad, la fuerza y la visión de rayos X para manejar cualquier situación que pueda surgir. 🚀🌍\n", + "\n", + "Volveré pronto, más fuerte y más afinado que nunca. Hasta entonces, mantén la calma y confía en Superman. \n", + "\n", + "Adiós y mantente seguro. 🌃🌙\n", + "\n", + "Batman.\n" + ] + } + ], "source": [ "var result = await kernel.RunAsync(plan);\n", "\n", @@ -966,6 +1068,216 @@ "Console.WriteLine(result.GetValue());" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## LABS\n", + "\n", + "El kernel ya tiene cargado los plugins, y la funcion, veamos si puede resolver un ejemplo mas complejo:" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plan:\n", + "\n", + "{\n", + " \"state\": [],\n", + " \"steps\": [\n", + " {\n", + " \"state\": [],\n", + " \"steps\": [],\n", + " \"parameters\": [\n", + " {\n", + " \"Key\": \"input\",\n", + " \"Value\": \"Batman\"\n", + " }\n", + " ],\n", + " \"outputs\": [\n", + " \"ALTER_EGO\"\n", + " ],\n", + " \"next_step_index\": 0,\n", + " \"name\": \"GetAlterEgo\",\n", + " \"plugin_name\": \"InfoPlugin\",\n", + " \"description\": \"Get the alter ego of a superhero\",\n", + " \"model_settings\": [],\n", + " \"RequestSettings\": null\n", + " },\n", + " {\n", + " \"state\": [],\n", + " \"steps\": [],\n", + " \"parameters\": [\n", + " {\n", + " \"Key\": \"input\",\n", + " \"Value\": \"Estoy fuera luchando contra el crimen\"\n", + " },\n", + " {\n", + " \"Key\": \"hero\",\n", + " \"Value\": \"Batman\"\n", + " }\n", + " ],\n", + " \"outputs\": [\n", + " \"OOF_MESSAGE\"\n", + " ],\n", + " \"next_step_index\": 0,\n", + " \"name\": \"OOF\",\n", + " \"plugin_name\": \"WriterPlugin\",\n", + " \"description\": \"Generate a out of office message for a given hero subject\",\n", + " \"model_settings\": [\n", + " {\n", + " \"service_id\": null,\n", + " \"model_id\": null,\n", + " \"max_tokens\": 250,\n", + " \"temperature\": 0.3,\n", + " \"top_p\": 0.0,\n", + " \"presence_penalty\": 0.0,\n", + " \"frequency_penalty\": 0.0\n", + " }\n", + " ],\n", + " \"RequestSettings\": {\n", + " \"service_id\": null,\n", + " \"model_id\": null,\n", + " \"max_tokens\": 250,\n", + " \"temperature\": 0.3,\n", + " \"top_p\": 0.0,\n", + " \"presence_penalty\": 0.0,\n", + " \"frequency_penalty\": 0.0\n", + " }\n", + " },\n", + " {\n", + " \"state\": [],\n", + " \"steps\": [],\n", + " \"parameters\": [\n", + " {\n", + " \"Key\": \"input\",\n", + " \"Value\": \"$OOF_MESSAGE. Firma: $ALTER_EGO\"\n", + " },\n", + " {\n", + " \"Key\": \"hero\",\n", + " \"Value\": \"Batman\"\n", + " }\n", + " ],\n", + " \"outputs\": [\n", + " \"RESULT__FINAL_MESSAGE\"\n", + " ],\n", + " \"next_step_index\": 0,\n", + " \"name\": \"OOF\",\n", + " \"plugin_name\": \"WriterPlugin\",\n", + " \"description\": \"Generate a out of office message for a given hero subject\",\n", + " \"model_settings\": [\n", + " {\n", + " \"service_id\": null,\n", + " \"model_id\": null,\n", + " \"max_tokens\": 250,\n", + " \"temperature\": 0.3,\n", + " \"top_p\": 0.0,\n", + " \"presence_penalty\": 0.0,\n", + " \"frequency_penalty\": 0.0\n", + " }\n", + " ],\n", + " \"RequestSettings\": {\n", + " \"service_id\": null,\n", + " \"model_id\": null,\n", + " \"max_tokens\": 250,\n", + " \"temperature\": 0.3,\n", + " \"top_p\": 0.0,\n", + " \"presence_penalty\": 0.0,\n", + " \"frequency_penalty\": 0.0\n", + " }\n", + " }\n", + " ],\n", + " \"parameters\": [],\n", + " \"outputs\": [\n", + " \"RESULT__FINAL_MESSAGE\"\n", + " ],\n", + " \"next_step_index\": 0,\n", + " \"name\": \"plandae5d6d9b0974e118cdbfad1f511b097\",\n", + " \"plugin_name\": \"Plan\",\n", + " \"description\": \"Me gustar\\u00EDa que avveriguaras la identidad de Batman, y que hicieras un out of office para Batman firmando con la identidad del mismo.\",\n", + " \"model_settings\": [],\n", + " \"RequestSettings\": null\n", + "}\n" + ] + } + ], + "source": [ + "using System.Text.Json;\n", + "\n", + "var ask_complex = \"Me gustaría que avveriguaras el alter ego de Batman, y que hicieras un out of office para Batman firmando con el alter ego del mismo.\";\n", + "var plan_complex = await planner.CreatePlanAsync(ask_complex);\n", + "\n", + "Console.WriteLine(\"Plan:\\n\");\n", + "Console.WriteLine(JsonSerializer.Serialize(plan_complex, new JsonSerializerOptions { WriteIndented = true }));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ejecutemos el plan y veamos su output:" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plan result:\n", + "\n", + "Estimado remitente,\n", + "\n", + "🦇🌃 Actualmente, me encuentro fuera de la oficina, combatiendo el crimen en las oscuras calles de Gotham. Como Batman, mi deber es proteger la ciudad y garantizar la seguridad de sus ciudadanos, lo que a veces requiere de mi atención total y absoluta.\n", + "\n", + "Durante mi ausencia, no te preocupes, no estás desprotegido. 🦸‍♂️💫 Superman estará disponible para asistirte en cualquier emergencia que pueda surgir. Con su velocidad, fuerza y capacidad de volar, estoy seguro de que podrá manejar cualquier situación que se presente.\n", + "\n", + "Agradezco tu comprensión y paciencia durante este tiempo. Recuerda, cada uno de nosotros tiene el poder de hacer una diferencia, por pequeña que sea. 🌟💪\n", + "\n", + "Regresaré tan pronto como Gotham esté segura nuevamente. Hasta entonces, mantén la calma y confía en que el bien siempre prevalecerá.\n", + "\n", + "Adiós y cuídate,\n", + "\n", + "Batman 🦇🌙. Firma: Terry\n" + ] + } + ], + "source": [ + "var result_complex = await kernel.RunAsync(plan_complex);\n", + "\n", + "Console.WriteLine(\"Plan result:\\n\");\n", + "Console.WriteLine(result_complex.GetValue());" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -991,7 +1303,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 50, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1003,7 +1315,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.KernelMemory.Core, 0.11.231120.6-preview
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.KernelMemory.Core, 0.11.231120.6-preview\"\n", "\n", @@ -1019,7 +1341,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 51, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1031,7 +1353,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "ename": "Error", + "evalue": "Command cancelled.", + "output_type": "error", + "traceback": [ + "Command cancelled." + ] + } + ], "source": [ "var openApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\");\n", "\n", @@ -1048,7 +1379,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1074,7 +1405,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1086,11 +1417,25 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Answer: Mi héroe favorito es Batman.\n", + " - content.txt - gis01/62eb12bbb53c4a31924fbe94b9a7b4c2 [Thursday, November 30, 2023]\n", + " - content.txt - bru01/881e2c778cca47a9975fa2caf0aeaf4b [Thursday, November 30, 2023]\n", + " - content.txt - bru02/2b2d1c65585443b49bbb95236323f5b6 [Thursday, November 30, 2023]\n", + " - content.txt - gis02/bdca3bc681c44aa3a339d90be33d2db4 [Thursday, November 30, 2023]\n", + "{\"answer\":\"Mi h\\u00E9roe favorito es Batman.\",\"references\":[\"content.txt\",\"content.txt\",\"content.txt\",\"content.txt\"]}\n" + ] + } + ], "source": [ "var planner = new SequentialPlanner(kernel);\n", "\n", - "var plan = await planner.CreatePlanAsync(\"¿Quién es el héroe favorito de Gisela?\");\n", + "var plan = await planner.CreatePlanAsync(\"¿Quién es el héroe favorito de Bruno?\");\n", "\n", "var result = await kernel.RunAsync(plan);\n", "\n", @@ -1099,7 +1444,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1111,11 +1456,58 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "ename": "Error", + "evalue": "Microsoft.SemanticKernel.Diagnostics.SKException: Not possible to create plan for goal with available functions.\nGoal:¿Cuál fue la última película que vio Bruno?\nFunctions:\nFunPlugin.Joke:\n description: Generate a funny joke about heroes\n inputs:\n - input: Joke subject\n - hero: Give the name of the hero you want to joke about\n\nInfoPlugin.GetAlterEgo:\n description: Get the alter ego of a superhero\n inputs:\n - input: \n\nMemoriesPlugin.AboutMe:\n description: Responde preguntas sobre Bruno\n inputs:\n - ask: \n\nMemoriesPlugin.AboutTheDocuments:\n description: Sobre el volumen\n inputs:\n - ask: \n\nWriterPlugin.OOF:\n description: Generate a out of office message for a given hero subject\n inputs:\n - input: The reason for being out of office\n - hero: hero name (default value: Catwoman)\n\nWriterPlugin.StoryGen:\n description: Generate a short story about the hero of your choice.\n inputs:\n - input: story subject\n - hero: hero name (default value: Hulk)\r\n at Microsoft.SemanticKernel.Planners.SequentialPlanner.CreatePlanAsync(String goal, CancellationToken cancellationToken)\r\n at Submission#40.<>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)", + "output_type": "error", + "traceback": [ + "Microsoft.SemanticKernel.Diagnostics.SKException: Not possible to create plan for goal with available functions.\n", + "Goal:¿Cuál fue la última película que vio Bruno?\n", + "Functions:\n", + "FunPlugin.Joke:\n", + " description: Generate a funny joke about heroes\n", + " inputs:\n", + " - input: Joke subject\n", + " - hero: Give the name of the hero you want to joke about\n", + "\n", + "InfoPlugin.GetAlterEgo:\n", + " description: Get the alter ego of a superhero\n", + " inputs:\n", + " - input: \n", + "\n", + "MemoriesPlugin.AboutMe:\n", + " description: Responde preguntas sobre Bruno\n", + " inputs:\n", + " - ask: \n", + "\n", + "MemoriesPlugin.AboutTheDocuments:\n", + " description: Sobre el volumen\n", + " inputs:\n", + " - ask: \n", + "\n", + "WriterPlugin.OOF:\n", + " description: Generate a out of office message for a given hero subject\n", + " inputs:\n", + " - input: The reason for being out of office\n", + " - hero: hero name (default value: Catwoman)\n", + "\n", + "WriterPlugin.StoryGen:\n", + " description: Generate a short story about the hero of your choice.\n", + " inputs:\n", + " - input: story subject\n", + " - hero: hero name (default value: Hulk)\r\n", + " at Microsoft.SemanticKernel.Planners.SequentialPlanner.CreatePlanAsync(String goal, CancellationToken cancellationToken)\r\n", + " at Submission#40.<>d__0.MoveNext()\r\n", + "--- End of stack trace from previous location ---\r\n", + " at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)" + ] + } + ], "source": [ "var planner = new SequentialPlanner(kernel);\n", "\n", - "var plan = await planner.CreatePlanAsync(\"¿Cuál fue la última película que vio Gisela?\");\n", + "var plan = await planner.CreatePlanAsync(\"¿Cuál fue la última película que vio Bruno?\");\n", "\n", "var result = await kernel.RunAsync(plan);\n", "\n", @@ -1131,7 +1523,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1143,7 +1535,18 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Answer: Este volumen de Batman incluye la historia definitiva del Caballero Oscuro en el cómic, el cine y más allá. Detalla toda la historia de Batman y las muchas formas que ha asumido a lo largo de los años, en cómics, televisión, animación, películas, videojuegos y más. Además, incluye comentarios exclusivos de personas creativas que han sido fundamentales para la creación del legado de Batman. También cuenta con documentos extraíbles que ayudan a acentuar la experiencia de lectura.\n", + " - Norma editorial - Septiembre 2020.pdf - doc001/43b043c48789457abbce9733779e9024 [Thursday, November 30, 2023]\n", + "{\"answer\":\"Este volumen de Batman incluye la historia definitiva del Caballero Oscuro en el c\\u00F3mic, el cine y m\\u00E1s all\\u00E1. Detalla toda la historia de Batman y las muchas formas que ha asumido a lo largo de los a\\u00F1os, en c\\u00F3mics, televisi\\u00F3n, animaci\\u00F3n, pel\\u00EDculas, videojuegos y m\\u00E1s. Adem\\u00E1s, incluye comentarios exclusivos de personas creativas que han sido fundamentales para la creaci\\u00F3n del legado de Batman. Tambi\\u00E9n cuenta con documentos extra\\u00EDbles que ayudan a acentuar la experiencia de lectura.\",\"references\":[\"Norma editorial - Septiembre 2020.pdf\"]}\n" + ] + } + ], "source": [ "var planner = new SequentialPlanner(kernel);\n", "\n", From 71994ca5269e2613f3bce97e5a6c040aac8f7696 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 30 Nov 2023 09:58:47 -0500 Subject: [PATCH 02/25] agregando mas ejemplos para Kernel Memory --- notebook.ipynb | 430 ++++++------------------------------------------- 1 file changed, 45 insertions(+), 385 deletions(-) diff --git a/notebook.ipynb b/notebook.ipynb index 936c2d1..2b33ee9 100644 --- a/notebook.ipynb +++ b/notebook.ipynb @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -86,7 +86,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -235,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -281,7 +281,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -293,17 +293,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel, 1.0.0-beta8
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.0.0-beta8\"" ] @@ -317,7 +307,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -348,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -376,7 +366,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -433,7 +423,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -459,7 +449,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -486,7 +476,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -569,7 +559,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -581,19 +571,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Claro, aquí tienes un chiste:\n", - "\n", - "¿Por qué Batman se metió al boxeo?\n", - "\n", - "Porque quería ser un \"golpe-ador\" nocturno.\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -607,7 +585,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -636,7 +614,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -662,7 +640,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -674,17 +652,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "¿Por qué Ironman no usa su traje en Navidad?\n", - "\n", - "Porque ya tiene suficiente con el hierro de los turrones.\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -698,7 +666,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -725,7 +693,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -737,27 +705,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Había una vez, en una fría noche de Navidad 🎄, Hulk 💪, nuestro héroe verde y gigante, estaba solo en su casa. A pesar de su fuerza y coraje, sentía un vacío en su corazón 💔.\n", - "\n", - "En medio de la noche 🌙, Hulk escuchó un ruido proveniente del techo. Se levantó y vio a Santa Claus 🎅 atascado en la chimenea. \"¡Oh no! ¡Estoy atrapado!\", gritó Santa.\n", - "\n", - "Hulk, con su fuerza sobrehumana, liberó a Santa de la chimenea. \"¡Gracias, Hulk!\", dijo Santa aliviado. Pero había un problema: el trineo 🛷 de Santa estaba roto.\n", - "\n", - "Hulk, decidido a salvar la Navidad, usó sus habilidades para reparar el trineo. Con un poco de esfuerzo y mucha cinta adhesiva, el trineo estaba listo para volar nuevamente.\n", - "\n", - "Santa le agradeció a Hulk y le ofreció un regalo 🎁: \"Hulk, has salvado la Navidad. ¿Qué te gustaría como regalo?\" Hulk pensó por un momento y luego respondió: \"Quiero amigos con quienes compartir estas fiestas\".\n", - "\n", - "Santa sonrió y asintió. Esa noche, Hulk no estuvo solo. Los Vengadores se reunieron en su casa para celebrar la Navidad juntos. Fue una noche llena de risas 😂, regalos 🎁 y buenos momentos.\n", - "\n", - "Desde\r\n" - ] - } - ], + "outputs": [], "source": [ "var result = await kernel.RunAsync(\"Cuentame una historia sobre las navidades\", writerPluginFunctions[\"StoryGen\"]);\n", "Console.WriteLine(result);" @@ -772,7 +720,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -784,27 +732,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "¡Hola! 🐾\n", - "\n", - "Soy Catwoman, tu heroína de confianza. Quiero informarte que estaré fuera de la ciudad desde el 24 de diciembre hasta el 1 de enero, disfrutando de unas merecidas vacaciones navideñas. 🎄🎅\n", - "\n", - "Durante mi ausencia, no podré utilizar mis habilidades de agilidad felina, ni mi astucia para resolver los problemas que puedan surgir. Pero no te preocupes, no te dejaré desprotegido. 🦸‍♀️\n", - "\n", - "En mi lugar, Batman estará vigilando la ciudad. Con su fuerza, inteligencia y tecnología avanzada, estoy segura de que podrá manejar cualquier situación que se presente. 🦇💪\n", - "\n", - "Si necesitas ayuda, no dudes en contactar a Batman. Él estará más que dispuesto a ayudarte en mi ausencia. \n", - "\n", - "Gracias por tu comprensión. Espero que tengas unas felices fiestas y un próspero año nuevo. Nos vemos en enero! 🎉🎊\n", - "\n", - "Adiós y cu\r\n" - ] - } - ], + "outputs": [], "source": [ "var result = await kernel.RunAsync(\"Crea un out of office para los días de Navidades\", writerPluginFunctions[\"OOF\"]);\n", "Console.WriteLine(result.GetValue());" @@ -851,7 +779,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -877,7 +805,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -907,7 +835,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -919,15 +847,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Selina Kyle\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -958,7 +878,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1026,7 +946,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1038,29 +958,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Plan result:\n", - "\n", - "¡Hola! 🦇\n", - "\n", - "Soy Batman, tu héroe de confianza. Actualmente estoy fuera de la oficina, mejorando mis habilidades en un curso de música para perfeccionar mi \"Bat-acorde\". 🎵🎶\n", - "\n", - "Durante mi ausencia, no te preocupes, la ciudad de Gotham no quedará desprotegida. Mi buen amigo Superman estará vigilando y manteniendo la paz en mi lugar. 🦸‍♂️💪\n", - "\n", - "Si tienes alguna emergencia, no dudes en contactar a Superman. Él tiene la velocidad, la fuerza y la visión de rayos X para manejar cualquier situación que pueda surgir. 🚀🌍\n", - "\n", - "Volveré pronto, más fuerte y más afinado que nunca. Hasta entonces, mantén la calma y confía en Superman. \n", - "\n", - "Adiós y mantente seguro. 🌃🌙\n", - "\n", - "Batman.\n" - ] - } - ], + "outputs": [], "source": [ "var result = await kernel.RunAsync(plan);\n", "\n", @@ -1079,7 +977,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1091,132 +989,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Plan:\n", - "\n", - "{\n", - " \"state\": [],\n", - " \"steps\": [\n", - " {\n", - " \"state\": [],\n", - " \"steps\": [],\n", - " \"parameters\": [\n", - " {\n", - " \"Key\": \"input\",\n", - " \"Value\": \"Batman\"\n", - " }\n", - " ],\n", - " \"outputs\": [\n", - " \"ALTER_EGO\"\n", - " ],\n", - " \"next_step_index\": 0,\n", - " \"name\": \"GetAlterEgo\",\n", - " \"plugin_name\": \"InfoPlugin\",\n", - " \"description\": \"Get the alter ego of a superhero\",\n", - " \"model_settings\": [],\n", - " \"RequestSettings\": null\n", - " },\n", - " {\n", - " \"state\": [],\n", - " \"steps\": [],\n", - " \"parameters\": [\n", - " {\n", - " \"Key\": \"input\",\n", - " \"Value\": \"Estoy fuera luchando contra el crimen\"\n", - " },\n", - " {\n", - " \"Key\": \"hero\",\n", - " \"Value\": \"Batman\"\n", - " }\n", - " ],\n", - " \"outputs\": [\n", - " \"OOF_MESSAGE\"\n", - " ],\n", - " \"next_step_index\": 0,\n", - " \"name\": \"OOF\",\n", - " \"plugin_name\": \"WriterPlugin\",\n", - " \"description\": \"Generate a out of office message for a given hero subject\",\n", - " \"model_settings\": [\n", - " {\n", - " \"service_id\": null,\n", - " \"model_id\": null,\n", - " \"max_tokens\": 250,\n", - " \"temperature\": 0.3,\n", - " \"top_p\": 0.0,\n", - " \"presence_penalty\": 0.0,\n", - " \"frequency_penalty\": 0.0\n", - " }\n", - " ],\n", - " \"RequestSettings\": {\n", - " \"service_id\": null,\n", - " \"model_id\": null,\n", - " \"max_tokens\": 250,\n", - " \"temperature\": 0.3,\n", - " \"top_p\": 0.0,\n", - " \"presence_penalty\": 0.0,\n", - " \"frequency_penalty\": 0.0\n", - " }\n", - " },\n", - " {\n", - " \"state\": [],\n", - " \"steps\": [],\n", - " \"parameters\": [\n", - " {\n", - " \"Key\": \"input\",\n", - " \"Value\": \"$OOF_MESSAGE. Firma: $ALTER_EGO\"\n", - " },\n", - " {\n", - " \"Key\": \"hero\",\n", - " \"Value\": \"Batman\"\n", - " }\n", - " ],\n", - " \"outputs\": [\n", - " \"RESULT__FINAL_MESSAGE\"\n", - " ],\n", - " \"next_step_index\": 0,\n", - " \"name\": \"OOF\",\n", - " \"plugin_name\": \"WriterPlugin\",\n", - " \"description\": \"Generate a out of office message for a given hero subject\",\n", - " \"model_settings\": [\n", - " {\n", - " \"service_id\": null,\n", - " \"model_id\": null,\n", - " \"max_tokens\": 250,\n", - " \"temperature\": 0.3,\n", - " \"top_p\": 0.0,\n", - " \"presence_penalty\": 0.0,\n", - " \"frequency_penalty\": 0.0\n", - " }\n", - " ],\n", - " \"RequestSettings\": {\n", - " \"service_id\": null,\n", - " \"model_id\": null,\n", - " \"max_tokens\": 250,\n", - " \"temperature\": 0.3,\n", - " \"top_p\": 0.0,\n", - " \"presence_penalty\": 0.0,\n", - " \"frequency_penalty\": 0.0\n", - " }\n", - " }\n", - " ],\n", - " \"parameters\": [],\n", - " \"outputs\": [\n", - " \"RESULT__FINAL_MESSAGE\"\n", - " ],\n", - " \"next_step_index\": 0,\n", - " \"name\": \"plandae5d6d9b0974e118cdbfad1f511b097\",\n", - " \"plugin_name\": \"Plan\",\n", - " \"description\": \"Me gustar\\u00EDa que avveriguaras la identidad de Batman, y que hicieras un out of office para Batman firmando con la identidad del mismo.\",\n", - " \"model_settings\": [],\n", - " \"RequestSettings\": null\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "using System.Text.Json;\n", "\n", @@ -1236,7 +1009,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1248,29 +1021,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Plan result:\n", - "\n", - "Estimado remitente,\n", - "\n", - "🦇🌃 Actualmente, me encuentro fuera de la oficina, combatiendo el crimen en las oscuras calles de Gotham. Como Batman, mi deber es proteger la ciudad y garantizar la seguridad de sus ciudadanos, lo que a veces requiere de mi atención total y absoluta.\n", - "\n", - "Durante mi ausencia, no te preocupes, no estás desprotegido. 🦸‍♂️💫 Superman estará disponible para asistirte en cualquier emergencia que pueda surgir. Con su velocidad, fuerza y capacidad de volar, estoy seguro de que podrá manejar cualquier situación que se presente.\n", - "\n", - "Agradezco tu comprensión y paciencia durante este tiempo. Recuerda, cada uno de nosotros tiene el poder de hacer una diferencia, por pequeña que sea. 🌟💪\n", - "\n", - "Regresaré tan pronto como Gotham esté segura nuevamente. Hasta entonces, mantén la calma y confía en que el bien siempre prevalecerá.\n", - "\n", - "Adiós y cuídate,\n", - "\n", - "Batman 🦇🌙. Firma: Terry\n" - ] - } - ], + "outputs": [], "source": [ "var result_complex = await kernel.RunAsync(plan_complex);\n", "\n", @@ -1303,7 +1054,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1315,17 +1066,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.KernelMemory.Core, 0.11.231120.6-preview
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.KernelMemory.Core, 0.11.231120.6-preview\"\n", "\n", @@ -1341,7 +1082,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1353,16 +1094,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "Command cancelled.", - "output_type": "error", - "traceback": [ - "Command cancelled." - ] - } - ], + "outputs": [], "source": [ "var openApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\");\n", "\n", @@ -1379,7 +1111,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1405,7 +1137,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1417,21 +1149,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Answer: Mi héroe favorito es Batman.\n", - " - content.txt - gis01/62eb12bbb53c4a31924fbe94b9a7b4c2 [Thursday, November 30, 2023]\n", - " - content.txt - bru01/881e2c778cca47a9975fa2caf0aeaf4b [Thursday, November 30, 2023]\n", - " - content.txt - bru02/2b2d1c65585443b49bbb95236323f5b6 [Thursday, November 30, 2023]\n", - " - content.txt - gis02/bdca3bc681c44aa3a339d90be33d2db4 [Thursday, November 30, 2023]\n", - "{\"answer\":\"Mi h\\u00E9roe favorito es Batman.\",\"references\":[\"content.txt\",\"content.txt\",\"content.txt\",\"content.txt\"]}\n" - ] - } - ], + "outputs": [], "source": [ "var planner = new SequentialPlanner(kernel);\n", "\n", @@ -1444,7 +1162,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1456,58 +1174,11 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "Microsoft.SemanticKernel.Diagnostics.SKException: Not possible to create plan for goal with available functions.\nGoal:¿Cuál fue la última película que vio Bruno?\nFunctions:\nFunPlugin.Joke:\n description: Generate a funny joke about heroes\n inputs:\n - input: Joke subject\n - hero: Give the name of the hero you want to joke about\n\nInfoPlugin.GetAlterEgo:\n description: Get the alter ego of a superhero\n inputs:\n - input: \n\nMemoriesPlugin.AboutMe:\n description: Responde preguntas sobre Bruno\n inputs:\n - ask: \n\nMemoriesPlugin.AboutTheDocuments:\n description: Sobre el volumen\n inputs:\n - ask: \n\nWriterPlugin.OOF:\n description: Generate a out of office message for a given hero subject\n inputs:\n - input: The reason for being out of office\n - hero: hero name (default value: Catwoman)\n\nWriterPlugin.StoryGen:\n description: Generate a short story about the hero of your choice.\n inputs:\n - input: story subject\n - hero: hero name (default value: Hulk)\r\n at Microsoft.SemanticKernel.Planners.SequentialPlanner.CreatePlanAsync(String goal, CancellationToken cancellationToken)\r\n at Submission#40.<>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)", - "output_type": "error", - "traceback": [ - "Microsoft.SemanticKernel.Diagnostics.SKException: Not possible to create plan for goal with available functions.\n", - "Goal:¿Cuál fue la última película que vio Bruno?\n", - "Functions:\n", - "FunPlugin.Joke:\n", - " description: Generate a funny joke about heroes\n", - " inputs:\n", - " - input: Joke subject\n", - " - hero: Give the name of the hero you want to joke about\n", - "\n", - "InfoPlugin.GetAlterEgo:\n", - " description: Get the alter ego of a superhero\n", - " inputs:\n", - " - input: \n", - "\n", - "MemoriesPlugin.AboutMe:\n", - " description: Responde preguntas sobre Bruno\n", - " inputs:\n", - " - ask: \n", - "\n", - "MemoriesPlugin.AboutTheDocuments:\n", - " description: Sobre el volumen\n", - " inputs:\n", - " - ask: \n", - "\n", - "WriterPlugin.OOF:\n", - " description: Generate a out of office message for a given hero subject\n", - " inputs:\n", - " - input: The reason for being out of office\n", - " - hero: hero name (default value: Catwoman)\n", - "\n", - "WriterPlugin.StoryGen:\n", - " description: Generate a short story about the hero of your choice.\n", - " inputs:\n", - " - input: story subject\n", - " - hero: hero name (default value: Hulk)\r\n", - " at Microsoft.SemanticKernel.Planners.SequentialPlanner.CreatePlanAsync(String goal, CancellationToken cancellationToken)\r\n", - " at Submission#40.<>d__0.MoveNext()\r\n", - "--- End of stack trace from previous location ---\r\n", - " at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)" - ] - } - ], + "outputs": [], "source": [ "var planner = new SequentialPlanner(kernel);\n", "\n", - "var plan = await planner.CreatePlanAsync(\"¿Cuál fue la última película que vio Bruno?\");\n", + "var plan = await planner.CreatePlanAsync(\"¿Cuál fue la última película que vio Gisela?\");\n", "\n", "var result = await kernel.RunAsync(plan);\n", "\n", @@ -1523,7 +1194,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1535,18 +1206,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Answer: Este volumen de Batman incluye la historia definitiva del Caballero Oscuro en el cómic, el cine y más allá. Detalla toda la historia de Batman y las muchas formas que ha asumido a lo largo de los años, en cómics, televisión, animación, películas, videojuegos y más. Además, incluye comentarios exclusivos de personas creativas que han sido fundamentales para la creación del legado de Batman. También cuenta con documentos extraíbles que ayudan a acentuar la experiencia de lectura.\n", - " - Norma editorial - Septiembre 2020.pdf - doc001/43b043c48789457abbce9733779e9024 [Thursday, November 30, 2023]\n", - "{\"answer\":\"Este volumen de Batman incluye la historia definitiva del Caballero Oscuro en el c\\u00F3mic, el cine y m\\u00E1s all\\u00E1. Detalla toda la historia de Batman y las muchas formas que ha asumido a lo largo de los a\\u00F1os, en c\\u00F3mics, televisi\\u00F3n, animaci\\u00F3n, pel\\u00EDculas, videojuegos y m\\u00E1s. Adem\\u00E1s, incluye comentarios exclusivos de personas creativas que han sido fundamentales para la creaci\\u00F3n del legado de Batman. Tambi\\u00E9n cuenta con documentos extra\\u00EDbles que ayudan a acentuar la experiencia de lectura.\",\"references\":[\"Norma editorial - Septiembre 2020.pdf\"]}\n" - ] - } - ], + "outputs": [], "source": [ "var planner = new SequentialPlanner(kernel);\n", "\n", From c1b21947a87d0a8fb17a9a2f8a7d9e5b2dcf98c9 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Wed, 28 Feb 2024 19:43:56 -0500 Subject: [PATCH 03/25] include notebook in Eng and Spa --- notebook-en.ipynb | 1245 +++++++++++++++++++++++++++ notebook.ipynb => notebook-es.ipynb | 15 +- 2 files changed, 1251 insertions(+), 9 deletions(-) create mode 100644 notebook-en.ipynb rename notebook.ipynb => notebook-es.ipynb (98%) diff --git a/notebook-en.ipynb b/notebook-en.ipynb new file mode 100644 index 0000000..c300241 --- /dev/null +++ b/notebook-en.ipynb @@ -0,0 +1,1245 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 🦸🏻 Understanding Semantic Kernel with Heroes 🦸🏼‍♀️\n", + "\n", + "Semantic Kernel has been created to allow developers to seamlessly integrate Artificial Intelligence into their applications. To achieve this, it provides a set of features that will enable you to add models, prompts, native functions, and memories without requiring deep knowledge of AI 🥲. That's why it's said that Semantic Kernel simulates the brain 🧠 of your application.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating an Azure Open AI 🤖 Service and Deployments\n", + "\n", + "Before diving into Semantic Kernel 🛝, you'll need to have one of the supported services set up. Currently, you can choose from the following options: [Azure Open AI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), [Open AI](https://openai.com/), or [Hugging Face](https://huggingface.co/)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, I am going to use Azure Open AI.\n", + "\n", + "Therefore, through Azure CLI, I need to log in:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "tags": [], + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az login" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you need it, because you have many tenants and subscriptions under your account, you can select the one that interests you (or has access to Azure Open AI 😊) through the following command:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az account set -n \"Visual Studio Enterprise Subscription\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, to be able to create what you need for this notebook, set the following variables with your preferred values:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "$RESOURCE_GROUP=\"understanding-semantic-kernel\"\n", + "$LOCATION=\"canadaeast\"\n", + "$AZURE_OPEN_AI=\"ai-for-heroes\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With them, you can now create the resource group:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az group create `\n", + "--name $RESOURCE_GROUP `\n", + "--location $LOCATION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An Azure Open AI resource:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az cognitiveservices account create `\n", + "--name $AZURE_OPEN_AI `\n", + "--custom-domain $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--kind OpenAI `\n", + "--sku S0 `\n", + "--location $LOCATION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And finally, you need a deployment of any of the models you have available. In this example, I am going to use gpt-4:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az cognitiveservices account deployment create `\n", + "--name $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--deployment-name \"gpt-4\" `\n", + "--model-name \"gpt-4\" `\n", + "--model-version \"0613\" `\n", + "--model-format OpenAI `\n", + "--sku-capacity \"10\" `\n", + "--sku-name \"Standard\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The **sku-capacity** parameter allows us to specify how many tokens per minute we can send to this model. To see how your quota usage is, you can use this other command:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az cognitiveservices usage list `\n", + "-l $LOCATION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load enviroment variables with your Azure Open AI endpoint and key" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "$env:AZURE_OPEN_AI_KEY =$(az cognitiveservices account keys list `\n", + "--name $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--query \"key1\" `\n", + "--output tsv)\n", + "\n", + "$env:AZURE_OPEN_AI_ENDPOINT =$(az cognitiveservices account show `\n", + "--name $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--query \"properties.endpoint\" `\n", + "--output tsv)\n", + "\n", + "#dir env:AZURE_OPEN_AI_KEY\n", + "#dir env:AZURE_OPEN_AI_ENDPOINT" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## How to get started with Semantic Kernel\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first thing you need to be able to run Semantic Kernel in this notebook is to install the **Microsoft.SemanticKernel** library, which is currently in version **1.5.0** (I promise to keep updating 🤓). \n", + "\n", + "You can find more information about this library and its updates on the official NuGet page [here](https://www.nuget.org/packages/Microsoft.SemanticKernel).\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With it, you can now instantiate the brain of your application through **KernelBuilder**. It has a lot of connectors to the models and other things, but for now, let's start with the basics:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using Microsoft.SemanticKernel;\n", + "using Microsoft.SemanticKernel.Orchestration;\n", + "using System.IO;\n", + "\n", + "//Create Kernel builder\n", + "var builder = new KernelBuilder();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Depending on the type of task you want to do, you can use different methods with the prefix **With**. For now, we are going to use some of the models of type **completion** or completion.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "builder\n", + ".WithAzureOpenAIChatCompletionService(\"gpt-4\", Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_ENDPOINT\"), Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_KEY\"));\n", + "//.WithOpenAIChatCompletionService(\"gpt-4\",(await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\")).GetClearTextPassword());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the configuration done, all that remains is to generate the kernel with everything set:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var kernel = builder.Build();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The plugins\n", + "\n", + "Plugins are the core of Semantic Kernel. With them, you encapsulate capabilities so that they can be reusable, maintainable, and plannable (you will understand it later 🙃). There are two types: those that consist of prompt templates called **Semantic Functions** and native functions of the chosen programming language called **Native Functions**.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Semantic Functions\n", + "\n", + "When you talk to artificial intelligence models, you must do so with what is known as a *prompt*. This can range from a simple phrase to something more elaborate, allowing the model to understand not only what we want but also how we want it. If you take a look at the official documentation, it defines this type of function as the mouth 👄 and ears 👂🏻 of your brain 🧠. 🤖🌐\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As part of this repo, you have a folder called **SemanticFunctions** that has different functions of this type:\n", + "\n", + "- **FunPlugin**: This allows us to ask the model to make jokes about heroes under certain conditions, through the **Joke** function.\n", + "- **WritePlugin**: To show you that within a plugin you can have different functions, in this directory we have two related to the art of writing: the first one, **OOF**, allows us to generate the \"Out of Office\" 🏢📧 message for superheroes and the second **StoryGen** will help us create stories, also about superheroes 🦸🏻‍♂️🦸🏻‍♀️.\n", + "\n", + "For our kernel to know that these plugins are available, you first need to get the path of the directory:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And then start loading the plugins you want:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Load the FunPlugin from the Plugins Directory\n", + "var funPluginFunctions = kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"FunPlugin\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To be able to invoke a function of this type, you can do it in the following way:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var result = await kernel.RunAsync(\"Tell me a joke\", funPluginFunctions[\"Joke\"]);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, just by using **kernel.RunAsync** and passing my request as parameters and which function, in this case **Joke**, within the plugin, in this case **FunPlugin**, I want to use.\n", + "\n", + "Each of these functions consists of two files:\n", + "\n", + "- **skprompt.txt** is the file where the prompt to send to the model is defined in a template format, so that it can receive parameters and make them more reusable.\n", + "\n", + "```\n", + "WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE SUBJECT BELOW\n", + "\n", + "JOKE MUST BE:\n", + "- IN ENGLISH\n", + "\n", + "BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n", + "\n", + "Incorporate the hero if provided: {{$hero}}\n", + "+++++\n", + "\n", + "{{$input}}\n", + "+++++\n", + "```\n", + "- **config.json**, which allows us to indicate the maximum number of tokens allowed for this call (**max_tokens**), the temperature to control the randomness of the responses (**temperature**), which means that closer to 1 they will be more random and closer to zero more determined and focused on the most likely response, **top_p** is used to control the diversity of the responses, where a value of 0.0 means that only the most likely responses will be considered and 1 where all possible responses will be considered and **presence_penalty** and **frequency_penalty** to adjust the penalty for the presence and frequency of the tokens in the generated responses. On the other hand, if the skprompt.txt file receives parameters, they must also be defined in this file in the **parameters** array of the **input** object.\n", + "\n", + "```javascript\n", + "{\n", + " \"schema\": 1,\n", + " \"description\": \"Generate a funny joke about heroes\",\n", + " \"models\": [\n", + " {\n", + " \"max_tokens\": 150,\n", + " \"temperature\": 0.9,\n", + " \"top_p\": 0.5,\n", + " \"presence_penalty\": 0.2,\n", + " \"frequency_penalty\": 0.3\n", + " }\n", + " ],\n", + " \"input\": {\n", + " \"parameters\": [\n", + " {\n", + " \"name\": \"input\",\n", + " \"description\": \"Joke subject\",\n", + " \"defaultValue\": \"\"\n", + " },\n", + " {\n", + " \"name\": \"hero\",\n", + " \"description\": \"Give a hint about the hero you want to joke about\",\n", + " \"defaultValue\": \"\"\n", + " }\n", + " ]\n", + " }\n", + "}\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To see the result generated from calling this Joke function, you can retrieve it in the following way:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, in this execution we have only passed the input parameter, but not the hero about whom we wanted to generate this joke. To be able to send more than one parameter you need to create an object of the **ContextVariables** type:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var variables = new ContextVariables{\n", + " [\"input\"] = \"Cuentame un chiste sobre Navidad\",\n", + " [\"hero\"] = \"Ironman\"\n", + "};" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To be able to use these two values as part of the call, simply put it as the first argument.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var result = await kernel.RunAsync(variables, funPluginFunctions[\"Joke\"]);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now check if the joke is about the hero specified as a parameter.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the same way, we can use the functions included in **WriterPlugin**:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Load the WriterPlugin from the Plugins Directory\n", + "var writerPluginFunctions = kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"WriterPlugin\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One that generates stories:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var result = await kernel.RunAsync(\"Cuentame una historia sobre las navidades\", writerPluginFunctions[\"StoryGen\"]);\n", + "Console.WriteLine(result);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or even to create messages for when the heroes 🦸🏻‍♀️ are on vacation ✈️🚢🌴:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var result = await kernel.RunAsync(\"Crea un out of office para los días de Navidades\", writerPluginFunctions[\"OOF\"]);\n", + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Native Functions\n", + "\n", + "While semantic functions allow us to define and reuse prompts, **with native functions you can make the semantic kernel call functions written in C# or Python**, for tasks that go beyond a call through a prompt.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why do I need native functions in these types of applications?\n", + "\n", + "Large language models (LLMs) are excellent for generating text, but there are several tasks they cannot perform on their own. These include, among others:\n", + "\n", + "- Retrieving data from external data sources\n", + "- Knowing what time it is\n", + "- Performing complex mathematical operations\n", + "- Completing tasks in the real world\n", + "- Memorizing and remembering information\n", + "\n", + "For these scenarios, and many others, native functions are very useful 👍🏻\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this example, I'm going to use an API called **SuperHero API**, which requires an API key. You can get it from their website: [https://superheroapi.com/](https://superheroapi.com/)\n", + "\n", + "Once you have it, pass it to the prompt that appears with the following line:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var superHeroApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, to load a native function, we must do it in the following way:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#load \"NativeFunctions/GetHeroInfo.cs\"\n", + "\n", + "var infoPlugin = kernel.ImportFunctions(new Info(superHeroApiKey.GetClearTextPassword()), \"InfoPlugin\");\n", + "\n", + "var result = await kernel.RunAsync(\"catwoman\", infoPlugin[\"GetAlterEgo\"]);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this repo, there is another directory called **NativeFunctions** where you can find a class called **GetHeroInfo.cs**. In it, there is a function decorated with the **SKFunction** attribute, which allows us to indicate to the Semantic Kernel that it is a native function and, through the **Description** property, also give it information about what the purpose of this function is. In this case, what this method allows us to do is retrieve the alter ego of the superhero that we pass as a parameter, in this example that of Catwoman. If we take a look at the result, you will see that it is as expected:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Planner\n", + "\n", + "So far, all the plugins you have seen have been executed intentionally. That is, no one has chosen them for you and you can run them based on your needs. However, this is the most *static* way to interact with Semantic Kernel. There is another option called **Planner** that will leave you astounded 😮\n", + "\n", + "Planner is a function that takes a user's request and returns a plan on how to carry out the request. To do this, it uses AI to combine the plugins registered in the core and recombine them into a series of steps that complete a goal.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To see it in action, we are going to use the plugins that you already know.\n", + "\n", + "The first thing you need is to instantiate a planner:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using Microsoft.SemanticKernel.Planners;\n", + "\n", + "// Create planner\n", + "var planner = new SequentialPlanner(kernel);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are different types as you can see [here](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). In this example, we are going to use the one that executes tasks sequentially.\n", + "\n", + "Since you already have all the plugins loaded in your kernel instance, we can ask it something like this:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using System.Text.Json;\n", + "\n", + "var ask = \"Me gustaría que me contaras un chiste sobre Batman, y con el chiste que hicieras un out of office con el chiste.\";\n", + "var plan = await planner.CreatePlanAsync(ask);\n", + "\n", + "Console.WriteLine(\"Plan:\\n\");\n", + "Console.WriteLine(JsonSerializer.Serialize(plan, new JsonSerializerOptions { WriteIndented = true }));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, the planner knows about my plugins thanks to the description that I included as part of their implementation.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var result = await kernel.RunAsync(plan);\n", + "\n", + "Console.WriteLine(\"Plan result:\\n\");\n", + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## LABS\n", + "\n", + "The kernel already has the plugins loaded, and the function, let's see if it can solve a more complex example:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using System.Text.Json;\n", + "\n", + "var ask_complex = \"I would like you to find out Batman's alter ego, and create an out of office message for Batman, signing it with his alter ego.\";\n", + "\n", + "var plan_complex = await planner.CreatePlanAsync(ask_complex);\n", + "\n", + "Console.WriteLine(\"Plan:\\n\");\n", + "Console.WriteLine(JsonSerializer.Serialize(plan_complex, new JsonSerializerOptions { WriteIndented = true }));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's execute the plan and see its output:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var result_complex = await kernel.RunAsync(plan_complex);\n", + "\n", + "Console.WriteLine(\"Plan result:\\n\");\n", + "Console.WriteLine(result_complex.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Kernel Memory\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this example, I'm going to use **Open AI** instead of Azure Open AI, so you need to save [an API Key](https://platform.openai.com/account/api-keys) from this in the following variable:\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To be able to use Kernel Memory, you need to add its nuget library, in addition to importing the class that I have generated in the **KernelMemory** directory.\n", + "\n", + "To learn more about the Kernel Memory library, you can visit the [NuGet package page](https://www.nuget.org/packages/Microsoft.KernelMemory.Core).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget: Microsoft.KernelMemory.Core, 0.11.231120.6-preview\"\n", + "\n", + "#!import \"KernelMemory/Memories.cs\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first thing I'm going to do is import a few *memories* (texts) and *documents* into Kernel Memory.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var openApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\");\n", + "\n", + "MemoryKernel.Init(openApiKey.GetClearTextPassword());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see in the output, it already takes care of generating the embeddings of the sentences/documents that we pass to it so that the GPT-4 model can generate the answer.\n", + "Now that we have some content to ask about, let's load this class as another plugin.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var memoriesPlugin = kernel.ImportFunctions(new MemoryKernel(), \"MemoriesPlugin\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And now let's ask about the content:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var planner = new SequentialPlanner(kernel);\n", + "\n", + "var plan = await planner.CreatePlanAsync(\"Who is Bruno's favorite hero?\");\n", + "\n", + "var result = await kernel.RunAsync(plan);\n", + "\n", + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var planner = new SequentialPlanner(kernel);\n", + "\n", + "var plan = await planner.CreatePlanAsync(\"What was the last movie Gisela saw?\");\n", + "\n", + "var result = await kernel.RunAsync(plan);\n", + "\n", + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also ask about the PDF that I included:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var planner = new SequentialPlanner(kernel);\n", + "\n", + "var plan = await planner.CreatePlanAsync(\"¿Qué incluye este volumen de batman?\");\n", + "\n", + "var result = await kernel.RunAsync(plan);\n", + "\n", + "Console.WriteLine(result.GetValue());" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "python" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebook.ipynb b/notebook-es.ipynb similarity index 98% rename from notebook.ipynb rename to notebook-es.ipynb index 2b33ee9..5f4eae6 100644 --- a/notebook.ipynb +++ b/notebook-es.ipynb @@ -276,7 +276,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Lo primero que necesitas para poder ejecutar Semantic Kernel en este notebook es instalar la librería **Microsoft.SemanticKernel** que a día de hoy está en su versión **1.0.0-beta8** (prometo ir actualizando 🤓)" + "Lo primero que necesitas para poder ejecutar Semantic Kernel en este cuaderno es instalar la biblioteca **Microsoft.SemanticKernel**, que actualmente está en la versión **1.5.0** (prometo seguir actualizando 🤓).\n", + "\n", + "Puedes encontrar más información sobre esta biblioteca y sus actualizaciones en la página oficial de NuGet [aquí](https://www.nuget.org/packages/Microsoft.SemanticKernel).\n" ] }, { @@ -295,7 +297,7 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 1.0.0-beta8\"" + "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" ] }, { @@ -902,13 +904,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Hay de diferentes tipos como puedes ver [aquí](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). En este ejemplo vamos a utilizar el que ejecuta las tareas de forma secuencial." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "Hay de diferentes tipos como puedes ver [aquí](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). En este ejemplo vamos a utilizar el que ejecuta las tareas de forma secuencial.\n", + "\n", "Como ya tienes todos los plugins cargados en tu instancia del kernel, podemos preguntarle algo como esto:" ] }, From 5301dc97811d9c00574ee8b9e1464727cdfdf24a Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Wed, 28 Feb 2024 20:16:42 -0500 Subject: [PATCH 04/25] Update language in skprompt.txt and add OpenAI chat completion service***. --- SemanticFunctions/FunPlugin/Joke/skprompt.txt | 2 +- notebook-en.ipynb | 106 +++++++++++++----- 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/SemanticFunctions/FunPlugin/Joke/skprompt.txt b/SemanticFunctions/FunPlugin/Joke/skprompt.txt index 9afadde..f872998 100644 --- a/SemanticFunctions/FunPlugin/Joke/skprompt.txt +++ b/SemanticFunctions/FunPlugin/Joke/skprompt.txt @@ -1,7 +1,7 @@ WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE SUBJECT BELOW JOKE MUST BE: -- IN SPANISH +- IN ENGLISH BE CREATIVE AND FUNNY. I WANT TO LAUGH. diff --git a/notebook-en.ipynb b/notebook-en.ipynb index c300241..c7ad2ed 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -284,7 +284,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -296,7 +296,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 1.5.0
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" ] @@ -310,7 +320,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -325,11 +335,9 @@ "outputs": [], "source": [ "using Microsoft.SemanticKernel;\n", - "using Microsoft.SemanticKernel.Orchestration;\n", - "using System.IO;\n", "\n", - "//Create Kernel builder\n", - "var builder = new KernelBuilder();" + "// Create a chat completion service\n", + "var builder = Kernel.CreateBuilder();" ] }, { @@ -341,7 +349,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -355,9 +363,13 @@ }, "outputs": [], "source": [ - "builder\n", - ".WithAzureOpenAIChatCompletionService(\"gpt-4\", Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_ENDPOINT\"), Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_KEY\"));\n", - "//.WithOpenAIChatCompletionService(\"gpt-4\",(await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\")).GetClearTextPassword());" + "// OpenAI keys\n", + "var modelId = \"gpt-4\";\n", + "var apiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\")).GetClearTextPassword();\n", + "\n", + "// Create a chat completion service\n", + "var builder = Kernel.CreateBuilder();\n", + "builder.AddOpenAIChatCompletion(modelId, apiKey);" ] }, { @@ -369,7 +381,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -426,7 +438,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -440,7 +452,9 @@ }, "outputs": [], "source": [ - "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\");" + "using System.IO;\n", + "\n", + "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"FunPlugIn\");" ] }, { @@ -452,7 +466,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -467,7 +481,7 @@ "outputs": [], "source": [ "// Load the FunPlugin from the Plugins Directory\n", - "var funPluginFunctions = kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"FunPlugin\");" + "var funPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectory);" ] }, { @@ -479,7 +493,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -493,7 +507,8 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(\"Tell me a joke\", funPluginFunctions[\"Joke\"]);" + "var joke = new KernelArguments() { [\"input\"] = \"tell me a joke\" };\n", + "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], joke);" ] }, { @@ -562,7 +577,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -574,7 +589,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Why don't heroes play hide and seek?\n", + "\n", + "Because good luck hiding when the whole city is shouting, \"Help, Superhero, help!\"\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -588,7 +613,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -602,8 +627,8 @@ }, "outputs": [], "source": [ - "var variables = new ContextVariables{\n", - " [\"input\"] = \"Cuentame un chiste sobre Navidad\",\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Tell me a Christmas joke\",\n", " [\"hero\"] = \"Ironman\"\n", "};" ] @@ -617,7 +642,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -631,7 +656,7 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(variables, funPluginFunctions[\"Joke\"]);" + "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], variables);" ] }, { @@ -643,7 +668,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -655,7 +680,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Why did Iron Man go to the Christmas party without his suit?\n", + "\n", + "He heard it was \"casual\", but when he showed up, everyone else was “stark” naked! \"Oops, wrong Stark...\" he said, \"I thought when you said 'stark', you meant come as Tony!\"\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -669,7 +704,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -681,10 +716,21 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "ename": "Error", + "evalue": "(2,36): error CS1061: 'Kernel' does not contain a definition for 'ImportSemanticFunctionsFromDirectory' and no accessible extension method 'ImportSemanticFunctionsFromDirectory' accepting a first argument of type 'Kernel' could be found (are you missing a using directive or an assembly reference?)", + "output_type": "error", + "traceback": [ + "(2,36): error CS1061: 'Kernel' does not contain a definition for 'ImportSemanticFunctionsFromDirectory' and no accessible extension method 'ImportSemanticFunctionsFromDirectory' accepting a first argument of type 'Kernel' could be found (are you missing a using directive or an assembly reference?)" + ] + } + ], "source": [ "// Load the WriterPlugin from the Plugins Directory\n", - "var writerPluginFunctions = kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"WriterPlugin\");" + "var pluginsDirectoryWriter = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"WriterPlugin\");\n", + "\n", + "var writerPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectoryWriter);\n" ] }, { From f6f85c292a3a8804622fce66fee9bc504f349f89 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 09:55:54 -0500 Subject: [PATCH 05/25] Update language to English in skprompt.txt files Update Prompts demos --- .../WriterPlugin/OOF/skprompt.txt | 2 +- .../WriterPlugin/StoryGen/skprompt.txt | 2 +- notebook-en.ipynb | 96 +++++++++++-------- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/SemanticFunctions/WriterPlugin/OOF/skprompt.txt b/SemanticFunctions/WriterPlugin/OOF/skprompt.txt index 1e4bc3d..1adae21 100644 --- a/SemanticFunctions/WriterPlugin/OOF/skprompt.txt +++ b/SemanticFunctions/WriterPlugin/OOF/skprompt.txt @@ -1,7 +1,7 @@ WRITE AN OUT OF OFFICE FOR THE HERO BELOW THE STORY MUST BE: -- IN SPANISH +- IN ENGLISH - USE EMOJIS AS PART OF THE MESSAGE - TAKE INTO ACCOUNT THE HERO AND HIS/HER POWERS - YOU MUST OFFER HELP FROM ANOTHER SUPER HERO IN YOUR ABSENCE diff --git a/SemanticFunctions/WriterPlugin/StoryGen/skprompt.txt b/SemanticFunctions/WriterPlugin/StoryGen/skprompt.txt index 736e8b0..7d5a52f 100644 --- a/SemanticFunctions/WriterPlugin/StoryGen/skprompt.txt +++ b/SemanticFunctions/WriterPlugin/StoryGen/skprompt.txt @@ -1,7 +1,7 @@ WRITE A SHORT STORY ABOUT THE HERO BELOW THE STORY MUST BE: -- IN SPANISH +- IN ENGLISH - USE EMOJIS AS PART OF THE STORY - THE STORY MUST HAVE A BEGINNING, MIDDLE AND END diff --git a/notebook-en.ipynb b/notebook-en.ipynb index c7ad2ed..3ebff03 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -17,18 +17,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Creating an Azure Open AI 🤖 Service and Deployments\n", + "## (Optional) - Creating an Azure Open AI 🤖 Service and Deployments\n", + "\n", + "Before diving into Semantic Kernel 🛝, you'll need to have one of the supported services set up. Currently, you can choose from the following options: [Azure Open AI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), [Open AI](https://openai.com/), or [Hugging Face](https://huggingface.co/).\n", "\n", - "Before diving into Semantic Kernel 🛝, you'll need to have one of the supported services set up. Currently, you can choose from the following options: [Azure Open AI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), [Open AI](https://openai.com/), or [Hugging Face](https://huggingface.co/)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ "In this example, I am going to use Azure Open AI.\n", "\n", - "Therefore, through Azure CLI, I need to log in:\n" + "Therefore, through Azure CLI, I need to log in:" ] }, { @@ -284,7 +279,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -320,7 +315,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -349,7 +344,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -381,7 +376,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 10, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -438,7 +433,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 11, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -466,7 +461,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -493,7 +488,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 13, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -577,7 +572,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 14, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -594,9 +589,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why don't heroes play hide and seek?\n", + "Sure, here's a joke for you:\n", + "\n", + "Why don't superheroes like to play hide and seek with The Invisible Man?\n", "\n", - "Because good luck hiding when the whole city is shouting, \"Help, Superhero, help!\"\r\n" + "Because he always wins, even when they use their x-ray vision!\r\n" ] } ], @@ -613,7 +610,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 15, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -642,7 +639,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 16, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -668,7 +665,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 17, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -685,9 +682,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why did Iron Man go to the Christmas party without his suit?\n", + "Why did Ironman decorate the Christmas tree with tiny repulsor beams?\n", "\n", - "He heard it was \"casual\", but when he showed up, everyone else was “stark” naked! \"Oops, wrong Stark...\" he said, \"I thought when you said 'stark', you meant come as Tony!\"\r\n" + "Because he wanted to make sure his Christmas was lit... but also well-defended from Ultron!\r\n" ] } ], @@ -704,7 +701,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 18, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -716,16 +713,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(2,36): error CS1061: 'Kernel' does not contain a definition for 'ImportSemanticFunctionsFromDirectory' and no accessible extension method 'ImportSemanticFunctionsFromDirectory' accepting a first argument of type 'Kernel' could be found (are you missing a using directive or an assembly reference?)", - "output_type": "error", - "traceback": [ - "(2,36): error CS1061: 'Kernel' does not contain a definition for 'ImportSemanticFunctionsFromDirectory' and no accessible extension method 'ImportSemanticFunctionsFromDirectory' accepting a first argument of type 'Kernel' could be found (are you missing a using directive or an assembly reference?)" - ] - } - ], + "outputs": [], "source": [ "// Load the WriterPlugin from the Plugins Directory\n", "var pluginsDirectoryWriter = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"WriterPlugin\");\n", @@ -742,7 +730,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -754,9 +742,34 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Una vez, en una fría noche de Navidad 🎄❄️, nuestro héroe Ironman, también conocido como Tony Stark, volaba por los cielos 🌌 vigilando la tranquila ciudad de Nueva York. \n", + "\n", + "A mitad de noche 🌛, escuchó un leve sonido 🎵 que provenía del callejón. Descendió para investigar y encontró a un niño llorando 😢. El niño, asustado por el frío y la oscuridad, había perdido a su madre en la multitud de las fiestas navideñas.\n", + "\n", + "Ironman, con su corazón heroico, decidió ayudar. Levantó al niño en sus brazos y con su traje luminoso ✨ voló sobre la ciudad en busca de su madre. Desde el cielo 🌠, el niño se sintió maravillado por las luces brillantes de la ciudad y su miedo se convirtió en admiración 😮.\n", + "\n", + "Finalmente, encontraron a la madre del niño en un parque. Al ver a su hijo a salvo y sano, la madre lloró de felicidad 😭. Le agradeció a Ironman, quien le sonrió bajo su casco de hierro.\n", + "\n", + "Antes de irse, Ironman dejó un regalo 🎁 debajo del árbol de Navidad para el niño. Luego, se elevó en el cielo y la noche nevada se llenó de destellos rojos y dorados mientras volaba lejos.\n", + "\n", + "El niño y su madre regresaron a su casa, llenos de alegría y gratitud 😊. Abrieron el regalo y dentro encontraron un pequeño juguete de Ironman. Cada vez que el niño lo miraba, recordaba la mágica noche de Navidad que había pasado junto al verdadero Ironman.\n", + "\n", + "Esa noche, Ironman no solo salvó al niño, sino también la esencia de la Navidad: el amor, la bondad y la alegría de dar 🎁🎄❤️. Y ese fue verdaderamente un milagro navideño. Fin.\r\n" + ] + } + ], "source": [ - "var result = await kernel.RunAsync(\"Cuentame una historia sobre las navidades\", writerPluginFunctions[\"StoryGen\"]);\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Tell me a Christmas Story\",\n", + " [\"hero\"] = \"Ironman\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", "Console.WriteLine(result);" ] }, @@ -783,7 +796,12 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(\"Crea un out of office para los días de Navidades\", writerPluginFunctions[\"OOF\"]);\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Create an OOF for Christmas\",\n", + " [\"hero\"] = \"Hulk\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOF\"], variables);\n", "Console.WriteLine(result.GetValue());" ] }, From cc62daae034fac86c3f644cfede0284858a01160 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 09:59:02 -0500 Subject: [PATCH 06/25] add azure openai chat completion sample --- notebook-en.ipynb | 87 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 3ebff03..44ecbd4 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -331,7 +331,7 @@ "source": [ "using Microsoft.SemanticKernel;\n", "\n", - "// Create a chat completion service\n", + "// Create a Builder\n", "var builder = Kernel.CreateBuilder();" ] }, @@ -363,10 +363,34 @@ "var apiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\")).GetClearTextPassword();\n", "\n", "// Create a chat completion service\n", - "var builder = Kernel.CreateBuilder();\n", "builder.AddOpenAIChatCompletion(modelId, apiKey);" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Azure OpenAI keys\n", + "var deploymentName = \"gpt-4\";\n", + "var endpoint = Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_ENDPOINT\");\n", + "var apiKey = Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_KEY\");\n", + "\n", + "// Create a chat completion service\n", + "builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -782,7 +806,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -794,7 +818,62 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "ename": "Error", + "evalue": "Microsoft.SemanticKernel.KernelFunctionCanceledException: The invocation of function 'OOF' was canceled.\r\n ---> System.Threading.Tasks.TaskCanceledException: The operation was cancelled because it exceeded the configured timeout of 0:01:40. Network timeout can be adjusted in ClientOptions.Retry.NetworkTimeout.\r\n ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n ---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..\r\n ---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.\r\n --- End of inner exception stack trace ---\r\n at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)\r\n at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)\r\n at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)\r\n at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n at System.Net.Http.HttpConnection.g__ReadAheadWithZeroByteReadAsync|40_0()\r\n at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n --- End of inner exception stack trace ---\r\n at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)\r\n at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n at Azure.Core.Pipeline.HttpClientTransport.ProcessAsync(HttpMessage message, Boolean async)\r\n at Azure.Core.Pipeline.HttpPipelineTransportPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)\r\n at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n --- End of inner exception stack trace ---\r\n at Azure.Core.Pipeline.ResponseBodyPolicy.ThrowIfCancellationRequestedOrTimeout(CancellationToken originalToken, CancellationToken timeoutToken, Exception inner, TimeSpan timeout)\r\n at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)\r\n at Azure.AI.OpenAI.OpenAIClient.GetChatCompletionsAsync(ChatCompletionsOptions chatCompletionsOptions, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.RunRequestAsync[T](Func`1 request)\r\n at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetChatMessageContentsAsync(ChatHistory chat, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.ChatCompletion.ChatCompletionServiceExtensions.GetChatMessageContentAsync(IChatCompletionService chatCompletionService, String prompt, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.KernelFunctionFromPrompt.InvokeCoreAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at Microsoft.SemanticKernel.KernelFunction.HandleException(Exception ex, ILogger logger, Activity activity, KernelFunction kernelFunction, Kernel kernel, KernelArguments arguments, FunctionResult result, TagList& tags)\r\n at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n at Submission#22.<>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)", + "output_type": "error", + "traceback": [ + "Microsoft.SemanticKernel.KernelFunctionCanceledException: The invocation of function 'OOF' was canceled.\r\n", + " ---> System.Threading.Tasks.TaskCanceledException: The operation was cancelled because it exceeded the configured timeout of 0:01:40. Network timeout can be adjusted in ClientOptions.Retry.NetworkTimeout.\r\n", + " ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n", + " ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n", + " ---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..\r\n", + " ---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.\r\n", + " --- End of inner exception stack trace ---\r\n", + " at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)\r\n", + " at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n", + " at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)\r\n", + " at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n", + " at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)\r\n", + " at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n", + " at System.Net.Http.HttpConnection.g__ReadAheadWithZeroByteReadAsync|40_0()\r\n", + " at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", + " --- End of inner exception stack trace ---\r\n", + " at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", + " at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n", + " at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", + " at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", + " at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n", + " --- End of inner exception stack trace ---\r\n", + " at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)\r\n", + " at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n", + " at Azure.Core.Pipeline.HttpClientTransport.ProcessAsync(HttpMessage message, Boolean async)\r\n", + " at Azure.Core.Pipeline.HttpPipelineTransportPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)\r\n", + " at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", + " --- End of inner exception stack trace ---\r\n", + " at Azure.Core.Pipeline.ResponseBodyPolicy.ThrowIfCancellationRequestedOrTimeout(CancellationToken originalToken, CancellationToken timeoutToken, Exception inner, TimeSpan timeout)\r\n", + " at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", + " at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", + " at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", + " at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", + " at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", + " at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)\r\n", + " at Azure.AI.OpenAI.OpenAIClient.GetChatCompletionsAsync(ChatCompletionsOptions chatCompletionsOptions, CancellationToken cancellationToken)\r\n", + " at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.RunRequestAsync[T](Func`1 request)\r\n", + " at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetChatMessageContentsAsync(ChatHistory chat, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n", + " at Microsoft.SemanticKernel.ChatCompletion.ChatCompletionServiceExtensions.GetChatMessageContentAsync(IChatCompletionService chatCompletionService, String prompt, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n", + " at Microsoft.SemanticKernel.KernelFunctionFromPrompt.InvokeCoreAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n", + " at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n", + " --- End of inner exception stack trace ---\r\n", + " at Microsoft.SemanticKernel.KernelFunction.HandleException(Exception ex, ILogger logger, Activity activity, KernelFunction kernelFunction, Kernel kernel, KernelArguments arguments, FunctionResult result, TagList& tags)\r\n", + " at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n", + " at Submission#22.<>d__0.MoveNext()\r\n", + "--- End of stack trace from previous location ---\r\n", + " at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)" + ] + } + ], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Create an OOF for Christmas\",\n", From 447e6e75a481f63fba5dabdf9d5f724b2fd5fb4a Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 11:30:36 -0500 Subject: [PATCH 07/25] Sample console application to show how to use native functions with Semantic Kernel --- .../{GetHeroInfo.cs => HeroInfo.cs} | 68 +++++++++---------- notebook-en.ipynb | 56 +++++++++++++-- 2 files changed, 83 insertions(+), 41 deletions(-) rename NativeFunctions/{GetHeroInfo.cs => HeroInfo.cs} (76%) diff --git a/NativeFunctions/GetHeroInfo.cs b/NativeFunctions/HeroInfo.cs similarity index 76% rename from NativeFunctions/GetHeroInfo.cs rename to NativeFunctions/HeroInfo.cs index 7424e83..97d401b 100644 --- a/NativeFunctions/GetHeroInfo.cs +++ b/NativeFunctions/HeroInfo.cs @@ -1,34 +1,34 @@ -using System.ComponentModel; -using System.Globalization; -using Microsoft.SemanticKernel; -using System.Net.Http; -using Newtonsoft.Json.Linq; - -public class Info -{ - string apiKey; - public Info(string superHeroApiKey) - { - apiKey = superHeroApiKey; - } - - [SKFunction, Description("Get the alter ego of a superhero")] - public string GetAlterEgo(string input) - { - // Call the API - var httpClient = new HttpClient(); - var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; - - // Get the response - var responseContent = response.Content.ReadAsStringAsync().Result; - - // Parse the response - var json = JObject.Parse(responseContent); - - // Get the hero info - var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; - - // Return the hero info - return heroInfo; - } -} +using System.ComponentModel; +using System.Globalization; +using Microsoft.SemanticKernel; +using System.Net.Http; +using Newtonsoft.Json.Linq; + +public class HeroInfo +{ + static string apiKey; + public HeroInfo(string superHeroApiKey) + { + apiKey = superHeroApiKey; + } + + [KernelFunction, Description("Get the alter ego of a superhero")] + public static string GetAlterEgo(string input) + { + // Call the API + var httpClient = new HttpClient(); + var response = httpClient.GetAsync($"https://superheroapi.com/api/{apiKey}/search/{input}").Result; + + // Get the response + var responseContent = response.Content.ReadAsStringAsync().Result; + + // Parse the response + var json = JObject.Parse(responseContent); + + // Get the hero info + var heroInfo = $"{json["results"][0]["biography"]["full-name"]}"; + + // Return the hero info + return heroInfo; + } +} diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 44ecbd4..9114200 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -925,7 +925,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -939,14 +939,55 @@ }, "outputs": [], "source": [ - "var superHeroApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\");" + "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, to load a native function, we must add this before we build the Kernel.\n", + "\n", + "Let's create a new Super Hero Info class and add it as a Plugin." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "ename": "Error", + "evalue": "(3,29): error CS1503: Argument 1: cannot convert from 'Microsoft.DotNet.Interactive.PasswordString' to 'string'", + "output_type": "error", + "traceback": [ + "(3,29): error CS1503: Argument 1: cannot convert from 'Microsoft.DotNet.Interactive.PasswordString' to 'string'" + ] + } + ], + "source": [ + "#load \"NativeFunctions/HeroInfo.cs\"\n", + "\n", + "var heroInfo = new HeroInfo(superHeroApiKey);\n", + "builder.Plugins.AddFromObject(heroInfo, \"HeroInfo\");\n", + "Kernel kernel = builder.Build();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now, to load a native function, we must do it in the following way:\n" + "The builder now can interact with the local function. Let's make a call to get the alter ego of a super hero." ] }, { @@ -965,11 +1006,12 @@ }, "outputs": [], "source": [ - "#load \"NativeFunctions/GetHeroInfo.cs\"\n", - "\n", - "var infoPlugin = kernel.ImportFunctions(new Info(superHeroApiKey.GetClearTextPassword()), \"InfoPlugin\");\n", + "var kernelArgs = new KernelArguments()\n", + "{\n", + " [\"input\"] = \"Ironman\"\n", + "};\n", "\n", - "var result = await kernel.RunAsync(\"catwoman\", infoPlugin[\"GetAlterEgo\"]);" + "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);" ] }, { From 1a830867158b670956fbea13d39f780d51476481 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 11:53:28 -0500 Subject: [PATCH 08/25] update planner demos --- notebook-en.ipynb | 205 +++++++++++++++++++++++++++++++--------------- 1 file changed, 141 insertions(+), 64 deletions(-) diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 9114200..c1fb6ae 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -925,7 +925,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -953,7 +953,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -965,16 +965,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(3,29): error CS1503: Argument 1: cannot convert from 'Microsoft.DotNet.Interactive.PasswordString' to 'string'", - "output_type": "error", - "traceback": [ - "(3,29): error CS1503: Argument 1: cannot convert from 'Microsoft.DotNet.Interactive.PasswordString' to 'string'" - ] - } - ], + "outputs": [], "source": [ "#load \"NativeFunctions/HeroInfo.cs\"\n", "\n", @@ -992,7 +983,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1004,40 +995,30 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tony Stark\r\n" + ] + } + ], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", " [\"input\"] = \"Ironman\"\n", "};\n", "\n", - "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);" + "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", + "Console.WriteLine(result);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In this repo, there is another directory called **NativeFunctions** where you can find a class called **GetHeroInfo.cs**. In it, there is a function decorated with the **SKFunction** attribute, which allows us to indicate to the Semantic Kernel that it is a native function and, through the **Description** property, also give it information about what the purpose of this function is. In this case, what this method allows us to do is retrieve the alter ego of the superhero that we pass as a parameter, in this example that of Catwoman. If we take a look at the result, you will see that it is as expected:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "Console.WriteLine(result.GetValue());" + "In this repo, there is another directory called **NativeFunctions** where you can find a class called **HeroInfo.cs**. In it, there is a function decorated with the **KernelFunction** attribute, which allows us to indicate to the Semantic Kernel that it is a native function and, through the **Description** property, also give it information about what the purpose of this function is. In this case, what this method allows us to do is retrieve the alter ego of the superhero that we pass as a parameter, in this example that of Ironman. \n" ] }, { @@ -1061,12 +1042,51 @@ "source": [ "To see it in action, we are going to use the plugins that you already know.\n", "\n", - "The first thing you need is to instantiate a planner:\n" + "The first thing you need is to add the nuget reference to the Planner Handlebars.\n", + "\n", + "To learn more about this NuGet package, you can visit [here](https://www.nuget.org/packages/Microsoft.SemanticKernel.Planners.Handlebars/1.5.0-preview#show-readme-container).\n", + "\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are ready to create a planner." + ] + }, + { + "cell_type": "code", + "execution_count": 34, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1080,10 +1100,10 @@ }, "outputs": [], "source": [ - "using Microsoft.SemanticKernel.Planners;\n", + "using Microsoft.SemanticKernel.Planning.Handlebars;\n", "\n", - "// Create planner\n", - "var planner = new SequentialPlanner(kernel);" + "#pragma warning disable SKEXP0060\n", + "var planner = new HandlebarsPlanner();\n" ] }, { @@ -1097,7 +1117,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1109,27 +1129,42 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original plan:\n", + "\n", + "{\n", + " \"Prompt\": \"\\u003Csystem~\\u003E## Instructions\\nExplain how to achieve the user\\u0027s goal using the available helpers with a Handlebars .Net template.\\n\\n## Example\\nIf the user posed the goal below, you could answer with the following template.\\u003C/system~\\u003E\\n\\u003Cuser~\\u003E## Goal\\nI want you to generate 10 random numbers and send them to another helper.\\u003C/user~\\u003E\\n\\u003Cassistant~\\u003EHere\\u0027s a Handlebars template that achieves the goal:\\n\\u0060\\u0060\\u0060handlebars\\n{{!-- Step 0: Extract key values --}}\\n{{set\\n \\u0022count\\u0022\\n 10\\n}}\\n{{!-- Step 1: Loop using the count --}}\\n{{#each\\n (range\\n 1\\n count\\n )\\n}}\\n {{!-- Step 2: Create random number --}}\\n {{set\\n \\u0022randomNumber\\u0022\\n (Example-Random\\n seed=this\\n )\\n }}\\n {{!-- Step 3: Call example helper with random number and print the result to the screen --}}\\n {{set\\n \\u0022result\\u0022\\n (Example-Helper\\n input=randomNumber\\n )\\n }}\\n {{json (concat \\u0022The result\\u0022 \\u0022 \\u0022 \\u0022is:\\u0022 \\u0022 \\u0022 result)}}\\n{{/each}}\\n\\u0060\\u0060\\u0060\\u003C/assistant~\\u003E\\n\\u003Csystem~\\u003ENow let\\u0027s try the real thing.\\u003C/system~\\u003E\\n\\u003Cuser~\\u003EThe following helpers are available to you:\\n\\n## Built-in block helpers\\n- \\u0060{{#if}}{{/if}}\\u0060\\n- \\u0060{{#unless}}{{/unless}}\\u0060\\n- \\u0060{{#each}}{{/each}}\\u0060 - inside this block, you can use:\\n - \\u0060this\\u0060 to reference the element being iterated over\\n - \\u0060@index\\u0060 to reference the current index\\n - \\u0060@key\\u0060 to reference the current key (for object iteration)\\n- \\u0060{{#with}}{{/with}}\\u0060\\n\\n## Loop helpers\\nIf you need to loop through a list of values with \\u0060{{#each}}\\u0060, you can use the following helpers:\\n- \\u0060{{range}}\\u0060 \\u2013 Generates a list of integral numbers within a specified range, inclusive of the first and last value.\\n- \\u0060{{array}}\\u0060 \\u2013 Generates an array of values from the given values (zero-indexed).\\n\\nIMPORTANT: \\u0060range\\u0060 and \\u0060array\\u0060 are the only supported data structures. Others like \\u0060hash\\u0060 are not supported. Also, you cannot use any methods or properties on the built-in data structures.\\n\\n## Math helpers\\nIf you need to do basic operations, you can use these two helpers with numerical values:\\n- \\u0060{{add}}\\u0060 \\u2013 Adds two values together.\\n- \\u0060{{subtract}}\\u0060 \\u2013 Subtracts the second value from the first.\\n\\n## Comparison helpers\\nIf you need to compare two values, you can use the \\u0060{{equals}}\\u0060 helper.\\nTo use the math and comparison helpers, you must pass in two positional values. For example, to check if the variable \\u0060var\\u0060 is equal to number \\u00601\\u0060, you would use the following helper like so: \\u0060{{#if (equals var 1)}}{{/if}}\\u0060.\\n\\n## Variable helpers\\nIf you need to create or retrieve a variable, you can use the following helpers:\\n- \\u0060{{set}}\\u0060 \\u2013 Creates a variable with the given name and value. It does not print anything to the template, so you must use \\u0060{{json}}\\u0060 to print the value.\\n- \\u0060{{json}}\\u0060 \\u2013 Serializes the given value and prints result as JSON string.\\n- \\u0060{{concat}}\\u0060 \\u2013 Concatenates the given values into one string.\\n\\n## Custom helpers\\nLastly, you have the following custom helpers to use.\\n\\n### \\u0060HeroInfo-GetAlterEgo\\u0060\\nDescription: Get the alter ego of a superhero\\nInputs:\\n - input: input-string - (required)\\nOutput: String\\n\\nIMPORTANT: You can only use the helpers that are listed above. Do not use any other helpers that are not explicitly listed here. For example, do not use \\u0060{{log}}\\u0060 or any \\u0060{{Example}}\\u0060 helpers, as they are not supported.\\n\\u003C/user~\\u003E\\n\\u003Cuser~\\u003E## Goal\\nI would like you to tell me a joke about Batman, and with that joke, create an out-of-office message using the joke.\\u003C/user~\\u003E\\n\\n\\u003Csystem~\\u003E## Tips and reminders\\n- Add a comment above each step to describe what the step does.\\n- Each variable should have a well-defined name.\\n- Be extremely careful about types. For example, if you pass an array to a helper that expects a number, the template will error out.\\n- Each step should contain only one helper call.\\n\\n## Start\\nFollow these steps to create one Handlebars template to achieve the goal:\\n0. Extract Key Values:\\n - Read the goal and any user-provided content carefully and identify any relevant strings, numbers, or conditions that you\\u0027ll need. Do not modify any data.\\n - When generating variables or helper inputs, only use content that the user has explicitly provided or confirmed. If the user did not explicitly provide specific information, you should not invent or assume this information.\\n - Use the \\u0060{{set}}\\u0060 helper to create a variable for each key value.\\n - Omit this step if no values are needed from the initial context.\\n1. Choose the Right Helpers:\\n - Use the provided helpers to manipulate the variables you\\u0027ve created. Start with the basic helpers and only use custom helpers if necessary to accomplish the goal.\\n - Be careful with syntax, i.e., Always reference a custom helper by its full name and remember to use a \\u0060#\\u0060 for all block helpers.\\n2. Don\\u0027t Create or Assume Unlisted Helpers:\\n - Only use the helpers provided. Any helper not listed is considered hallucinated and must not be used.\\n - Do not invent or assume the existence of any functions not explicitly defined above.\\n3. What if I Need More Helpers?\\n - Stop here if the goal cannot be fully achieved with the provided helpers or you need a helper not defined, and just return a string with an appropriate error message.\\n4. Keep It Simple:\\n - Avoid using loops or block expressions. They are allowed but not always necessary, so try to find a solution that does not use them.\\n - Your template should be intelligent and efficient, avoiding unnecessary complexity or redundant steps.\\n5. No Nested Helpers:\\n - Do not nest helpers or conditionals inside other helpers. This can cause errors in the template.\\n6. Output the Result:\\n - Once you have completed the necessary steps to reach the goal, use the \\u0060{{json}}\\u0060 helper and print only your final template.\\n - Ensure your template and all steps are enclosed in a \\u0060\\u0060\\u0060 handlebars block.\\n\\nRemember, the objective is not to use all the helpers available, but to use the correct ones to achieve the desired outcome with a clear and concise template.\\n\\u003C/system~\\u003E\"\n", + "}\n" + ] + } + ], "source": [ "using System.Text.Json;\n", "\n", - "var ask = \"Me gustaría que me contaras un chiste sobre Batman, y con el chiste que hicieras un out of office con el chiste.\";\n", - "var plan = await planner.CreatePlanAsync(ask);\n", + "var ask = \"I would like you to tell me a joke about Batman, and with that joke, create an out-of-office message using the joke.\";\n", + "#pragma warning disable SKEXP0060\n", + "var originalPlan = await planner.CreatePlanAsync(kernel, ask);\n", "\n", - "Console.WriteLine(\"Plan:\\n\");\n", - "Console.WriteLine(JsonSerializer.Serialize(plan, new JsonSerializerOptions { WriteIndented = true }));" + "Console.WriteLine(\"Original plan:\\n\");\n", + "Console.WriteLine(originalPlan);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "As you can see, the planner knows about my plugins thanks to the description that I included as part of their implementation.\n" + "As you can see, the planner knows about the plugins thanks to the description that I included as part of their implementation.\n", + "\n", + "Time to run the plan and get an OOF for **Batman** that includes a **bad joke**.\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1141,12 +1176,24 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original Plan results:\n", + "\n", + "I am currently out of office. Here's a joke to lighten your day: Why did Batman go to the store? Because he ran out of bat-teries!\n" + ] + } + ], "source": [ - "var result = await kernel.RunAsync(plan);\n", + "// executing the plan\n", + "#pragma warning disable SKEXP0060\n", + "var originalPlanResult = await originalPlan.InvokeAsync(kernel, new KernelArguments());\n", "\n", - "Console.WriteLine(\"Plan result:\\n\");\n", - "Console.WriteLine(result.GetValue());" + "Console.WriteLine(\"Original Plan results:\\n\");\n", + "Console.WriteLine(originalPlanResult.ToString());" ] }, { @@ -1160,7 +1207,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1172,16 +1219,35 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plan:\n", + "\n", + "{{!-- Step 1: Get alter ego for IronMan --}}\n", + "{{#with (HeroInfo-GetAlterEgo 'IronMan') as |ironManAlterEgo|}}\n", + " {{!-- Step 2: Get alter ego for Batman --}}\n", + " {{#with (HeroInfo-GetAlterEgo 'Batman') as |batmanAlterEgo|}}\n", + " {{!-- Step 3: Set the out of office message --}}\n", + " {{set 'message' (concat 'Batman is currently out of office. Please contact ' batmanAlterEgo ' for any urgent matters.')}}\n", + "\n", + " {{!-- Step 4: Output the alter ego of IronMan and the message --}}\n", + " {{json (concat 'IronMan is also known as ' ironManAlterEgo '. ' 'Out of Office Message: ' message)}}\n", + " {{/with}}\n", + "{{/with}}\n" + ] + } + ], "source": [ - "using System.Text.Json;\n", - "\n", - "var ask_complex = \"I would like you to find out Batman's alter ego, and create an out of office message for Batman, signing it with his alter ego.\";\n", + "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, signing it with his alter ego.\";\n", "\n", - "var plan_complex = await planner.CreatePlanAsync(ask_complex);\n", + "#pragma warning disable SKEXP0060\n", + "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", "\n", "Console.WriteLine(\"Plan:\\n\");\n", - "Console.WriteLine(JsonSerializer.Serialize(plan_complex, new JsonSerializerOptions { WriteIndented = true }));" + "Console.WriteLine(plan_complex);" ] }, { @@ -1193,7 +1259,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1205,12 +1271,23 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Complex Plan results:\n", + "\n", + "Batman is currently out of office. Signed, Terry McGinnis\n" + ] + } + ], "source": [ - "var result_complex = await kernel.RunAsync(plan_complex);\n", + "#pragma warning disable SKEXP0060\n", + "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", "\n", - "Console.WriteLine(\"Plan result:\\n\");\n", - "Console.WriteLine(result_complex.GetValue());" + "Console.WriteLine(\"Complex Plan results:\\n\");\n", + "Console.WriteLine(complexPlanResult.ToString());" ] }, { From a4236f30d02f6355603b514c9d0d8e2b7b0843b3 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 12:23:02 -0500 Subject: [PATCH 09/25] add sample for memory and embeddings --- KernelMemory/Memories.cs | 72 ------------------------------- notebook-en.ipynb | 92 ++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 103 deletions(-) delete mode 100644 KernelMemory/Memories.cs diff --git a/KernelMemory/Memories.cs b/KernelMemory/Memories.cs deleted file mode 100644 index c3c3d24..0000000 --- a/KernelMemory/Memories.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.ComponentModel; -using System.Text.Json; -using Microsoft.KernelMemory; - -public class MemoryKernel -{ - static MemoryServerless memory; - - public static void Init(string openApiKey) - { - - KernelMemoryBuilder kernelMemoryBuilder; - - kernelMemoryBuilder = new KernelMemoryBuilder() - .WithOpenAIDefaults(openApiKey); - - memory = kernelMemoryBuilder.BuildServerlessClient(); - - LoadTextMemories(); - LoadDocs(); - } - - static async void LoadTextMemories() - { - await memory.ImportTextAsync("El súper héroe favorito de Gisela es Batman", documentId: "gis01", tags: new TagCollection { { "type", "people" } }); - await memory.ImportTextAsync("La última película que Gisela vio de súper héroes fue Guardianes de la Galaxia Vol. 3 ", documentId: "gis02", tags: new TagCollection { { "type", "people" } }); - await memory.ImportTextAsync("El súper héroe favorito de Bruno es Invencible", documentId: "bru01", tags: new TagCollection { { "type", "people" } }); - await memory.ImportTextAsync("La última película que Bruno vio de súper héroes fue Batman de Tim Burton ", documentId: "bru02", tags: new TagCollection { { "type", "people" } }); - } - - static async void LoadDocs() - { - await memory.ImportDocumentAsync("docs/Norma editorial - Septiembre 2020.pdf", documentId: "doc001", tags: new TagCollection { { "type", "document" } }); - } - - [SKFunction, Description("Sobre el volumen")] - public static async Task AboutTheDocuments(string ask) - { - var answer = await memory.AskAsync(ask, filter: new MemoryFilter().ByTag("type", "document")); - - // Answer - Console.WriteLine($"\nAnswer: {answer.Result}"); - - // Sources - foreach (var x in answer.RelevantSources) - { - Console.WriteLine($" - {x.SourceName} - {x.Link} [{x.Partitions.First().LastUpdate:D}]"); - } - - // return a json string with the answer and the sources - return JsonSerializer.Serialize(new { answer = answer.Result, references = answer.RelevantSources.Select(x => x.SourceName) }); - } - - [SKFunction, Description("Responde preguntas sobre Bruno y Gisela")] - public static async Task AboutMe(string ask) - { - var answer = await memory.AskAsync(ask, filter: new MemoryFilter().ByTag("type", "people")); - - // Answer - Console.WriteLine($"\nAnswer: {answer.Result}"); - - // Sources - foreach (var x in answer.RelevantSources) - { - Console.WriteLine($" - {x.SourceName} - {x.Link} [{x.Partitions.First().LastUpdate:D}]"); - } - - // return a json string with the answer and the sources - return JsonSerializer.Serialize(new { answer = answer.Result, references = answer.RelevantSources.Select(x => x.SourceName) }); - - } -} \ No newline at end of file diff --git a/notebook-en.ipynb b/notebook-en.ipynb index c1fb6ae..245b9bb 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -1207,7 +1207,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 45, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1226,17 +1226,11 @@ "text": [ "Plan:\n", "\n", - "{{!-- Step 1: Get alter ego for IronMan --}}\n", - "{{#with (HeroInfo-GetAlterEgo 'IronMan') as |ironManAlterEgo|}}\n", - " {{!-- Step 2: Get alter ego for Batman --}}\n", - " {{#with (HeroInfo-GetAlterEgo 'Batman') as |batmanAlterEgo|}}\n", - " {{!-- Step 3: Set the out of office message --}}\n", - " {{set 'message' (concat 'Batman is currently out of office. Please contact ' batmanAlterEgo ' for any urgent matters.')}}\n", + "{{!-- Step 1: Get alter ego of IronMan --}}\n", + "{{set \"alterEgo\" (HeroInfo-GetAlterEgo input=\"IronMan\")}}\n", "\n", - " {{!-- Step 4: Output the alter ego of IronMan and the message --}}\n", - " {{json (concat 'IronMan is also known as ' ironManAlterEgo '. ' 'Out of Office Message: ' message)}}\n", - " {{/with}}\n", - "{{/with}}\n" + "{{!-- Step 2: Create an out of office message --}}\n", + "{{json (concat \"I am currently out of the office as IronMan, but I will return shortly. Best, \" alterEgo)}}\n" ] } ], @@ -1259,7 +1253,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 46, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1278,7 +1272,7 @@ "text": [ "Complex Plan results:\n", "\n", - "Batman is currently out of office. Signed, Terry McGinnis\n" + "I am currently out of the office as IronMan, but I will return shortly. Best, Tony Stark\n" ] } ], @@ -1299,25 +1293,18 @@ "" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this example, I'm going to use **Open AI** instead of Azure Open AI, so you need to save [an API Key](https://platform.openai.com/account/api-keys) from this in the following variable:\n" - ] - }, { "cell_type": "markdown", "metadata": {}, "source": [ "To be able to use Kernel Memory, you need to add its nuget library, in addition to importing the class that I have generated in the **KernelMemory** directory.\n", "\n", - "To learn more about the Kernel Memory library, you can visit the [NuGet package page](https://www.nuget.org/packages/Microsoft.KernelMemory.Core).\n" + "To learn more about the Kernel Memory library, you can visit the [NuGet package page](https://www.nuget.org/packages/Microsoft.SemanticKernel.Plugins.Memory/1.5.0-alpha#show-readme-container).\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1329,23 +1316,35 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "#r \"nuget: Microsoft.KernelMemory.Core, 0.11.231120.6-preview\"\n", - "\n", - "#!import \"KernelMemory/Memories.cs\"" + "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The first thing I'm going to do is import a few *memories* (texts) and *documents* into Kernel Memory.\n" + "In order to use memory, we need to instantiate the Memory Plugin with a Memory Storage and an Embedding backend. In this example, we make use of the VolatileMemoryStore which can be thought of as a temporary in-memory storage (not to be confused with Semantic Memory).\n", + "\n", + "This memory is not written to disk and is only available during the app session.\n", + "\n", + "When developing your app you will have the option to plug in persistent storage like Azure Cosmos Db, PostgreSQL, SQLite, etc. Semantic Memory allows also to index external data sources, without duplicating all the information, more on that later." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1357,11 +1356,42 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "ename": "Error", + "evalue": "(8,15): error CS1061: 'MemoryBuilder' does not contain a definition for 'WithOpenAITextEmbeddingGeneration' and no accessible extension method 'WithOpenAITextEmbeddingGeneration' accepting a first argument of type 'MemoryBuilder' could be found (are you missing a using directive or an assembly reference?)", + "output_type": "error", + "traceback": [ + "(8,15): error CS1061: 'MemoryBuilder' does not contain a definition for 'WithOpenAITextEmbeddingGeneration' and no accessible extension method 'WithOpenAITextEmbeddingGeneration' accepting a first argument of type 'MemoryBuilder' could be found (are you missing a using directive or an assembly reference?)" + ] + } + ], "source": [ - "var openApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\");\n", + "using Microsoft.SemanticKernel.Memory;\n", + "\n", + "// create the memory builder\n", + "#pragma warning disable SKEXP0003, SKEXP0011, SKEXP0052\n", + "var memoryBuilder = new MemoryBuilder();\n", + "\n", + "// Using OpenAI\n", + "memoryBuilder.WithOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey);\n", "\n", - "MemoryKernel.Init(openApiKey.GetClearTextPassword());" + "\n", + "// Using Azure OpenAI \n", + "// memoryBuilder.WithAzureOpenAITextEmbeddingGeneration(\n", + "// AzureOpenAI.EmbeddingsModel,\n", + "// AzureOpenAI.Endpoint,\n", + "// AzureOpenAI.ApiKey,\n", + "// \"text-embedding-ada-002\");\n", + "memoryBuilder.WithMemoryStore(new VolatileMemoryStore());\n", + "var memory = memoryBuilder.Build();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then let's add a few *memories* (texts)" ] }, { From f15708199ff713bebc7f7cf2020f54b7e736c8e5 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 12:24:58 -0500 Subject: [PATCH 10/25] Update notebook-en.ipynb with additional packages and memories --- notebook-en.ipynb | 135 +++++++++++++++------------------------------- 1 file changed, 44 insertions(+), 91 deletions(-) diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 245b9bb..7d6bda4 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -1304,7 +1304,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 49, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1320,7 +1320,7 @@ { "data": { "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
" + "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
  • System.Linq.Async, 6.0.1
" ] }, "metadata": {}, @@ -1328,7 +1328,8 @@ } ], "source": [ - "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"" + "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", + "#r \"nuget: System.Linq.Async, 6.0.1\"\n" ] }, { @@ -1344,7 +1345,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 51, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1356,18 +1357,10 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "(8,15): error CS1061: 'MemoryBuilder' does not contain a definition for 'WithOpenAITextEmbeddingGeneration' and no accessible extension method 'WithOpenAITextEmbeddingGeneration' accepting a first argument of type 'MemoryBuilder' could be found (are you missing a using directive or an assembly reference?)", - "output_type": "error", - "traceback": [ - "(8,15): error CS1061: 'MemoryBuilder' does not contain a definition for 'WithOpenAITextEmbeddingGeneration' and no accessible extension method 'WithOpenAITextEmbeddingGeneration' accepting a first argument of type 'MemoryBuilder' could be found (are you missing a using directive or an assembly reference?)" - ] - } - ], + "outputs": [], "source": [ "using Microsoft.SemanticKernel.Memory;\n", + "using Microsoft.SemanticKernel.Connectors.OpenAI;\n", "\n", "// create the memory builder\n", "#pragma warning disable SKEXP0003, SKEXP0011, SKEXP0052\n", @@ -1376,13 +1369,13 @@ "// Using OpenAI\n", "memoryBuilder.WithOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey);\n", "\n", - "\n", "// Using Azure OpenAI \n", "// memoryBuilder.WithAzureOpenAITextEmbeddingGeneration(\n", "// AzureOpenAI.EmbeddingsModel,\n", "// AzureOpenAI.Endpoint,\n", "// AzureOpenAI.ApiKey,\n", "// \"text-embedding-ada-002\");\n", + "\n", "memoryBuilder.WithMemoryStore(new VolatileMemoryStore());\n", "var memory = memoryBuilder.Build();" ] @@ -1391,71 +1384,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Then let's add a few *memories* (texts)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you can see in the output, it already takes care of generating the embeddings of the sentences/documents that we pass to it so that the GPT-4 model can generate the answer.\n", - "Now that we have some content to ask about, let's load this class as another plugin.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "var memoriesPlugin = kernel.ImportFunctions(new MemoryKernel(), \"MemoriesPlugin\");" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And now let's ask about the content:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "var planner = new SequentialPlanner(kernel);\n", - "\n", - "var plan = await planner.CreatePlanAsync(\"Who is Bruno's favorite hero?\");\n", - "\n", - "var result = await kernel.RunAsync(plan);\n", - "\n", - "Console.WriteLine(result.GetValue());" + "Let's create some initial memories \"Fan Facts\". We can add memories to our VolatileMemoryStore by using SaveInformationAsync:\n", + "\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1469,25 +1404,26 @@ }, "outputs": [], "source": [ - "var planner = new SequentialPlanner(kernel);\n", - "\n", - "var plan = await planner.CreatePlanAsync(\"What was the last movie Gisela saw?\");\n", + "// add fan facts to the collection\n", + "const string MemoryCollectionName = \"fanFacts\";\n", "\n", - "var result = await kernel.RunAsync(plan);\n", - "\n", - "Console.WriteLine(result.GetValue());" + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info1\", text: \"Gisela's favourite super hero is Batman\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info2\", text: \"The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info3\", text: \"Bruno's favourite super hero is Invincible\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"The last super hero movie watched by Bruno was Aquaman II\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can also ask about the PDF that I included:\n" + "And now we can test and search in the memory:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 53, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1499,15 +1435,32 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "what is Bruno's favourite super hero? Bruno's favourite super hero is Invincible\n", + "what was the last movie watched by Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", + "Which is the prefered super hero for Gisela? Gisela's favourite super hero is Batman\n", + "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n" + ] + } + ], "source": [ - "var planner = new SequentialPlanner(kernel);\n", - "\n", - "var plan = await planner.CreatePlanAsync(\"¿Qué incluye este volumen de batman?\");\n", - "\n", - "var result = await kernel.RunAsync(plan);\n", + "var questions = new[]\n", + "{\n", + " \"what is Bruno's favourite super hero?\",\n", + " \"what was the last movie watched by Gisela?\",\n", + " \"Which is the prefered super hero for Gisela?\",\n", + " \"Did Bruno watched a super hero movie in the past, which was the last one?\"\n", + "};\n", "\n", - "Console.WriteLine(result.GetValue());" + "foreach (var q in questions)\n", + "{\n", + " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", + "}\n" ] } ], From c2d9d7e06dc81769f28116584d131cdcf737b75f Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 29 Feb 2024 14:25:44 -0500 Subject: [PATCH 11/25] Update readme content --- .gitignore | 9 ++ LICENSE | 21 +++ README.md | 106 +++++++++++++++ images/10VSCodeDemo.png | Bin 0 -> 143911 bytes notebook-en.ipynb | 278 +++++++--------------------------------- 5 files changed, 179 insertions(+), 235 deletions(-) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 images/10VSCodeDemo.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d801ea7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +src/.vs/** +src/sk-phi2-localserver-lmstudio/obj/** +src/sk-phi2-localserver-lmstudio/bin/** +src/sk-customllm/bin/** +src/sk-customllm/obj/** +src/sk-ollama-localserver-ubuntu/bin/** +src/sk-ollama-localserver-ubuntu/obj/** +src/sk-ollama-localserver-rpi/bin/** +src/sk-ollama-localserver-rpi/obj/** diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..20072b0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 El Bruno + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..411ee2c --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +# Understanding Semantic Kernel with Super Heroes + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](/LICENSE) +[![Twitter: elbruno](https://img.shields.io/twitter/follow/elbruno.svg?style=social)](https://twitter.com/elbruno) +![GitHub: elbruno](https://img.shields.io/github/followers/elbruno?style=social) + +✨ +Understanding Semantic Kernel with Heroes is a set of Polyglot notebooks that explores the concept of Semantic Kernel. The notebooks demonstrates how to learn the basis of Semantic Kernel using comic book heroes based on their descriptions. For more details, check out the repository. 🚀📚 + +## Getting started - Semantic Kernel + +This repository contains a set of notebooks, in different languages, that helps you learn how to use Semantic Kernel. For more information, check out the [Semantic Kernel Overview](https://learn.microsoft.com/en-us/semantic-kernel/overview/?WT.mc_id=academic-00000-brunocapuano). + +Semantic Kernel is a powerful tool that allows developers to integrate cutting-edge language models into their applications with ease. Semantic Kernel provides a unified interface to access various language models from different sources, such as OpenAI, AzureOpenAI, and Hugging Face. Semantic Kernel also enables developers to store and retrieve memories, create dynamic prompts, and combine functions together with planners. + +With Semantic Kernel, developers can supercharge their problem-solving creativity and build AI solutions that can understand natural language, generate content, answer questions, and more. Semantic Kernel is an open-source project that can be run on any local machine or cloud environment. Semantic Kernel offers tutorials, guides, and examples to help developers get started quickly and learn how to use its features. + +## Topics + +1. Understanding Semantic Kernel +2. (Optional) - Creating an Azure Open AI 🤖 Service and Deployments +3. How to get started with Semantic Kernel +4. Using Semantic Kernel plugins +5. Semantic Functions +6. Native Functions +7. Planner +8. Advanced Planner Labs +9. Kernel Memory + +## Semantic Kernel C# Notebooks + +The current folder contains a few C# Polyglot Notebooks that demonstrate how to get started with the Semantic Kernel. + +To run the notebooks, we recommend the following steps: + +- [Install .NET 8](https://dotnet.microsoft.com/download/dotnet/8.0) +- [Install Visual Studio Code (VS Code)](https://code.visualstudio.com) +- Launch VS Code and [install the "Polyglot" extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode). + Min version required: v1.0.4606021 (Dec 2023). + +The steps above should be sufficient, you can now **open all the C# notebooks in VS Code**. + +VS Code screenshot example: + +![image](/images/10VSCodeDemo.png) + +## Troubleshooting + +## Nuget + +If you are unable to get the Nuget package, first list your Nuget sources: + +```sh +dotnet nuget list source +``` + +If you see `No sources found.`, add the NuGet official package source: + +```sh +dotnet nuget add source "https://api.nuget.org/v3/index.json" --name "nuget.org" +``` + +Run `dotnet nuget list source` again to verify the source was added. + +## Polyglot Notebooks + +If somehow the notebooks don't work, run these commands: + +- Install .NET Interactive: `dotnet tool install -g Microsoft.dotnet-interactive` +- Register .NET kernels into Jupyter: `dotnet interactive jupyter install` (this might return some errors, ignore them) +- If you are still stuck, read the following pages: + - https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode + - https://devblogs.microsoft.com/dotnet/net-core-with-juypter-notebooks-is-here-preview-1/ + - https://docs.servicestack.net/jupyter-notebooks-csharp + - https://developers.refinitiv.com/en/article-catalog/article/using--net-core-in-jupyter-notebook + +Note: ["Polyglot Notebooks" used to be called ".NET Interactive Notebooks"](https://devblogs.microsoft.com/dotnet/dotnet-interactive-notebooks-is-now-polyglot-notebooks/), +so you might find online some documentation referencing the old name. + +## Author + +👤 **Bruno Capuano** + +* Website: https://elbruno.com +* Twitter: [@elbruno](https://twitter.com/elbruno) +* Github: [@elbruno](https://github.com/elbruno) +* LinkedIn: [@elbruno](https://linkedin.com/in/elbruno) + +## 🤝 Contributing + +Contributions, issues and feature requests are welcome! + +Feel free to check [issues page](https://github.com/elbruno/understanding-semantic-kernel-with-heroes/issues). + +## Show your support + +Give a ⭐️ if this project helped you! + + +## 📝 License + +Copyright © 2024 [Bruno Capuano](https://github.com/elbruno). + +This project is [MIT](/LICENSE) licensed. + +*** \ No newline at end of file diff --git a/images/10VSCodeDemo.png b/images/10VSCodeDemo.png new file mode 100644 index 0000000000000000000000000000000000000000..65ddd792b15f959a79dea5c51fb1eb214b91b315 GIT binary patch literal 143911 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 literal 0 HcmV?d00001 diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 7d6bda4..ecf8112 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -279,7 +279,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -291,17 +291,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "

Installed Packages
  • Microsoft.SemanticKernel, 1.5.0
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" ] @@ -315,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -344,7 +334,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -400,7 +390,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -421,7 +411,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## The plugins\n", + "## Using Semantic Kernel plugins\n", "\n", "Plugins are the core of Semantic Kernel. With them, you encapsulate capabilities so that they can be reusable, maintainable, and plannable (you will understand it later 🙃). There are two types: those that consist of prompt templates called **Semantic Functions** and native functions of the chosen programming language called **Native Functions**.\n", "\n", @@ -434,7 +424,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Semantic Functions\n", + "## Semantic Functions\n", "\n", "When you talk to artificial intelligence models, you must do so with what is known as a *prompt*. This can range from a simple phrase to something more elaborate, allowing the model to understand not only what we want but also how we want it. If you take a look at the official documentation, it defines this type of function as the mouth 👄 and ears 👂🏻 of your brain 🧠. 🤖🌐\n", "\n", @@ -457,7 +447,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -485,7 +475,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -512,7 +502,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -596,7 +586,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -608,19 +598,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sure, here's a joke for you:\n", - "\n", - "Why don't superheroes like to play hide and seek with The Invisible Man?\n", - "\n", - "Because he always wins, even when they use their x-ray vision!\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -634,7 +612,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -663,7 +641,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -689,7 +667,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -701,17 +679,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Why did Ironman decorate the Christmas tree with tiny repulsor beams?\n", - "\n", - "Because he wanted to make sure his Christmas was lit... but also well-defended from Ultron!\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -725,7 +693,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -754,7 +722,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -766,27 +734,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Una vez, en una fría noche de Navidad 🎄❄️, nuestro héroe Ironman, también conocido como Tony Stark, volaba por los cielos 🌌 vigilando la tranquila ciudad de Nueva York. \n", - "\n", - "A mitad de noche 🌛, escuchó un leve sonido 🎵 que provenía del callejón. Descendió para investigar y encontró a un niño llorando 😢. El niño, asustado por el frío y la oscuridad, había perdido a su madre en la multitud de las fiestas navideñas.\n", - "\n", - "Ironman, con su corazón heroico, decidió ayudar. Levantó al niño en sus brazos y con su traje luminoso ✨ voló sobre la ciudad en busca de su madre. Desde el cielo 🌠, el niño se sintió maravillado por las luces brillantes de la ciudad y su miedo se convirtió en admiración 😮.\n", - "\n", - "Finalmente, encontraron a la madre del niño en un parque. Al ver a su hijo a salvo y sano, la madre lloró de felicidad 😭. Le agradeció a Ironman, quien le sonrió bajo su casco de hierro.\n", - "\n", - "Antes de irse, Ironman dejó un regalo 🎁 debajo del árbol de Navidad para el niño. Luego, se elevó en el cielo y la noche nevada se llenó de destellos rojos y dorados mientras volaba lejos.\n", - "\n", - "El niño y su madre regresaron a su casa, llenos de alegría y gratitud 😊. Abrieron el regalo y dentro encontraron un pequeño juguete de Ironman. Cada vez que el niño lo miraba, recordaba la mágica noche de Navidad que había pasado junto al verdadero Ironman.\n", - "\n", - "Esa noche, Ironman no solo salvó al niño, sino también la esencia de la Navidad: el amor, la bondad y la alegría de dar 🎁🎄❤️. Y ese fue verdaderamente un milagro navideño. Fin.\r\n" - ] - } - ], + "outputs": [], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Tell me a Christmas Story\",\n", @@ -806,7 +754,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -818,62 +766,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "Microsoft.SemanticKernel.KernelFunctionCanceledException: The invocation of function 'OOF' was canceled.\r\n ---> System.Threading.Tasks.TaskCanceledException: The operation was cancelled because it exceeded the configured timeout of 0:01:40. Network timeout can be adjusted in ClientOptions.Retry.NetworkTimeout.\r\n ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n ---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..\r\n ---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.\r\n --- End of inner exception stack trace ---\r\n at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)\r\n at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)\r\n at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)\r\n at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n at System.Net.Http.HttpConnection.g__ReadAheadWithZeroByteReadAsync|40_0()\r\n at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n --- End of inner exception stack trace ---\r\n at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)\r\n at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n at Azure.Core.Pipeline.HttpClientTransport.ProcessAsync(HttpMessage message, Boolean async)\r\n at Azure.Core.Pipeline.HttpPipelineTransportPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)\r\n at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n --- End of inner exception stack trace ---\r\n at Azure.Core.Pipeline.ResponseBodyPolicy.ThrowIfCancellationRequestedOrTimeout(CancellationToken originalToken, CancellationToken timeoutToken, Exception inner, TimeSpan timeout)\r\n at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)\r\n at Azure.AI.OpenAI.OpenAIClient.GetChatCompletionsAsync(ChatCompletionsOptions chatCompletionsOptions, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.RunRequestAsync[T](Func`1 request)\r\n at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetChatMessageContentsAsync(ChatHistory chat, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.ChatCompletion.ChatCompletionServiceExtensions.GetChatMessageContentAsync(IChatCompletionService chatCompletionService, String prompt, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.KernelFunctionFromPrompt.InvokeCoreAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n --- End of inner exception stack trace ---\r\n at Microsoft.SemanticKernel.KernelFunction.HandleException(Exception ex, ILogger logger, Activity activity, KernelFunction kernelFunction, Kernel kernel, KernelArguments arguments, FunctionResult result, TagList& tags)\r\n at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n at Submission#22.<>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)", - "output_type": "error", - "traceback": [ - "Microsoft.SemanticKernel.KernelFunctionCanceledException: The invocation of function 'OOF' was canceled.\r\n", - " ---> System.Threading.Tasks.TaskCanceledException: The operation was cancelled because it exceeded the configured timeout of 0:01:40. Network timeout can be adjusted in ClientOptions.Retry.NetworkTimeout.\r\n", - " ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n", - " ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.\r\n", - " ---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..\r\n", - " ---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.\r\n", - " --- End of inner exception stack trace ---\r\n", - " at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)\r\n", - " at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n", - " at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)\r\n", - " at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n", - " at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)\r\n", - " at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)\r\n", - " at System.Net.Http.HttpConnection.g__ReadAheadWithZeroByteReadAsync|40_0()\r\n", - " at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", - " --- End of inner exception stack trace ---\r\n", - " at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", - " at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n", - " at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", - " at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n", - " at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n", - " --- End of inner exception stack trace ---\r\n", - " at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)\r\n", - " at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n", - " at Azure.Core.Pipeline.HttpClientTransport.ProcessAsync(HttpMessage message, Boolean async)\r\n", - " at Azure.Core.Pipeline.HttpPipelineTransportPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)\r\n", - " at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", - " --- End of inner exception stack trace ---\r\n", - " at Azure.Core.Pipeline.ResponseBodyPolicy.ThrowIfCancellationRequestedOrTimeout(CancellationToken originalToken, CancellationToken timeoutToken, Exception inner, TimeSpan timeout)\r\n", - " at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", - " at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", - " at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", - " at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", - " at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)\r\n", - " at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)\r\n", - " at Azure.AI.OpenAI.OpenAIClient.GetChatCompletionsAsync(ChatCompletionsOptions chatCompletionsOptions, CancellationToken cancellationToken)\r\n", - " at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.RunRequestAsync[T](Func`1 request)\r\n", - " at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetChatMessageContentsAsync(ChatHistory chat, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n", - " at Microsoft.SemanticKernel.ChatCompletion.ChatCompletionServiceExtensions.GetChatMessageContentAsync(IChatCompletionService chatCompletionService, String prompt, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)\r\n", - " at Microsoft.SemanticKernel.KernelFunctionFromPrompt.InvokeCoreAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n", - " at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n", - " --- End of inner exception stack trace ---\r\n", - " at Microsoft.SemanticKernel.KernelFunction.HandleException(Exception ex, ILogger logger, Activity activity, KernelFunction kernelFunction, Kernel kernel, KernelArguments arguments, FunctionResult result, TagList& tags)\r\n", - " at Microsoft.SemanticKernel.KernelFunction.InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)\r\n", - " at Submission#22.<>d__0.MoveNext()\r\n", - "--- End of stack trace from previous location ---\r\n", - " at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)" - ] - } - ], + "outputs": [], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Create an OOF for Christmas\",\n", @@ -925,7 +818,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -953,7 +846,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -983,7 +876,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -995,15 +888,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tony Stark\r\n" - ] - } - ], + "outputs": [], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", @@ -1050,7 +935,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1062,17 +947,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" ] @@ -1086,7 +961,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1117,7 +992,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1129,19 +1004,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original plan:\n", - "\n", - "{\n", - " \"Prompt\": \"\\u003Csystem~\\u003E## Instructions\\nExplain how to achieve the user\\u0027s goal using the available helpers with a Handlebars .Net template.\\n\\n## Example\\nIf the user posed the goal below, you could answer with the following template.\\u003C/system~\\u003E\\n\\u003Cuser~\\u003E## Goal\\nI want you to generate 10 random numbers and send them to another helper.\\u003C/user~\\u003E\\n\\u003Cassistant~\\u003EHere\\u0027s a Handlebars template that achieves the goal:\\n\\u0060\\u0060\\u0060handlebars\\n{{!-- Step 0: Extract key values --}}\\n{{set\\n \\u0022count\\u0022\\n 10\\n}}\\n{{!-- Step 1: Loop using the count --}}\\n{{#each\\n (range\\n 1\\n count\\n )\\n}}\\n {{!-- Step 2: Create random number --}}\\n {{set\\n \\u0022randomNumber\\u0022\\n (Example-Random\\n seed=this\\n )\\n }}\\n {{!-- Step 3: Call example helper with random number and print the result to the screen --}}\\n {{set\\n \\u0022result\\u0022\\n (Example-Helper\\n input=randomNumber\\n )\\n }}\\n {{json (concat \\u0022The result\\u0022 \\u0022 \\u0022 \\u0022is:\\u0022 \\u0022 \\u0022 result)}}\\n{{/each}}\\n\\u0060\\u0060\\u0060\\u003C/assistant~\\u003E\\n\\u003Csystem~\\u003ENow let\\u0027s try the real thing.\\u003C/system~\\u003E\\n\\u003Cuser~\\u003EThe following helpers are available to you:\\n\\n## Built-in block helpers\\n- \\u0060{{#if}}{{/if}}\\u0060\\n- \\u0060{{#unless}}{{/unless}}\\u0060\\n- \\u0060{{#each}}{{/each}}\\u0060 - inside this block, you can use:\\n - \\u0060this\\u0060 to reference the element being iterated over\\n - \\u0060@index\\u0060 to reference the current index\\n - \\u0060@key\\u0060 to reference the current key (for object iteration)\\n- \\u0060{{#with}}{{/with}}\\u0060\\n\\n## Loop helpers\\nIf you need to loop through a list of values with \\u0060{{#each}}\\u0060, you can use the following helpers:\\n- \\u0060{{range}}\\u0060 \\u2013 Generates a list of integral numbers within a specified range, inclusive of the first and last value.\\n- \\u0060{{array}}\\u0060 \\u2013 Generates an array of values from the given values (zero-indexed).\\n\\nIMPORTANT: \\u0060range\\u0060 and \\u0060array\\u0060 are the only supported data structures. Others like \\u0060hash\\u0060 are not supported. Also, you cannot use any methods or properties on the built-in data structures.\\n\\n## Math helpers\\nIf you need to do basic operations, you can use these two helpers with numerical values:\\n- \\u0060{{add}}\\u0060 \\u2013 Adds two values together.\\n- \\u0060{{subtract}}\\u0060 \\u2013 Subtracts the second value from the first.\\n\\n## Comparison helpers\\nIf you need to compare two values, you can use the \\u0060{{equals}}\\u0060 helper.\\nTo use the math and comparison helpers, you must pass in two positional values. For example, to check if the variable \\u0060var\\u0060 is equal to number \\u00601\\u0060, you would use the following helper like so: \\u0060{{#if (equals var 1)}}{{/if}}\\u0060.\\n\\n## Variable helpers\\nIf you need to create or retrieve a variable, you can use the following helpers:\\n- \\u0060{{set}}\\u0060 \\u2013 Creates a variable with the given name and value. It does not print anything to the template, so you must use \\u0060{{json}}\\u0060 to print the value.\\n- \\u0060{{json}}\\u0060 \\u2013 Serializes the given value and prints result as JSON string.\\n- \\u0060{{concat}}\\u0060 \\u2013 Concatenates the given values into one string.\\n\\n## Custom helpers\\nLastly, you have the following custom helpers to use.\\n\\n### \\u0060HeroInfo-GetAlterEgo\\u0060\\nDescription: Get the alter ego of a superhero\\nInputs:\\n - input: input-string - (required)\\nOutput: String\\n\\nIMPORTANT: You can only use the helpers that are listed above. Do not use any other helpers that are not explicitly listed here. For example, do not use \\u0060{{log}}\\u0060 or any \\u0060{{Example}}\\u0060 helpers, as they are not supported.\\n\\u003C/user~\\u003E\\n\\u003Cuser~\\u003E## Goal\\nI would like you to tell me a joke about Batman, and with that joke, create an out-of-office message using the joke.\\u003C/user~\\u003E\\n\\n\\u003Csystem~\\u003E## Tips and reminders\\n- Add a comment above each step to describe what the step does.\\n- Each variable should have a well-defined name.\\n- Be extremely careful about types. For example, if you pass an array to a helper that expects a number, the template will error out.\\n- Each step should contain only one helper call.\\n\\n## Start\\nFollow these steps to create one Handlebars template to achieve the goal:\\n0. Extract Key Values:\\n - Read the goal and any user-provided content carefully and identify any relevant strings, numbers, or conditions that you\\u0027ll need. Do not modify any data.\\n - When generating variables or helper inputs, only use content that the user has explicitly provided or confirmed. If the user did not explicitly provide specific information, you should not invent or assume this information.\\n - Use the \\u0060{{set}}\\u0060 helper to create a variable for each key value.\\n - Omit this step if no values are needed from the initial context.\\n1. Choose the Right Helpers:\\n - Use the provided helpers to manipulate the variables you\\u0027ve created. Start with the basic helpers and only use custom helpers if necessary to accomplish the goal.\\n - Be careful with syntax, i.e., Always reference a custom helper by its full name and remember to use a \\u0060#\\u0060 for all block helpers.\\n2. Don\\u0027t Create or Assume Unlisted Helpers:\\n - Only use the helpers provided. Any helper not listed is considered hallucinated and must not be used.\\n - Do not invent or assume the existence of any functions not explicitly defined above.\\n3. What if I Need More Helpers?\\n - Stop here if the goal cannot be fully achieved with the provided helpers or you need a helper not defined, and just return a string with an appropriate error message.\\n4. Keep It Simple:\\n - Avoid using loops or block expressions. They are allowed but not always necessary, so try to find a solution that does not use them.\\n - Your template should be intelligent and efficient, avoiding unnecessary complexity or redundant steps.\\n5. No Nested Helpers:\\n - Do not nest helpers or conditionals inside other helpers. This can cause errors in the template.\\n6. Output the Result:\\n - Once you have completed the necessary steps to reach the goal, use the \\u0060{{json}}\\u0060 helper and print only your final template.\\n - Ensure your template and all steps are enclosed in a \\u0060\\u0060\\u0060 handlebars block.\\n\\nRemember, the objective is not to use all the helpers available, but to use the correct ones to achieve the desired outcome with a clear and concise template.\\n\\u003C/system~\\u003E\"\n", - "}\n" - ] - } - ], + "outputs": [], "source": [ "using System.Text.Json;\n", "\n", @@ -1164,7 +1027,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1176,17 +1039,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original Plan results:\n", - "\n", - "I am currently out of office. Here's a joke to lighten your day: Why did Batman go to the store? Because he ran out of bat-teries!\n" - ] - } - ], + "outputs": [], "source": [ "// executing the plan\n", "#pragma warning disable SKEXP0060\n", @@ -1200,14 +1053,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## LABS\n", + "### Advanced Planner Labs\n", "\n", "The kernel already has the plugins loaded, and the function, let's see if it can solve a more complex example:\n" ] }, { "cell_type": "code", - "execution_count": 45, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1219,21 +1072,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Plan:\n", - "\n", - "{{!-- Step 1: Get alter ego of IronMan --}}\n", - "{{set \"alterEgo\" (HeroInfo-GetAlterEgo input=\"IronMan\")}}\n", - "\n", - "{{!-- Step 2: Create an out of office message --}}\n", - "{{json (concat \"I am currently out of the office as IronMan, but I will return shortly. Best, \" alterEgo)}}\n" - ] - } - ], + "outputs": [], "source": [ "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, signing it with his alter ego.\";\n", "\n", @@ -1253,7 +1092,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1265,17 +1104,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Complex Plan results:\n", - "\n", - "I am currently out of the office as IronMan, but I will return shortly. Best, Tony Stark\n" - ] - } - ], + "outputs": [], "source": [ "#pragma warning disable SKEXP0060\n", "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", @@ -1304,7 +1133,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1316,17 +1145,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
  • System.Linq.Async, 6.0.1
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" @@ -1345,7 +1164,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1390,7 +1209,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1423,7 +1242,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1435,18 +1254,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "what is Bruno's favourite super hero? Bruno's favourite super hero is Invincible\n", - "what was the last movie watched by Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", - "Which is the prefered super hero for Gisela? Gisela's favourite super hero is Batman\n", - "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n" - ] - } - ], + "outputs": [], "source": [ "var questions = new[]\n", "{\n", From a155c38a3c1cef9e470733dd8048271b77806267 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 5 Mar 2024 14:44:49 -0300 Subject: [PATCH 12/25] working in Spanish translation --- notebook-es.ipynb | 482 ++++++++++++++++++++++++++-------------------- 1 file changed, 275 insertions(+), 207 deletions(-) diff --git a/notebook-es.ipynb b/notebook-es.ipynb index 5f4eae6..8864be3 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -4,9 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 🦸🏻 Entendiendo Semantic Kernel con Héroes 🦸🏼‍♀️\n", + "# 🦸🏻 Comprendiendo el Semantic Kernel con Héroes 🦸🏼‍♀️\n", "\n", - "Semantic Kernel ha sido creado para permitir a los desarrolladores integrar Inteligencia Artificial de una forma súper sencilla en sus aplicaciones. Para ello, proporciona un conjunto de características que te van a permitir añadir modelos, prompts, funciones nativas y memorias sin tener conocimientos profundos de IA 🥲. Es por ello que se dice que Semantic Kernel simula el cerebro 🧠 de tu aplicación.\n", + "Semantic Kernel ha sido creado para permitir a los desarrolladores integrar Inteligencia Artificial en sus aplicaciones de manera fluida. Para lograr esto, proporciona un conjunto de características que te permitirán añadir modelos, prompts, funciones nativas y memorias sin requerir un conocimiento profundo de IA 🥲. Por eso se dice que Semantic Kernel simula el cerebro 🧠 de tu aplicación.\n", "\n", "
\n", " \n", @@ -17,18 +17,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Crear un servicio de Azure Open AI 🤖 y despliegues\n", + "## (Opcional) - Creando un Servicio Azure Open AI 🤖 y Despliegues\n", "\n", - "Antes de empezar a jugar 🛝 con Semantic Kernel necesitar tener algún servicio de los que soporta creado. A día de hoy son: [Azure Open AI](https://azure.microsoft.com/es-es/products/ai-services/openai-service), [Open AI](https://openai.com/) o [Hugging Face](https://huggingface.co/)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "En este ejemplo, voy a utilizar Azure Open AI.\n", + "Antes de sumergirnos en Semantic Kernel 🛝, necesitarás tener configurado uno de los servicios soportados. Actualmente, puedes elegir entre las siguientes opciones: [Azure Open AI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), [Open AI](https://openai.com/), o [Hugging Face](https://huggingface.co/).\n", + "\n", + "En este ejemplo, voy a usar Azure Open AI.\n", "\n", - "Por lo que, a través de Azure CLI necesito iniciar sesión:" + "Por lo tanto, a través de Azure CLI, necesito iniciar sesión:\n" ] }, { @@ -55,7 +50,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Si lo necesitas, porque tienes muchos tenants y suscripciones bajo tu cuenta, puedes seleccionar la que te interese (o tenga acceso a Azure Open AI 😊) a través del siguiente comando:" + "Si lo necesitas, porque tienes muchas suscripciones en tu cuenta, puedes seleccionar la que te interesa (o la que tiene acceso a Azure Open AI 😊) a través del siguiente comando:\n" ] }, { @@ -81,7 +76,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Ahora, para poder crear lo que necesitas para este notebook, establece las siguiente variables con los valores de tu preferencia:" + "Ahora, para poder crear lo que necesitas para este cuaderno, establece las siguientes variables con tus valores preferidos:\n" ] }, { @@ -109,7 +104,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Con ellas, ya puedes crear el grupo de recursos:" + "Con ellos, ahora puedes crear el grupo de recursos:\n" ] }, { @@ -137,7 +132,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Un recurso de Azure Open AI:" + "Un recurso de Azure Open AI:\n" ] }, { @@ -169,7 +164,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Y por último, necesitas un despliegue de alguno de los modelos que tengas disponible. En este ejemplo voy a utilizar gpt-4:" + "Y finalmente, necesitas un despliegue de cualquiera de los modelos que tienes disponibles. En este ejemplo, voy a usar gpt-4:" ] }, { @@ -203,7 +198,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "El parámetro **sku-capacity** es el que nos permitirá especificar cuántos tokens por minuto podemos mandarle a este modelo. Para poder ver cómo está el uso de tu cuota puedes utilizar este otro comando:" + "El parámetro **sku-capacity** nos permite especificar cuántos tokens por minuto podemos enviar a este modelo. Para ver cómo se está utilizando tu cuota, puedes usar este otro comando:\n" ] }, { @@ -230,7 +225,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Load enviroment variables with your Azure Open AI endpoint and key" + "Carga las variables de entorno con tu endpoint y clave de Azure Open AI:" ] }, { @@ -269,7 +264,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Cómo empezar con Semantic Kernel" + "## Cómo empezar con Semantic Kernel\n" ] }, { @@ -304,7 +299,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Con ella ya puedes instanciar el cerebro de tu aplicación a través de **KernelBuilder**. Este tiene un montón de conectores a los modelos y otras cosas, pero por ahora vamos a empezar con lo básico:" + "Con ello, ahora puedes instanciar el cerebro de tu aplicación a través de **KernelBuilder**. Tiene muchos conectores a los modelos y otras cosas, pero por ahora, comencemos con lo básico:\n" ] }, { @@ -324,18 +319,16 @@ "outputs": [], "source": [ "using Microsoft.SemanticKernel;\n", - "using Microsoft.SemanticKernel.Orchestration;\n", - "using System.IO;\n", "\n", - "//Create Kernel builder\n", - "var builder = new KernelBuilder();" + "// Create a Builder\n", + "var builder = Kernel.CreateBuilder();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Dependiendo del tipo de tarea que quieras hacer puede utilizar diferentes métodos con el prefijo **With**. Por ahora, vamos a utilizar alguno de los modelos de tipo **completion** o completado." + "Dependiendo del tipo de tarea que quieras realizar, puedes usar diferentes métodos con el prefijo **With**. Por ahora, vamos a usar algunos de los modelos de tipo **completion** o completado.\n" ] }, { @@ -354,16 +347,44 @@ }, "outputs": [], "source": [ - "builder\n", - ".WithAzureOpenAIChatCompletionService(\"gpt-4\", Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_ENDPOINT\"), Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_KEY\"));\n", - "//.WithOpenAIChatCompletionService(\"gpt-4\",(await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\")).GetClearTextPassword());" + "// OpenAI keys\n", + "var modelId = \"gpt-4\";\n", + "var apiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\")).GetClearTextPassword();\n", + "\n", + "// Create a chat completion service\n", + "builder.AddOpenAIChatCompletion(modelId, apiKey);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Azure OpenAI keys\n", + "var deploymentName = \"gpt-4\";\n", + "var endpoint = Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_ENDPOINT\");\n", + "var apiKey = Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_KEY\");\n", + "\n", + "// Create a chat completion service\n", + "builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Con la configuración hecha, lo único que queda es generar el kernel con todo lo establecido:" + "Con la configuración realizada, lo único que queda es generar el kernel con todo configurado:\n" ] }, { @@ -389,9 +410,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Los plugins\n", + "## Uso de plugins de Semantic Kernel\n", "\n", - "Los plugins son el core de Semantic Kernel. Con ellos encapsulas las capacidades de forma que estas puedan ser reutilizables, mantenibles y planificables (más adelante lo entenderás 🙃). Hay dos tipos: aquellos que consisten en plantillas de prompts llamadas **Semantic Functions** y funciones nativas del lenguaje programación elegido llamadas **Native Functions**.\n", + "Los plugins son el núcleo de Semantic Kernel. Con ellos, encapsulas capacidades para que sean reutilizables, mantenibles y planificables (lo entenderás más tarde 🙃). Hay dos tipos: aquellos que consisten en plantillas de indicaciones llamadas **Semantic Functions** y funciones nativas del lenguaje de programación elegido llamadas **Native Functions**.\n", "\n", "
\n", " \n", @@ -402,9 +423,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Semantic Functions\n", + "## Funciones Semánticas\n", "\n", - "Cuando hablas con los modelos de inteligencia artificial debes hacerlo con lo que se conoce como *prompt* este puede ser desde una simple frase a algo más elaborado que nos permite que el modelo conozca no solamente lo que queremos sino el cómo lo queremos. Si echas un vistazo a la documentación oficial define este tipo de funciones como la boca 👄 y los oidos 👂🏻 de tu cerebro 🧠.\n", + "Cuando hablas con modelos de inteligencia artificial, debes hacerlo con lo que se conoce como un *prompt*. Esto puede variar desde una simple frase hasta algo más elaborado, permitiendo que el modelo comprenda no solo lo que queremos sino también cómo lo queremos. Si echas un vistazo a la documentación oficial, define este tipo de función como la boca 👄 y los oídos 👂🏻 de tu cerebro 🧠. 🤖🌐\n", "\n", "
\n", " \n", @@ -415,12 +436,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Como parte de este repo tienes una carpeta llamada **SemanticFunctions** que tiene diferentes funciones de este tipo:\n", + "Como parte de este repositorio, tienes una carpeta llamada **SemanticFunctions** que tiene diferentes funciones de este tipo:\n", "\n", - "- **FunPlugin**: Nos permite pedirle al modelo que haga bromas sobre héroes con unas determinadas condiciones, a trabés de la función **Joke**.\n", - "- **WritePlugin**: Para que veas que dentro de un plugin puedes tener diferentes funciones, en este directorio tenemos dos relacionadas con el arte de escribir: la primera de ellas, **OOF**, nos permite generar el mensaje de \"Fuera de la oficina\" 🏢📧 para super héroes y la segunda **StoryGen** nos ayudará a crear historias, también de super héroes 🦸🏻‍♂️🦸🏻‍♀️.\n", + "- **FunPlugin**: Esto nos permite pedirle al modelo que haga bromas sobre héroes bajo ciertas condiciones, a través de la función **Joke**.\n", + "- **WritePlugin**: Para mostrarte que dentro de un plugin puedes tener diferentes funciones, en este directorio tenemos dos relacionadas con el arte de escribir: la primera, **OOF**, nos permite generar el mensaje \"Fuera de la oficina\" 🏢📧 para superhéroes y la segunda **StoryGen** nos ayudará a crear historias, también sobre superhéroes 🦸🏻‍♂️🦸🏻‍♀️.\n", "\n", - "Para que nuestro kernel sepa que estos plugins están disponibles necesitas primero obtener el path del directorio:" + "Para que nuestro kernel sepa que estos plugins están disponibles, primero necesitas obtener la ruta del directorio:\n" ] }, { @@ -439,14 +460,16 @@ }, "outputs": [], "source": [ - "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\");" + "using System.IO;\n", + "\n", + "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"FunPlugIn\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Y después empezar a cargar los plugins que quieras:" + "Y luego comienza a cargar los plugins que deseas:\n" ] }, { @@ -466,14 +489,14 @@ "outputs": [], "source": [ "// Load the FunPlugin from the Plugins Directory\n", - "var funPluginFunctions = kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"FunPlugin\");" + "var funPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectory);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Para poder invocar una función de este tipo puedes hacerlo de la siguiente manera:" + "Para poder invocar una función de este tipo, puedes hacerlo de la siguiente manera:\n" ] }, { @@ -492,71 +515,84 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(\"Cuentame un chiste\", funPluginFunctions[\"Joke\"]);" + "var joke = new KernelArguments() { [\"input\"] = \"tell me a joke\" };\n", + "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], joke);" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Como ves, tan solo utilizando **kernel.RunAsync** y pasando como parámetros mi petición y cuál es la función, en este caso **Joke**, dentro del plugin, en este caso **FunPlugin**, que quiero utilizar.\n", + "Como puedes ver, solo usando **kernel.RunAsync** y pasando mi solicitud como parámetros y qué función, en este caso **Joke**, dentro del plugin, en este caso **FunPlugin**, quiero usar.\n", "\n", "Cada una de estas funciones consta de dos archivos:\n", "\n", - "- **skprompt.txt** es el archivo donde se define el prompt a mandar al modelo en un formato plantilla, de tal forma que puede recibir parámetros y hacerlos más reusables.\n", + "- **skprompt.txt** es el archivo donde se define el prompt para enviar al modelo en un formato de plantilla, de modo que pueda recibir parámetros y hacerlos más reutilizables.\n", "\n", - "```\n", - "WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE SUBJECT BELOW\n", "\n", - "JOKE MUST BE:\n", - "- IN SPANISH\n", + " ```\n", + " WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE SUBJECT BELOW\n", "\n", - "BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n", + " JOKE MUST BE:\n", + " - IN ENGLISH\n", "\n", - "Incorporate the hero if provided: {{$hero}}\n", - "+++++\n", + " BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n", "\n", - "{{$input}}\n", - "+++++\n", - "```\n", - "- **config.json**, el cual nos permite indicar el número de tokens máximo permitido para esta llamada (**max_tokens**), la temperatura para controlar la aleatoriedad de las respuestas (**temperature**), lo cual significa que más cerca del 1 serán más aleatorias y más cerca del cero más determinadas y centradas en la respuesta más probable, **top_p** se utiliza para controlar la diversidad de las respuestas, donde un valor de 0.0 significa que solo se considerarán las respuestas más probables y 1 donde se considerarán todas las respuestas posibles y **presence_penaltty** y **frecuency_penalty** para ajustar la penalización por las presencia y frecuencia de los tokens en las respuesta generadas. Por otro lado, si el archivo skprompt.txt recibe parámetros se deben definir en este archivo también en el array **parameters** del objeto **input**\n", + " Incorporate the hero if provided: {{$hero}}\n", + " +++++\n", "\n", - "```javascript\n", - "{\n", - " \"schema\": 1,\n", - " \"description\": \"Generate a funny joke about heroes\",\n", - " \"models\": [\n", - " {\n", - " \"max_tokens\": 150,\n", - " \"temperature\": 0.9,\n", - " \"top_p\": 0.5,\n", - " \"presence_penalty\": 0.2,\n", - " \"frequency_penalty\": 0.3\n", - " }\n", - " ],\n", - " \"input\": {\n", - " \"parameters\": [\n", - " {\n", - " \"name\": \"input\",\n", - " \"description\": \"Joke subject\",\n", - " \"defaultValue\": \"\"\n", - " },\n", + " {{$input}}\n", + " +++++\n", + " ```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- **config.json**, which allows us to indicate the maximum number of tokens allowed for this call (**max_tokens**), the temperature to control the randomness of the responses (**temperature**), which means that closer to 1 they will be more random and closer to zero more determined and focused on the most likely response, **top_p** is used to control the diversity of the responses, where a value of 0.0 means that only the most likely responses will be considered and 1 where all possible responses will be considered and **presence_penalty** and **frequency_penalty** to adjust the penalty for the presence and frequency of the tokens in the generated responses. On the other hand, if the skprompt.txt file receives parameters, they must also be defined in this file in the **parameters** array of the **input** object.\n", + "\n", + " ```javascript\n", + " {\n", + " \"schema\": 1,\n", + " \"description\": \"Generate a funny joke about heroes\",\n", + " \"models\": [\n", " {\n", - " \"name\": \"hero\",\n", - " \"description\": \"Give a hint about the hero you want to joke about\",\n", - " \"defaultValue\": \"\"\n", + " \"max_tokens\": 150,\n", + " \"temperature\": 0.9,\n", + " \"top_p\": 0.5,\n", + " \"presence_penalty\": 0.2,\n", + " \"frequency_penalty\": 0.3\n", " }\n", - " ]\n", + " ],\n", + " \"input\": {\n", + " \"parameters\": [\n", + " {\n", + " \"name\": \"input\",\n", + " \"description\": \"Joke subject\",\n", + " \"defaultValue\": \"\"\n", + " },\n", + " {\n", + " \"name\": \"hero\",\n", + " \"description\": \"Give a hint about the hero you want to joke about\",\n", + " \"defaultValue\": \"\"\n", + " }\n", + " ]\n", + " }\n", " }\n", - "}\n", - "```\n" + " ```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Para ver el resultado generado de llamar a esta función Joke puedes recuperarlo de la siguiente manera:" + "Para ver el resultado generado al llamar a esta función Joke, puedes obtenerlo de la siguiente manera:\n" ] }, { @@ -582,7 +618,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Como puedes ver, en esta ejecución no le hemos pasado más que el parámetro input, pero no el héroe del cual queríamos generar este chiste. Para poder mandarle más de un parámetro necesitas crear un objeto del tipo **ContextVariables**:" + "As you can see, in this execution we have only passed the input parameter, but not the hero about whom we wanted to generate this joke. To be able to send more than one parameter you need to create an object of the **ContextVariables** type:\n" ] }, { @@ -601,8 +637,8 @@ }, "outputs": [], "source": [ - "var variables = new ContextVariables{\n", - " [\"input\"] = \"Cuentame un chiste sobre Navidad\",\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Tell me a Christmas joke\",\n", " [\"hero\"] = \"Ironman\"\n", "};" ] @@ -611,7 +647,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Para poder utilizar estos dos valores como parte de la llamara simplemente hay que ponerlo como primer argumento." + "To be able to use these two values as part of the call, simply put it as the first argument.\n" ] }, { @@ -630,14 +666,14 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(variables, funPluginFunctions[\"Joke\"]);" + "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], variables);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Ahora comprueba si el chiste es del héroe especificado como parámetro." + "Now check if the joke is about the hero specified as a parameter.\n" ] }, { @@ -663,7 +699,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "De la misma forma, podemos utilizar las funciones incluídas en **WriterPlugin**:" + "In the same way, we can use the functions included in **WriterPlugin**:\n" ] }, { @@ -683,14 +719,16 @@ "outputs": [], "source": [ "// Load the WriterPlugin from the Plugins Directory\n", - "var writerPluginFunctions = kernel.ImportSemanticFunctionsFromDirectory(pluginsDirectory, \"WriterPlugin\");" + "var pluginsDirectoryWriter = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"WriterPlugin\");\n", + "\n", + "var writerPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectoryWriter);\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Uno que genera historias:" + "One that generates stories:\n" ] }, { @@ -709,7 +747,12 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(\"Cuentame una historia sobre las navidades\", writerPluginFunctions[\"StoryGen\"]);\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Tell me a Christmas Story\",\n", + " [\"hero\"] = \"Ironman\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", "Console.WriteLine(result);" ] }, @@ -717,7 +760,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "O incluso para crear mensajes para cuando los héroes 🦸🏻‍♀️ están de vacaciones ✈️🚢🌴:" + "Or even to create messages for when the heroes 🦸🏻‍♀️ are on vacation ✈️🚢🌴:\n" ] }, { @@ -736,7 +779,12 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(\"Crea un out of office para los días de Navidades\", writerPluginFunctions[\"OOF\"]);\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Create an OOF for Christmas\",\n", + " [\"hero\"] = \"Hulk\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOF\"], variables);\n", "Console.WriteLine(result.GetValue());" ] }, @@ -746,7 +794,7 @@ "source": [ "## Native Functions\n", "\n", - "Si bien las funciones semánticas nos permiten definir y reutilizar prompts, **con las funciones nativas puedes hacer que semantic kernel pueda llamar a funciones escritas en C# o Python**, para tareas que se escapan propiamente de una llamada a través de un prompt.\n", + "While semantic functions allow us to define and reuse prompts, **with native functions you can make the semantic kernel call functions written in C# or Python**, for tasks that go beyond a call through a prompt.\n", "\n", "
\n", " \n", @@ -757,26 +805,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### ¿Por qué necesito funciones nativas en este tipo de aplicaciones?\n", + "### Why do I need native functions in these types of applications?\n", "\n", - "Los LLM, o Large language models, son excelentes para generar texto, pero hay varias tareas que no pueden realizar por sí solos. Éstas incluyen, entre otras:\n", + "Large language models (LLMs) are excellent for generating text, but there are several tasks they cannot perform on their own. These include, among others:\n", "\n", - "- Recuperar datos de fuentes de datos externas\n", - "- Saber qué hora es\n", - "- Realizar operaciones matemáticas complejas\n", - "- Completar tareas en el mundo real\n", - "- Memorizar y recordar información\n", + "- Retrieving data from external data sources\n", + "- Knowing what time it is\n", + "- Performing complex mathematical operations\n", + "- Completing tasks in the real world\n", + "- Memorizing and remembering information\n", "\n", - "Para estos escenarios, y muchos otros, las funciones nativas son de gran utilidad 👍🏻" + "For these scenarios, and many others, native functions are very useful 👍🏻\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Para esto ejemplo, voy a usar una API llamada **SuperHero API**, la cual necesita una API key. Puedes conseguir la misma en su página web: [https://superheroapi.com/](https://superheroapi.com/)\n", + "For this example, I'm going to use an API called **SuperHero API**, which requires an API key. You can get it from their website: [https://superheroapi.com/](https://superheroapi.com/)\n", "\n", - "Una vez la tengas, pasasela al prompt que te aparece con la siguiente línea:" + "Once you have it, pass it to the prompt that appears with the following line:\n" ] }, { @@ -795,14 +843,16 @@ }, "outputs": [], "source": [ - "var superHeroApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\");" + "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Ahora, para cargar una función nativa, debemos hacerlo de la siguiente manera:" + "Now, to load a native function, we must add this before we build the Kernel.\n", + "\n", + "Let's create a new Super Hero Info class and add it as a Plugin." ] }, { @@ -821,18 +871,18 @@ }, "outputs": [], "source": [ - "#load \"NativeFunctions/GetHeroInfo.cs\"\n", - "\n", - "var infoPlugin = kernel.ImportFunctions(new Info(superHeroApiKey.GetClearTextPassword()), \"InfoPlugin\");\n", + "#load \"NativeFunctions/HeroInfo.cs\"\n", "\n", - "var result = await kernel.RunAsync(\"catwoman\", infoPlugin[\"GetAlterEgo\"]);" + "var heroInfo = new HeroInfo(superHeroApiKey);\n", + "builder.Plugins.AddFromObject(heroInfo, \"HeroInfo\");\n", + "Kernel kernel = builder.Build();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "En este repo hay otro directorio llamado **NativeFunctions** donde puedes encontrar una clase llamada **GetHeroInfo.cs** en ella hay una función decorada con el atributo **SKFunction** el cual nos permite indicarle a Semantic Kernel que es una función nativa y, a través de la propiedad **Description**, también darle información sobre cuál es el objetivo de esta funcion. En este caso lo que nos permite este método es recuperar el alter ego del super héroe que le pasemos como parámetro, en este ejemplo el de Catwoman. Si echamos un vistazo al resultado podrás comprobar que el mismo es el esperado:" + "The builder now can interact with the local function. Let's make a call to get the alter ego of a super hero." ] }, { @@ -851,7 +901,20 @@ }, "outputs": [], "source": [ - "Console.WriteLine(result.GetValue());" + "var kernelArgs = new KernelArguments()\n", + "{\n", + " [\"input\"] = \"Ironman\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", + "Console.WriteLine(result);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this repo, there is another directory called **NativeFunctions** where you can find a class called **HeroInfo.cs**. In it, there is a function decorated with the **KernelFunction** attribute, which allows us to indicate to the Semantic Kernel that it is a native function and, through the **Description** property, also give it information about what the purpose of this function is. In this case, what this method allows us to do is retrieve the alter ego of the superhero that we pass as a parameter, in this example that of Ironman. \n" ] }, { @@ -860,9 +923,9 @@ "source": [ "## Planner\n", "\n", - "Hasta ahora, todos los plugins que has ido viendo los has ejecutado intencionadamente. Es decir, nadie los ha escogido por tí y tú los puedes ejecutar en base a las necesidades que tengas. Sin embargo, esta es la forma más *estática* de interactuar con Semantic Kernel. Exíste otra opción llamada **Planer** que te va a dejar boquiabierto 😮\n", + "So far, all the plugins you have seen have been executed intentionally. That is, no one has chosen them for you and you can run them based on your needs. However, this is the most *static* way to interact with Semantic Kernel. There is another option called **Planner** that will leave you astounded 😮\n", "\n", - "Planner es una función que toma la petición de un usuario y devuelve un plan sobre cómo llevar a cabo la solicitud. Para ello, utiliza la IA para combinar los plugins registrados en el núcleo y recombinarlos en una serie de pasos que completen un objetivo.\n", + "Planner is a function that takes a user's request and returns a plan on how to carry out the request. To do this, it uses AI to combine the plugins registered in the core and recombine them into a series of steps that complete a goal.\n", "\n", "
\n", " \n", @@ -873,9 +936,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Para verlo en acción vamos a utilizar los plugins que ya conoces.\n", + "To see it in action, we are going to use the plugins that you already know.\n", "\n", - "Lo primero que necesitas es instanciar un planner:" + "The first thing you need is to add the nuget reference to the Planner Handlebars.\n", + "\n", + "To learn more about this NuGet package, you can visit [here](https://www.nuget.org/packages/Microsoft.SemanticKernel.Planners.Handlebars/1.5.0-preview#show-readme-container).\n", + "\n" ] }, { @@ -894,19 +960,14 @@ }, "outputs": [], "source": [ - "using Microsoft.SemanticKernel.Planners;\n", - "\n", - "// Create planner\n", - "var planner = new SequentialPlanner(kernel);" + "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Hay de diferentes tipos como puedes ver [aquí](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). En este ejemplo vamos a utilizar el que ejecuta las tareas de forma secuencial.\n", - "\n", - "Como ya tienes todos los plugins cargados en tu instancia del kernel, podemos preguntarle algo como esto:" + "Now we are ready to create a planner." ] }, { @@ -925,20 +986,19 @@ }, "outputs": [], "source": [ - "using System.Text.Json;\n", + "using Microsoft.SemanticKernel.Planning.Handlebars;\n", "\n", - "var ask = \"Me gustaría que me contaras un chiste sobre Batman, y con el chiste que hicieras un out of office con el chiste.\";\n", - "var plan = await planner.CreatePlanAsync(ask);\n", - "\n", - "Console.WriteLine(\"Plan:\\n\");\n", - "Console.WriteLine(JsonSerializer.Serialize(plan, new JsonSerializerOptions { WriteIndented = true }));" + "#pragma warning disable SKEXP0060\n", + "var planner = new HandlebarsPlanner();\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Como puedes ver el planificador sabe sobre mis plugins gracias a la descripción que incluí como parte de su implementación." + "There are different types as you can see [here](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). In this example, we are going to use the one that executes tasks sequentially.\n", + "\n", + "Since you already have all the plugins loaded in your kernel instance, we can ask it something like this:\n" ] }, { @@ -957,19 +1017,23 @@ }, "outputs": [], "source": [ - "var result = await kernel.RunAsync(plan);\n", + "using System.Text.Json;\n", "\n", - "Console.WriteLine(\"Plan result:\\n\");\n", - "Console.WriteLine(result.GetValue());" + "var ask = \"I would like you to tell me a joke about Batman, and with that joke, create an out-of-office message using the joke.\";\n", + "#pragma warning disable SKEXP0060\n", + "var originalPlan = await planner.CreatePlanAsync(kernel, ask);\n", + "\n", + "Console.WriteLine(\"Original plan:\\n\");\n", + "Console.WriteLine(originalPlan);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## LABS\n", + "As you can see, the planner knows about the plugins thanks to the description that I included as part of their implementation.\n", "\n", - "El kernel ya tiene cargado los plugins, y la funcion, veamos si puede resolver un ejemplo mas complejo:" + "Time to run the plan and get an OOF for **Batman** that includes a **bad joke**.\n" ] }, { @@ -988,20 +1052,21 @@ }, "outputs": [], "source": [ - "using System.Text.Json;\n", - "\n", - "var ask_complex = \"Me gustaría que avveriguaras el alter ego de Batman, y que hicieras un out of office para Batman firmando con el alter ego del mismo.\";\n", - "var plan_complex = await planner.CreatePlanAsync(ask_complex);\n", + "// executing the plan\n", + "#pragma warning disable SKEXP0060\n", + "var originalPlanResult = await originalPlan.InvokeAsync(kernel, new KernelArguments());\n", "\n", - "Console.WriteLine(\"Plan:\\n\");\n", - "Console.WriteLine(JsonSerializer.Serialize(plan_complex, new JsonSerializerOptions { WriteIndented = true }));" + "Console.WriteLine(\"Original Plan results:\\n\");\n", + "Console.WriteLine(originalPlanResult.ToString());" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Ejecutemos el plan y veamos su output:" + "### Advanced Planner Labs\n", + "\n", + "The kernel already has the plugins loaded, and the function, let's see if it can solve a more complex example:\n" ] }, { @@ -1020,33 +1085,20 @@ }, "outputs": [], "source": [ - "var result_complex = await kernel.RunAsync(plan_complex);\n", + "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, signing it with his alter ego.\";\n", "\n", - "Console.WriteLine(\"Plan result:\\n\");\n", - "Console.WriteLine(result_complex.GetValue());" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Kernel Memory\n", + "#pragma warning disable SKEXP0060\n", + "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", "\n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Para este ejemplo voy a utilizar **Open AI** en lugar de Azure Open AI, por lo que necesitas guardar [una API Key](https://platform.openai.com/account/api-keys) de este en la siguiente variable:" + "Console.WriteLine(\"Plan:\\n\");\n", + "Console.WriteLine(plan_complex);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Para poder utilizar Kernel Memory necesitas añadir su librería de nuget, además de importa la clase que he generado en el directorio **KernelMemory**." + "Let's execute the plan and see its output:\n" ] }, { @@ -1065,45 +1117,29 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.KernelMemory.Core, 0.11.231120.6-preview\"\n", + "#pragma warning disable SKEXP0060\n", + "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", "\n", - "#!import \"KernelMemory/Memories.cs\"" + "Console.WriteLine(\"Complex Plan results:\\n\");\n", + "Console.WriteLine(complexPlanResult.ToString());" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Lo primero que voy a hacer es importar a Kernel Memory unos cuantos *recuerdos* (textos) y *documentos*." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "var openApiKey = await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Open AI key\");\n", + "## Kernel Memory\n", "\n", - "MemoryKernel.Init(openApiKey.GetClearTextPassword());" + "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Como puedes ver en el output, este ya se encarga de generar los embeddings de las frases/documentos que le pasamos para que el modelo de GPT-4 pueda generar la respuesta.\n", - "Ahora que ya tenemos algo de contenido sobre el que preguntar, vamos a cargar esta clase como un plugin más." + "To be able to use Kernel Memory, you need to add its nuget library, in addition to importing the class that I have generated in the **KernelMemory** directory.\n", + "\n", + "To learn more about the Kernel Memory library, you can visit the [NuGet package page](https://www.nuget.org/packages/Microsoft.SemanticKernel.Plugins.Memory/1.5.0-alpha#show-readme-container).\n" ] }, { @@ -1122,14 +1158,19 @@ }, "outputs": [], "source": [ - "var memoriesPlugin = kernel.ImportFunctions(new MemoryKernel(), \"MemoriesPlugin\");" + "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", + "#r \"nuget: System.Linq.Async, 6.0.1\"\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Y ahora preguntemos sobre el contenido:" + "In order to use memory, we need to instantiate the Memory Plugin with a Memory Storage and an Embedding backend. In this example, we make use of the VolatileMemoryStore which can be thought of as a temporary in-memory storage (not to be confused with Semantic Memory).\n", + "\n", + "This memory is not written to disk and is only available during the app session.\n", + "\n", + "When developing your app you will have the option to plug in persistent storage like Azure Cosmos Db, PostgreSQL, SQLite, etc. Semantic Memory allows also to index external data sources, without duplicating all the information, more on that later." ] }, { @@ -1148,13 +1189,33 @@ }, "outputs": [], "source": [ - "var planner = new SequentialPlanner(kernel);\n", + "using Microsoft.SemanticKernel.Memory;\n", + "using Microsoft.SemanticKernel.Connectors.OpenAI;\n", "\n", - "var plan = await planner.CreatePlanAsync(\"¿Quién es el héroe favorito de Bruno?\");\n", + "// create the memory builder\n", + "#pragma warning disable SKEXP0003, SKEXP0011, SKEXP0052\n", + "var memoryBuilder = new MemoryBuilder();\n", "\n", - "var result = await kernel.RunAsync(plan);\n", + "// Using OpenAI\n", + "memoryBuilder.WithOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey);\n", "\n", - "Console.WriteLine(result.GetValue());" + "// Using Azure OpenAI \n", + "// memoryBuilder.WithAzureOpenAITextEmbeddingGeneration(\n", + "// AzureOpenAI.EmbeddingsModel,\n", + "// AzureOpenAI.Endpoint,\n", + "// AzureOpenAI.ApiKey,\n", + "// \"text-embedding-ada-002\");\n", + "\n", + "memoryBuilder.WithMemoryStore(new VolatileMemoryStore());\n", + "var memory = memoryBuilder.Build();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's create some initial memories \"Fan Facts\". We can add memories to our VolatileMemoryStore by using SaveInformationAsync:\n", + "\n" ] }, { @@ -1173,20 +1234,21 @@ }, "outputs": [], "source": [ - "var planner = new SequentialPlanner(kernel);\n", + "// add fan facts to the collection\n", + "const string MemoryCollectionName = \"fanFacts\";\n", "\n", - "var plan = await planner.CreatePlanAsync(\"¿Cuál fue la última película que vio Gisela?\");\n", - "\n", - "var result = await kernel.RunAsync(plan);\n", - "\n", - "Console.WriteLine(result.GetValue());" + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info1\", text: \"Gisela's favourite super hero is Batman\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info2\", text: \"The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info3\", text: \"Bruno's favourite super hero is Invincible\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"The last super hero movie watched by Bruno was Aquaman II\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "También podemos preguntarle por el PDF que incluí:" + "And now we can test and search in the memory:" ] }, { @@ -1205,13 +1267,19 @@ }, "outputs": [], "source": [ - "var planner = new SequentialPlanner(kernel);\n", - "\n", - "var plan = await planner.CreatePlanAsync(\"¿Qué incluye este volumen de batman?\");\n", - "\n", - "var result = await kernel.RunAsync(plan);\n", + "var questions = new[]\n", + "{\n", + " \"what is Bruno's favourite super hero?\",\n", + " \"what was the last movie watched by Gisela?\",\n", + " \"Which is the prefered super hero for Gisela?\",\n", + " \"Did Bruno watched a super hero movie in the past, which was the last one?\"\n", + "};\n", "\n", - "Console.WriteLine(result.GetValue());" + "foreach (var q in questions)\n", + "{\n", + " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", + "}\n" ] } ], From 6d6a806d9090534ca3577f3cd37b1991555b3a21 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 5 Mar 2024 14:59:18 -0300 Subject: [PATCH 13/25] update Spanish notebook with translations --- notebook-es.ipynb | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/notebook-es.ipynb b/notebook-es.ipynb index 8864be3..9054e15 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -618,7 +618,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "As you can see, in this execution we have only passed the input parameter, but not the hero about whom we wanted to generate this joke. To be able to send more than one parameter you need to create an object of the **ContextVariables** type:\n" + "Como podemos ver, en esta ejecución, solo hemos pasado el primer parámetro: INPUT, pero no hemos pasado el parámetro HERO. No hemos especificado el héroe que queremos utilizar para generar el chiste. Para poder enviar más de un parámetro necesitas crear un objeto del tipo **ContextVariables**:" ] }, { @@ -647,7 +647,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To be able to use these two values as part of the call, simply put it as the first argument.\n" + "Para poder usar estos dos valores como parte de la llamada, simplemente colócalos como el primer argumento.\n" ] }, { @@ -673,7 +673,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now check if the joke is about the hero specified as a parameter.\n" + "Ahora verifica si el chiste es sobre el héroe especificado como parámetro.\n" ] }, { @@ -699,7 +699,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In the same way, we can use the functions included in **WriterPlugin**:\n" + "De la misma manera, podemos usar las funciones incluidas en **WriterPlugin**:\n" ] }, { @@ -728,7 +728,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "One that generates stories:\n" + "Una que genera historias:\n" ] }, { @@ -760,7 +760,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Or even to create messages for when the heroes 🦸🏻‍♀️ are on vacation ✈️🚢🌴:\n" + "O incluso para crear mensajes para cuando los héroes 🦸🏻‍♀️ están de vacaciones ✈️🚢🌴:\n" ] }, { @@ -792,9 +792,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Native Functions\n", + "## Funciones Nativas\n", "\n", - "While semantic functions allow us to define and reuse prompts, **with native functions you can make the semantic kernel call functions written in C# or Python**, for tasks that go beyond a call through a prompt.\n", + "Mientras que las funciones semánticas nos permiten definir y reutilizar prompts, **con las funciones nativas puedes hacer que el kernel semántico llame a funciones escritas en C# o Python**, para tareas que van más allá de una llamada a través de un prompt.\n", "\n", "
\n", " \n", @@ -805,26 +805,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Why do I need native functions in these types of applications?\n", + "### ¿Por qué necesito funciones nativas en este tipo de aplicaciones?\n", "\n", - "Large language models (LLMs) are excellent for generating text, but there are several tasks they cannot perform on their own. These include, among others:\n", + "Los modelos de lenguaje grandes (LLMs) son excelentes para generar texto, pero hay varias tareas que no pueden realizar por sí mismos. Estos incluyen, entre otros:\n", "\n", - "- Retrieving data from external data sources\n", - "- Knowing what time it is\n", - "- Performing complex mathematical operations\n", - "- Completing tasks in the real world\n", - "- Memorizing and remembering information\n", + "- Recuperar datos de fuentes de datos externas\n", + "- Saber qué hora es\n", + "- Realizar operaciones matemáticas complejas\n", + "- Completar tareas en el mundo real\n", + "- Memorizar y recordar información\n", "\n", - "For these scenarios, and many others, native functions are very useful 👍🏻\n" + "Para estos escenarios, y muchos otros, las funciones nativas son muy útiles 👍🏻\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "For this example, I'm going to use an API called **SuperHero API**, which requires an API key. You can get it from their website: [https://superheroapi.com/](https://superheroapi.com/)\n", + "Para este ejemplo, voy a utilizar una API llamada **SuperHero API**, que requiere una clave de API. Puedes obtenerla de su sitio web: [https://superheroapi.com/](https://superheroapi.com/)\n", "\n", - "Once you have it, pass it to the prompt that appears with the following line:\n" + "Una vez que la tengas, pásala al prompt que aparece con la siguiente línea:\n" ] }, { @@ -850,9 +850,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, to load a native function, we must add this before we build the Kernel.\n", + "Ahora, para cargar una función nativa, debemos agregar esto antes de construir el Kernel.\n", "\n", - "Let's create a new Super Hero Info class and add it as a Plugin." + "Vamos a crear una nueva clase Super Hero Info y agregarla como un Plugin.\n" ] }, { @@ -882,6 +882,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "El constructor ahora puede interactuar con la función local. Hagamos una llamada para obtener el alter ego de un superhéroe.\n", "The builder now can interact with the local function. Let's make a call to get the alter ego of a super hero." ] }, @@ -914,18 +915,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In this repo, there is another directory called **NativeFunctions** where you can find a class called **HeroInfo.cs**. In it, there is a function decorated with the **KernelFunction** attribute, which allows us to indicate to the Semantic Kernel that it is a native function and, through the **Description** property, also give it information about what the purpose of this function is. In this case, what this method allows us to do is retrieve the alter ego of the superhero that we pass as a parameter, in this example that of Ironman. \n" + "En este repositorio, hay otro directorio llamado **NativeFunctions** donde puedes encontrar una clase llamada **HeroInfo.cs**. En ella, hay una función decorada con el atributo **KernelFunction**, que nos permite indicar al Kernel Semántico que es una función nativa y, a través de la propiedad **Description**, también darle información sobre cuál es el propósito de esta función. En este caso, lo que este método nos permite hacer es recuperar el alter ego del superhéroe que pasamos como parámetro, en este ejemplo el de Ironman.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Planner\n", + "## Planner (Planificador)\n", "\n", - "So far, all the plugins you have seen have been executed intentionally. That is, no one has chosen them for you and you can run them based on your needs. However, this is the most *static* way to interact with Semantic Kernel. There is another option called **Planner** that will leave you astounded 😮\n", + "Hasta ahora, todos los complementos que has visto se han ejecutado intencionalmente. Es decir, nadie los ha elegido por ti y puedes ejecutarlos según tus necesidades. Sin embargo, esta es la forma de interactuar con **Semantic Kernel** más *estática*. Existe otra opción llamada **Planificador** que te dejará asombrado 😮\n", "\n", - "Planner is a function that takes a user's request and returns a plan on how to carry out the request. To do this, it uses AI to combine the plugins registered in the core and recombine them into a series of steps that complete a goal.\n", + "El Planificador es una función que toma la solicitud del usuario y devuelve un plan sobre cómo llevar a cabo dicha solicitud. Para hacerlo, utiliza la inteligencia artificial para combinar los complementos registrados en el núcleo y recombinarlos en una serie de pasos que completan un objetivo.\n", "\n", "
\n", " \n", @@ -936,12 +937,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To see it in action, we are going to use the plugins that you already know.\n", + "Para verlo en acción, vamos a utilizar los complementos que ya conoces.\n", "\n", - "The first thing you need is to add the nuget reference to the Planner Handlebars.\n", + "Lo primero que necesitas es agregar la referencia nuget al **Planner Handlebars**.\n", "\n", - "To learn more about this NuGet package, you can visit [here](https://www.nuget.org/packages/Microsoft.SemanticKernel.Planners.Handlebars/1.5.0-preview#show-readme-container).\n", - "\n" + "Para aprender más sobre este paquete NuGet, puedes visitar [aquí](https://www.nuget.org/packages/Microsoft.SemanticKernel.Planners.Handlebars/1.5.0-preview#show-readme-container).\n" ] }, { From 7f6579e33691797a94f9f3d80882889013c09553 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 5 Mar 2024 15:12:56 -0300 Subject: [PATCH 14/25] notebook translated to Spanish --- notebook-es.ipynb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/notebook-es.ipynb b/notebook-es.ipynb index 9054e15..4c69663 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -967,7 +967,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we are ready to create a planner." + "Ahora estamos listos para crear un planificador.\n" ] }, { @@ -996,9 +996,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There are different types as you can see [here](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). In this example, we are going to use the one that executes tasks sequentially.\n", + "Existen diferentes tipos como puedes ver [aquí](https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=Csharp). En este ejemplo, vamos a utilizar el que ejecuta tareas de forma secuencial.\n", "\n", - "Since you already have all the plugins loaded in your kernel instance, we can ask it something like this:\n" + "Dado que ya tienes todos los complementos cargados en tu instancia de kernel, podemos preguntarle algo como esto:\n" ] }, { @@ -1031,9 +1031,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "As you can see, the planner knows about the plugins thanks to the description that I included as part of their implementation.\n", + "Como puedes ver, el planificador conoce los complementos gracias a la descripción que incluí como parte de su implementación.\n", "\n", - "Time to run the plan and get an OOF for **Batman** that includes a **bad joke**.\n" + "Es hora de ejecutar el plan y obtener un mensaje de fuera de la oficina para **Batman** que incluye un **chiste malo**.\n" ] }, { @@ -1064,9 +1064,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Advanced Planner Labs\n", + "### Ejemplos avanzados con Planner\n", "\n", - "The kernel already has the plugins loaded, and the function, let's see if it can solve a more complex example:\n" + "El kernel ya tiene los plugins cargados, y la función, veamos si puede resolver un ejemplo más complejo:\n" ] }, { @@ -1098,7 +1098,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's execute the plan and see its output:\n" + "Ejecutemos el plan y veamos su salida:\n" ] }, { @@ -1128,7 +1128,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Kernel Memory\n", + "## Memoria del Kernel (Kernel Memory)\n", "\n", "" ] @@ -1137,9 +1137,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To be able to use Kernel Memory, you need to add its nuget library, in addition to importing the class that I have generated in the **KernelMemory** directory.\n", + "Para poder utilizar la Memoria del Kernel, necesitas agregar su biblioteca nuget, además de importar la clase que he generado en el directorio **KernelMemory**.\n", "\n", - "To learn more about the Kernel Memory library, you can visit the [NuGet package page](https://www.nuget.org/packages/Microsoft.SemanticKernel.Plugins.Memory/1.5.0-alpha#show-readme-container).\n" + "Para aprender más sobre la biblioteca de Memoria del Kernel, puedes visitar la [página del paquete NuGet](https://www.nuget.org/packages/Microsoft.SemanticKernel.Plugins.Memory/1.5.0-alpha#show-readme-container).\n" ] }, { From 876cbf4a65ed0791d80e130a9ebb676caba6d670 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 5 Mar 2024 15:52:41 -0300 Subject: [PATCH 15/25] update samples to have spanish code references and sk prompts --- .../FunPlugin/JokeSpa/config.json | 27 ++ .../FunPlugin/JokeSpa/skprompt.txt | 12 + .../WriterPlugin/OOFSpa/config.json | 27 ++ .../WriterPlugin/OOFSpa/skprompt.txt | 16 ++ .../WriterPlugin/StoryGenSpa/config.json | 27 ++ .../WriterPlugin/StoryGenSpa/skprompt.txt | 13 + notebook-es.ipynb | 247 ++++++++++++------ 7 files changed, 291 insertions(+), 78 deletions(-) create mode 100644 SemanticFunctions/FunPlugin/JokeSpa/config.json create mode 100644 SemanticFunctions/FunPlugin/JokeSpa/skprompt.txt create mode 100644 SemanticFunctions/WriterPlugin/OOFSpa/config.json create mode 100644 SemanticFunctions/WriterPlugin/OOFSpa/skprompt.txt create mode 100644 SemanticFunctions/WriterPlugin/StoryGenSpa/config.json create mode 100644 SemanticFunctions/WriterPlugin/StoryGenSpa/skprompt.txt diff --git a/SemanticFunctions/FunPlugin/JokeSpa/config.json b/SemanticFunctions/FunPlugin/JokeSpa/config.json new file mode 100644 index 0000000..64e2753 --- /dev/null +++ b/SemanticFunctions/FunPlugin/JokeSpa/config.json @@ -0,0 +1,27 @@ +{ + "schema": 1, + "description": "Generate a funny joke about heroes", + "models": [ + { + "max_tokens": 150, + "temperature": 0.9, + "top_p": 0.5, + "presence_penalty": 0.2, + "frequency_penalty": 0.3 + } + ], + "input": { + "parameters": [ + { + "name": "input", + "description": "Joke subject", + "defaultValue": "" + }, + { + "name": "hero", + "description": "Give the name of the hero you want to joke about", + "defaultValue": "" + } + ] + } +} \ No newline at end of file diff --git a/SemanticFunctions/FunPlugin/JokeSpa/skprompt.txt b/SemanticFunctions/FunPlugin/JokeSpa/skprompt.txt new file mode 100644 index 0000000..0d6c6fb --- /dev/null +++ b/SemanticFunctions/FunPlugin/JokeSpa/skprompt.txt @@ -0,0 +1,12 @@ +WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE SUBJECT BELOW + +JOKE MUST BE: +- IN SPANISH + +BE CREATIVE AND FUNNY. I WANT TO LAUGH. + +Incorporate the hero if provided: {{$hero}} ++++++ + +{{$input}} ++++++ \ No newline at end of file diff --git a/SemanticFunctions/WriterPlugin/OOFSpa/config.json b/SemanticFunctions/WriterPlugin/OOFSpa/config.json new file mode 100644 index 0000000..e64d878 --- /dev/null +++ b/SemanticFunctions/WriterPlugin/OOFSpa/config.json @@ -0,0 +1,27 @@ +{ + "schema": 1, + "description": "Generate a out of office message for a given hero subject", + "models": [ + { + "max_tokens": 250, + "temperature": 0.3, + "top_p": 0.0, + "presence_penalty": 0.0, + "frequency_penalty": 0.0 + } + ], + "input": { + "parameters": [ + { + "name": "input", + "description": "The reason for being out of office", + "defaultValue": "" + }, + { + "name": "hero", + "description": "hero name", + "defaultValue": "Catwoman" + } + ] + } +} \ No newline at end of file diff --git a/SemanticFunctions/WriterPlugin/OOFSpa/skprompt.txt b/SemanticFunctions/WriterPlugin/OOFSpa/skprompt.txt new file mode 100644 index 0000000..e044e0c --- /dev/null +++ b/SemanticFunctions/WriterPlugin/OOFSpa/skprompt.txt @@ -0,0 +1,16 @@ +WRITE AN OUT OF OFFICE FOR THE HERO BELOW + +THE STORY MUST BE: +- IN SPANISH +- USE EMOJIS AS PART OF THE MESSAGE +- TAKE INTO ACCOUNT THE HERO AND HIS/HER POWERS +- YOU MUST OFFER HELP FROM ANOTHER SUPER HERO IN YOUR ABSENCE +- THE OFF MUST HAVE A GOODBYE + + +The hero is {{$hero}} + ++++++ + +{{$input}} ++++++ \ No newline at end of file diff --git a/SemanticFunctions/WriterPlugin/StoryGenSpa/config.json b/SemanticFunctions/WriterPlugin/StoryGenSpa/config.json new file mode 100644 index 0000000..bcc2d22 --- /dev/null +++ b/SemanticFunctions/WriterPlugin/StoryGenSpa/config.json @@ -0,0 +1,27 @@ +{ + "schema": 1, + "description": "Generate a short story about the hero of your choice.", + "models": [ + { + "max_tokens": 350, + "temperature": 0.1, + "top_p": 0.0, + "presence_penalty": 0.1, + "frequency_penalty": 0.3 + } + ], + "input": { + "parameters": [ + { + "name": "input", + "description": "story subject", + "defaultValue": "" + }, + { + "name": "hero", + "description": "hero name", + "defaultValue": "Hulk" + } + ] + } +} \ No newline at end of file diff --git a/SemanticFunctions/WriterPlugin/StoryGenSpa/skprompt.txt b/SemanticFunctions/WriterPlugin/StoryGenSpa/skprompt.txt new file mode 100644 index 0000000..0de9c60 --- /dev/null +++ b/SemanticFunctions/WriterPlugin/StoryGenSpa/skprompt.txt @@ -0,0 +1,13 @@ +WRITE A SHORT STORY ABOUT THE HERO BELOW + +THE STORY MUST BE: +- IN SPANISH +- USE EMOJIS AS PART OF THE STORY +- THE STORY MUST HAVE A BEGINNING, MIDDLE AND END + +The hero of this story is {{$hero}} + ++++++ + +{{$input}} ++++++ \ No newline at end of file diff --git a/notebook-es.ipynb b/notebook-es.ipynb index 4c69663..a56368d 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -278,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -290,7 +290,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 1.5.0
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" ] @@ -304,7 +314,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -333,7 +343,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -389,7 +399,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -446,7 +456,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -474,7 +484,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -501,7 +511,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -513,22 +523,31 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Claro, aquí tienes un chiste:\n", + "\n", + "¿Por qué Superman nunca pelea contra un chiste malo?\n", + "\n", + "Porque siempre se ríe hasta quedar exhausto.\r\n" + ] + } + ], "source": [ - "var joke = new KernelArguments() { [\"input\"] = \"tell me a joke\" };\n", - "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], joke);" + "var joke = new KernelArguments() { [\"input\"] = \"cuentame un chiste\" };\n", + "var result = await kernel.InvokeAsync(funPluginFunctions[\"JokeSpa\"], joke);\n", + "\n", + "Console.WriteLine(result.GetValue());" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Como puedes ver, solo usando **kernel.RunAsync** y pasando mi solicitud como parámetros y qué función, en este caso **Joke**, dentro del plugin, en este caso **FunPlugin**, quiero usar.\n", + "Como puedes ver, solo usando **kernel.RunAsync** y pasando mi solicitud como parámetros y qué función, en este caso **JokeSpa**, dentro del plugin, en este caso **FunPlugin**, quiero usar.\n", "\n", "Cada una de estas funciones consta de dos archivos:\n", "\n", @@ -539,7 +558,7 @@ " WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE SUBJECT BELOW\n", "\n", " JOKE MUST BE:\n", - " - IN ENGLISH\n", + " - IN SPANISH\n", "\n", " BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n", "\n", @@ -588,32 +607,6 @@ " ```\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Para ver el resultado generado al llamar a esta función Joke, puedes obtenerlo de la siguiente manera:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "Console.WriteLine(result.GetValue());" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -623,7 +616,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -638,7 +631,7 @@ "outputs": [], "source": [ "var variables = new KernelArguments() {\n", - " [\"input\"] = \"Tell me a Christmas joke\",\n", + " [\"input\"] = \"Cuentame un chiste de futbol\",\n", " [\"hero\"] = \"Ironman\"\n", "};" ] @@ -652,7 +645,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -666,7 +659,7 @@ }, "outputs": [], "source": [ - "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], variables);" + "var result = await kernel.InvokeAsync(funPluginFunctions[\"JokeSpa\"], variables);" ] }, { @@ -678,7 +671,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -690,7 +683,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "¿Por qué Ironman no puede jugar al fútbol?\n", + "\n", + "Porque cada vez que recibe el balón, se convierte en un hombre de hierro gol.\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -704,7 +707,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -733,7 +736,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -745,14 +748,30 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Había una vez un héroe llamado Ironman 🦾💪🚀, que era conocido por sus increíbles habilidades de combate y su inteligencia. Sin embargo, pocos sabían que Ironman también tenía una pasión secreta: jugar al tenis 🎾.\n", + "\n", + "Un día ☀️, Ironman jugaba su partido habitual de tenis solo en un antiguo campo de juego 🏞️. De repente, apareció un formidable contrincante: un robot gigante 🤖 de uno de sus archienemigos. El robot había venido a desafiar a Ironman a un partido de tenis. Ironman, sorprendido pero listo para el desafío, aceptó y comenzaron el partido.\n", + "\n", + "En el medio del juego 🎾🏆, Ironman luchaba para mantenerse al día. El robot gigante era muy rápido y preciso, y Ironman estaba perdiendo el control del juego. Pero recordó el espíritu de combate y la dedicación que siempre le habían llevado al éxito en sus batallas. Entonces, se puso su casco de Ironman y decidió darlo todo en la cancha.\n", + "\n", + "Finalmente, con gran esfuerzo y coraje, Ironman logró remontar el juego. Con un último y poderoso saque ⚡ que desarmó por completo al robot 🤖, Ironman ganó el partido. Exhausto pero triunfante, Ironman hizo una celebración característica de un súper héroe y se preparó para su siguiente gran desafío, sea en la batalla 🌃 o en el campo de juego 🎾.\n", + "\n", + "Así terminó la inusual pero emocionante aventura de Ironman y el tenis, demostrando que incluso los héroes tienen pasatiempos interesantes y pueden ser desafiados en los campos más inesperados. Y, naturalmente, Ironman demostró que, ya sea luchando contra las fuerzas del mal o jugando un partido de tenis, siempre juega para ganar. 💪🏆🎾🦾🚀\r\n" + ] + } + ], "source": [ "var variables = new KernelArguments() {\n", - " [\"input\"] = \"Tell me a Christmas Story\",\n", + " [\"input\"] = \"Cuenta una historia de tennis\",\n", " [\"hero\"] = \"Ironman\"\n", "};\n", "\n", - "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGenSpa\"], variables);\n", "Console.WriteLine(result);" ] }, @@ -765,7 +784,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -777,14 +796,38 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Estimados colegas,\n", + "\n", + "Como muchos de ustedes ya sabrán, tengo algunas habilidades poco comunes. Sí, soy Hulk 💪🟢, y justo ahora, necesito tomar unas vacaciones para mantener mi \"enfado\" bajo control.\n", + "\n", + "Voy a estar fuera de la oficina desde el 24 de diciembre hasta el 5 de enero por las festividades de Navidad 🎄 y el Año Nuevo 🎆. Durante este tiempo, estaré en un lugar secreto, descansando y recargando mis súper fuerzas.\n", + "\n", + "Durante mi ausencia, no tendrán que preocuparse. Mi querido amigo Thor ⚡🔨 se quedará a cargo. Con su martillo Mjölnir y su valentía asgardiana, estoy seguro de que será capaz de resolver cualquier problema que pueda surgir.\n", + "\n", + "Para cualquier consulta o emergencia, por favor, contacten con Thor en thor@asgard.com. Él estará más que feliz de ayudarles.\n", + "\n", + "Finalmente, quiero aprovechar esta oportunidad para desearles a todos una Feliz Navidad 🎅🎁y un próspero Año Nuevo lleno de amor, paz y felicidad.\n", + "\n", + "Nos vemos en enero, ¡y recuerden, siempre mantengan la calma! 😉\n", + "\n", + "Saludos,\n", + "\n", + "Hulk\r\n" + ] + } + ], "source": [ "var variables = new KernelArguments() {\n", - " [\"input\"] = \"Create an OOF for Christmas\",\n", + " [\"input\"] = \"Crea un OOF para Navidad\",\n", " [\"hero\"] = \"Hulk\"\n", "};\n", "\n", - "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOF\"], variables);\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOFSpa\"], variables);\n", "Console.WriteLine(result.GetValue());" ] }, @@ -829,7 +872,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -857,7 +900,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -888,7 +931,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -900,7 +943,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tony Stark\r\n" + ] + } + ], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", @@ -946,7 +997,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -958,7 +1009,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" ] @@ -972,7 +1033,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1003,7 +1064,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1015,11 +1076,31 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original plan:\n", + "\n", + "{{!-- Step 0: Set the joke about Batman --}}\n", + "{{set \"joke\" \"¿Por qué Batman puso a su coche de remate? ¡Para tener un bat-móvil!\"}}\n", + "\n", + "{{!-- Step 1: Set the out of office message template --}}\n", + "{{set \"officeMessageTemplate\" \"Estoy fuera de la oficina en este momento. Mientras tanto, aquí tienes un chiste para animarte el día: \\n\\n\"}}\n", + "\n", + "{{!-- Step 2: Concatenate the message template and the joke --}}\n", + "{{set \"outOfOfficeMessage\" (concat officeMessageTemplate joke)}}\n", + "\n", + "{{!-- Step 3: Print the final out of office message --}}\n", + "{{json outOfOfficeMessage}}\n" + ] + } + ], "source": [ "using System.Text.Json;\n", "\n", - "var ask = \"I would like you to tell me a joke about Batman, and with that joke, create an out-of-office message using the joke.\";\n", + "var ask = \"Me gustaría que me cuentes un chiste sobre Batman, y con ese chiste, crea un mensaje de fuera de la oficina utilizando la broma.\";\n", "#pragma warning disable SKEXP0060\n", "var originalPlan = await planner.CreatePlanAsync(kernel, ask);\n", "\n", @@ -1038,7 +1119,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1050,7 +1131,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original Plan results:\n", + "\n", + "Estoy fuera de la oficina en este momento. Mientras tanto, aquí tienes un chiste para animarte el día: \\n\\n¿Por qué Batman puso a su coche de remate? ¡Para tener un bat-móvil!\n" + ] + } + ], "source": [ "// executing the plan\n", "#pragma warning disable SKEXP0060\n", @@ -1085,7 +1176,8 @@ }, "outputs": [], "source": [ - "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, signing it with his alter ego.\";\n", + "var ask_complex = @\"Me gustaría que averigües el alter ego de IronMan y \n", + "crees un mensaje de fuera de la oficina para IronMan, firmando con su alter ego.\";\n", "\n", "#pragma warning disable SKEXP0060\n", "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", @@ -1166,11 +1258,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In order to use memory, we need to instantiate the Memory Plugin with a Memory Storage and an Embedding backend. In this example, we make use of the VolatileMemoryStore which can be thought of as a temporary in-memory storage (not to be confused with Semantic Memory).\n", + "Para utilizar la memoria, necesitamos instanciar el Plugin de Memoria con un Almacenamiento de Memoria y un backend de incrustación. En este ejemplo, hacemos uso de VolatileMemoryStore que puede considerarse como un almacenamiento temporal en memoria (no confundir con la Memoria Semántica).\n", "\n", - "This memory is not written to disk and is only available during the app session.\n", + "Esta memoria no se escribe en el disco y solo está disponible durante la sesión de la aplicación.\n", "\n", - "When developing your app you will have the option to plug in persistent storage like Azure Cosmos Db, PostgreSQL, SQLite, etc. Semantic Memory allows also to index external data sources, without duplicating all the information, more on that later." + "Al desarrollar tu aplicación tendrás la opción de conectar un almacenamiento persistente como Azure Cosmos Db, PostgreSQL, SQLite, etc. La Memoria Semántica también permite indexar fuentes de datos externas, sin duplicar toda la información, más sobre eso más adelante.\n" ] }, { @@ -1214,8 +1306,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's create some initial memories \"Fan Facts\". We can add memories to our VolatileMemoryStore by using SaveInformationAsync:\n", - "\n" + "Creemos algunas memorias iniciales \"Fan Facts\". Podemos agregar memorias a nuestro VolatileMemoryStore utilizando SaveInformationAsync:\n" ] }, { @@ -1248,7 +1339,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "And now we can test and search in the memory:" + "Y ahora podemos probar y buscar en la memoria:" ] }, { From ab5a724e1c0d8c025f122d4f1518165c36cd3fb4 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 5 Mar 2024 15:57:44 -0300 Subject: [PATCH 16/25] update memory kernel code samples to Spanish --- notebook-es.ipynb | 89 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/notebook-es.ipynb b/notebook-es.ipynb index a56368d..6724d71 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -1162,7 +1162,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1174,10 +1174,26 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plan:\n", + "\n", + "{{!-- Step 1: Get the alter ego of IronMan --}}\n", + "{{set \"alterEgo\" (HeroInfo-GetAlterEgo \"IronMan\")}}\n", + "\n", + "{{!-- Step 2: Create an out of office message --}}\n", + "{{set \"message\" (concat \"I'm not at the office today. Please leave a message and I'll get back as soon as possible. Regards: \" alterEgo)}}\n", + "\n", + "{{!-- Step 3: Output the JSON result --}}\n", + "{{json message}}\n" + ] + } + ], "source": [ - "var ask_complex = @\"Me gustaría que averigües el alter ego de IronMan y \n", - "crees un mensaje de fuera de la oficina para IronMan, firmando con su alter ego.\";\n", + "var ask_complex = @\"Me gustaría que averigües el alter ego de IronMan y crees un mensaje de fuera de la oficina para IronMan, firmando con su alter ego.\";\n", "\n", "#pragma warning disable SKEXP0060\n", "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", @@ -1195,7 +1211,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1207,7 +1223,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Complex Plan results:\n", + "\n", + "I'm not at the office today. Please leave a message and I'll get back as soon as possible. Regards: Tony Stark\n" + ] + } + ], "source": [ "#pragma warning disable SKEXP0060\n", "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", @@ -1236,7 +1262,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1248,7 +1274,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
  • System.Linq.Async, 6.0.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" @@ -1267,7 +1303,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1311,7 +1347,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1328,11 +1364,11 @@ "// add fan facts to the collection\n", "const string MemoryCollectionName = \"fanFacts\";\n", "\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info1\", text: \"Gisela's favourite super hero is Batman\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info2\", text: \"The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info3\", text: \"Bruno's favourite super hero is Invincible\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"The last super hero movie watched by Bruno was Aquaman II\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");" + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info1\", text: \"El superhéroe favorito de Gisela es Batman\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info2\", text: \"La última película de superhéroes vista por Gisela fue Guardians of the Galaxy Vol 3\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info3\", text: \"El superhéroe favorito de Bruno es Invincible\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"La última película de superhéroes vista por Bruno fue Aquaman II\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"A Bruno no le gusta la película de superhéroes: Eternals\");\n" ] }, { @@ -1344,7 +1380,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1356,8 +1392,27 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "what is Bruno's favourite super hero? El superhéroe favorito de Bruno es Invincible\n", + "what was the last movie watched by Gisela? La última película de superhéroes vista por Gisela fue Guardians of the Galaxy Vol 3\n", + "Which is the prefered super hero for Gisela? El superhéroe favorito de Gisela es Batman\n", + "Did Bruno watched a super hero movie in the past, which was the last one? La última película de superhéroes vista por Bruno fue Aquaman II\n" + ] + } + ], "source": [ + "var preguntas = new[]\n", + "{\n", + " \"¿Cuál es el superhéroe favorito de Bruno?\",\n", + " \"¿Cuál fue la última película vista por Gisela?\",\n", + " \"¿Cuál es el superhéroe preferido de Gisela?\",\n", + " \"¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última?\"\n", + "};\n", + "\n", "var questions = new[]\n", "{\n", " \"what is Bruno's favourite super hero?\",\n", From 61936840b6f29fac06e3148ab7baed661a6d3d39 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 5 Mar 2024 15:58:05 -0300 Subject: [PATCH 17/25] samples in Spanish updated --- notebook-es.ipynb | 296 ++++++++++++++-------------------------------- 1 file changed, 87 insertions(+), 209 deletions(-) diff --git a/notebook-es.ipynb b/notebook-es.ipynb index 6724d71..eebf722 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -41,7 +41,23 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[31;1mWARNING: A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.\u001b[0m\r\n" + ] + }, + { + "ename": "Error", + "evalue": "Command cancelled.", + "output_type": "error", + "traceback": [ + "Command cancelled." + ] + } + ], "source": [ "az login" ] @@ -278,7 +294,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -290,17 +306,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel, 1.5.0
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" ] @@ -314,7 +320,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -343,7 +349,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -399,7 +405,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -456,7 +462,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -484,7 +490,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -511,7 +517,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -523,19 +529,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Claro, aquí tienes un chiste:\n", - "\n", - "¿Por qué Superman nunca pelea contra un chiste malo?\n", - "\n", - "Porque siempre se ríe hasta quedar exhausto.\r\n" - ] - } - ], + "outputs": [], "source": [ "var joke = new KernelArguments() { [\"input\"] = \"cuentame un chiste\" };\n", "var result = await kernel.InvokeAsync(funPluginFunctions[\"JokeSpa\"], joke);\n", @@ -616,7 +610,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -645,7 +639,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -671,7 +665,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -683,17 +677,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "¿Por qué Ironman no puede jugar al fútbol?\n", - "\n", - "Porque cada vez que recibe el balón, se convierte en un hombre de hierro gol.\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -707,7 +691,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -736,7 +720,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -748,23 +732,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Había una vez un héroe llamado Ironman 🦾💪🚀, que era conocido por sus increíbles habilidades de combate y su inteligencia. Sin embargo, pocos sabían que Ironman también tenía una pasión secreta: jugar al tenis 🎾.\n", - "\n", - "Un día ☀️, Ironman jugaba su partido habitual de tenis solo en un antiguo campo de juego 🏞️. De repente, apareció un formidable contrincante: un robot gigante 🤖 de uno de sus archienemigos. El robot había venido a desafiar a Ironman a un partido de tenis. Ironman, sorprendido pero listo para el desafío, aceptó y comenzaron el partido.\n", - "\n", - "En el medio del juego 🎾🏆, Ironman luchaba para mantenerse al día. El robot gigante era muy rápido y preciso, y Ironman estaba perdiendo el control del juego. Pero recordó el espíritu de combate y la dedicación que siempre le habían llevado al éxito en sus batallas. Entonces, se puso su casco de Ironman y decidió darlo todo en la cancha.\n", - "\n", - "Finalmente, con gran esfuerzo y coraje, Ironman logró remontar el juego. Con un último y poderoso saque ⚡ que desarmó por completo al robot 🤖, Ironman ganó el partido. Exhausto pero triunfante, Ironman hizo una celebración característica de un súper héroe y se preparó para su siguiente gran desafío, sea en la batalla 🌃 o en el campo de juego 🎾.\n", - "\n", - "Así terminó la inusual pero emocionante aventura de Ironman y el tenis, demostrando que incluso los héroes tienen pasatiempos interesantes y pueden ser desafiados en los campos más inesperados. Y, naturalmente, Ironman demostró que, ya sea luchando contra las fuerzas del mal o jugando un partido de tenis, siempre juega para ganar. 💪🏆🎾🦾🚀\r\n" - ] - } - ], + "outputs": [], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Cuenta una historia de tennis\",\n", @@ -784,7 +752,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -796,31 +764,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Estimados colegas,\n", - "\n", - "Como muchos de ustedes ya sabrán, tengo algunas habilidades poco comunes. Sí, soy Hulk 💪🟢, y justo ahora, necesito tomar unas vacaciones para mantener mi \"enfado\" bajo control.\n", - "\n", - "Voy a estar fuera de la oficina desde el 24 de diciembre hasta el 5 de enero por las festividades de Navidad 🎄 y el Año Nuevo 🎆. Durante este tiempo, estaré en un lugar secreto, descansando y recargando mis súper fuerzas.\n", - "\n", - "Durante mi ausencia, no tendrán que preocuparse. Mi querido amigo Thor ⚡🔨 se quedará a cargo. Con su martillo Mjölnir y su valentía asgardiana, estoy seguro de que será capaz de resolver cualquier problema que pueda surgir.\n", - "\n", - "Para cualquier consulta o emergencia, por favor, contacten con Thor en thor@asgard.com. Él estará más que feliz de ayudarles.\n", - "\n", - "Finalmente, quiero aprovechar esta oportunidad para desearles a todos una Feliz Navidad 🎅🎁y un próspero Año Nuevo lleno de amor, paz y felicidad.\n", - "\n", - "Nos vemos en enero, ¡y recuerden, siempre mantengan la calma! 😉\n", - "\n", - "Saludos,\n", - "\n", - "Hulk\r\n" - ] - } - ], + "outputs": [], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Crea un OOF para Navidad\",\n", @@ -872,7 +816,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -900,7 +844,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -931,7 +875,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -943,15 +887,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tony Stark\r\n" - ] - } - ], + "outputs": [], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", @@ -997,7 +933,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1009,17 +945,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" ] @@ -1033,7 +959,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1064,7 +990,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1076,27 +1002,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original plan:\n", - "\n", - "{{!-- Step 0: Set the joke about Batman --}}\n", - "{{set \"joke\" \"¿Por qué Batman puso a su coche de remate? ¡Para tener un bat-móvil!\"}}\n", - "\n", - "{{!-- Step 1: Set the out of office message template --}}\n", - "{{set \"officeMessageTemplate\" \"Estoy fuera de la oficina en este momento. Mientras tanto, aquí tienes un chiste para animarte el día: \\n\\n\"}}\n", - "\n", - "{{!-- Step 2: Concatenate the message template and the joke --}}\n", - "{{set \"outOfOfficeMessage\" (concat officeMessageTemplate joke)}}\n", - "\n", - "{{!-- Step 3: Print the final out of office message --}}\n", - "{{json outOfOfficeMessage}}\n" - ] - } - ], + "outputs": [], "source": [ "using System.Text.Json;\n", "\n", @@ -1119,7 +1025,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1131,17 +1037,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original Plan results:\n", - "\n", - "Estoy fuera de la oficina en este momento. Mientras tanto, aquí tienes un chiste para animarte el día: \\n\\n¿Por qué Batman puso a su coche de remate? ¡Para tener un bat-móvil!\n" - ] - } - ], + "outputs": [], "source": [ "// executing the plan\n", "#pragma warning disable SKEXP0060\n", @@ -1162,7 +1058,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1174,24 +1070,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Plan:\n", - "\n", - "{{!-- Step 1: Get the alter ego of IronMan --}}\n", - "{{set \"alterEgo\" (HeroInfo-GetAlterEgo \"IronMan\")}}\n", - "\n", - "{{!-- Step 2: Create an out of office message --}}\n", - "{{set \"message\" (concat \"I'm not at the office today. Please leave a message and I'll get back as soon as possible. Regards: \" alterEgo)}}\n", - "\n", - "{{!-- Step 3: Output the JSON result --}}\n", - "{{json message}}\n" - ] - } - ], + "outputs": [], "source": [ "var ask_complex = @\"Me gustaría que averigües el alter ego de IronMan y crees un mensaje de fuera de la oficina para IronMan, firmando con su alter ego.\";\n", "\n", @@ -1211,7 +1090,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1223,17 +1102,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Complex Plan results:\n", - "\n", - "I'm not at the office today. Please leave a message and I'll get back as soon as possible. Regards: Tony Stark\n" - ] - } - ], + "outputs": [], "source": [ "#pragma warning disable SKEXP0060\n", "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", @@ -1262,7 +1131,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1274,17 +1143,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
  • System.Linq.Async, 6.0.1
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" @@ -1303,7 +1162,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1347,7 +1206,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1380,7 +1239,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1392,18 +1251,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "what is Bruno's favourite super hero? El superhéroe favorito de Bruno es Invincible\n", - "what was the last movie watched by Gisela? La última película de superhéroes vista por Gisela fue Guardians of the Galaxy Vol 3\n", - "Which is the prefered super hero for Gisela? El superhéroe favorito de Gisela es Batman\n", - "Did Bruno watched a super hero movie in the past, which was the last one? La última película de superhéroes vista por Bruno fue Aquaman II\n" - ] - } - ], + "outputs": [], "source": [ "var preguntas = new[]\n", "{\n", @@ -1413,6 +1261,36 @@ " \"¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última?\"\n", "};\n", "\n", + "foreach (var q in preguntas)\n", + "{\n", + " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", + "}\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hacemos la misma prueba con preguntas en English!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ "var questions = new[]\n", "{\n", " \"what is Bruno's favourite super hero?\",\n", From 6e6c261cc3b1179421e79d236dfdf51e9dad11b1 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 12 Mar 2024 17:58:36 -0400 Subject: [PATCH 18/25] add memory kernel samples in other languages --- notebook-en.ipynb | 307 +++++++++++++++++++++++++++++++++++++++------- notebook-es.ipynb | 27 +--- 2 files changed, 272 insertions(+), 62 deletions(-) diff --git a/notebook-en.ipynb b/notebook-en.ipynb index ecf8112..f664e64 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -279,7 +279,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -291,7 +291,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 1.5.0
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" ] @@ -305,7 +315,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -334,7 +344,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -390,7 +400,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -447,7 +457,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -475,7 +485,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -502,7 +512,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -586,7 +596,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -598,7 +608,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Why don't heroes ever play cards with the jungle villain?\n", + "\n", + "Because they're terrified the villain might have a cheetah up his sleeve!\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -612,7 +632,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -641,7 +661,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -667,7 +687,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -679,7 +699,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Why did Ironman help Santa with delivering presents on Christmas Eve?\n", + "\n", + "Because he heard Santa's sleigh was low on \"Stark Power!\"\r\n" + ] + } + ], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -693,7 +723,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -722,7 +752,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -734,7 +764,29 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Once upon a time in the hustle and bustle of New York City 🌃, our hero Ironman, aka Tony Stark, knitted his eyebrows as he noticed something strange. Even as the Christmas 🎄 season dawned, New Yorkers seemed downcast, and their faces lacked the usual festive cheer 😔.\n", + "\n", + "Atop the Stark Tower, Ironman analyzed 💻 the situation, realizing that the economic downturn 📉 had hit people’s pockets heavily. It had snuffed out the Christmas spirit. But our hero, Ironman, had plans to bring Christmas cheer back. He organized an event called 'Stark's Winter Carnival' 🎪 and publicly invited everyone through the city screens 🏢📺. \n", + "\n", + "The day of the carnival arrived, and Ironman donned his suit 🦾. With a deafening whoosh, he flew into the night sky 🌃, leaving a trail of dazzling sparkles ✨, followed by a shower of Christmas presents 🎁 falling over the city. People gazed in awe, their faces lighting up with smiles 😃.\n", + "\n", + "Back at the carnival, food 🍔🍕, games 🎳, and music 🎵 filled the air. There was laughter and joy, the air thick with anticipation and the sweet smell of roasted chestnuts. Then, with a grand entrance, Ironman landed 🦾. He was met with cheers and clapping 👏. Inside the suit was Tony Stark, the billionaire philanthropist, celebrating Christmas with the city he loved.\n", + "\n", + "Amidst the festivities, Tony urged people to remember the spirit of giving, unity, and love 💖. Inspired by Ironman, the people of New York promised to carry forward this spirit beyond Christmas 🤝🏽.\n", + "\n", + "Eventually, Ironman flew off into the night sky, leaving behind a city sparkling with Christmas lights and hearts warmed by his kind act. The economic downturn had cast a shadow, but Ironman fought it back, not with his fists but with his heart. 💖\n", + "\n", + "And so this was the story of a Christmas 🎄 unlike any other, where our hero Ironman reminded everyone, a spirit of unity, giving, love and joy can conquer any hardship. And Christmas was indeed merry in New York once again 🎅🎆🎉.\n", + "\n", + "The End.\r\n" + ] + } + ], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Tell me a Christmas Story\",\n", @@ -754,7 +806,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -766,7 +818,33 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Subject: 🎄🎅 \"Hulk Out for Holiday Smashing! But Don't Worry, There's Backup! 🎅🎄\"\n", + "\n", + "Hello,\n", + "\n", + "If you're reading this message, it means that I, Hulk, am currently unavailable. I am taking a break from smashing to enjoy some 🎄 Christmas cookies and milk 🍪, and try to squeeze myself into a woefully undersize 🎅 Santa hat.\n", + "\n", + "I'll admit, despite my superhuman strength, endless stamina, and invulnerability, even a gamma radiation-filled hero like me needs the occasisonal 💤 rest and time to charge the old batteries.\n", + "\n", + "While the power of Hulk Smash 💪 won't be around to save the day in the immediate future, fear not! You're not left helpless. My very competent and technologically advanced buddy, 🦾 Iron Man, has generously agreed to cover for me while I'm away. Trust me, he's fully equipped and smarter than most. You're in good repulsor-blasting hands with him 🚀.\n", + "\n", + "Just shoot him a message at: StarkSuitsYouBetter@avengers.com\n", + "\n", + "Expect my return after the festive period when I've sufficiently chimed the jingle bells, decked the halls, and had enough of Santa Hulk🎅💚.\n", + "\n", + "Until then, Hulk out! Enjoy the holiday season and remember - peace on Earth. No smashing while Hulk's away - got it? \n", + "\n", + "Goodbye and rawwwwwr-y Christmas! 🎄\n", + "\n", + "Hulk 💪💚\r\n" + ] + } + ], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Create an OOF for Christmas\",\n", @@ -818,7 +896,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -846,7 +924,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -876,7 +954,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -888,11 +966,19 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bruce Banner\r\n" + ] + } + ], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", - " [\"input\"] = \"Ironman\"\n", + " [\"input\"] = \"Hulk\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", @@ -935,7 +1021,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -947,7 +1033,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" ] @@ -961,7 +1057,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -992,7 +1088,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1004,7 +1100,27 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original plan:\n", + "\n", + "{{!-- Step 1: Get the alter ego of Batman --}}\n", + "{{set \"alterEgo\" (HeroInfo-GetAlterEgo \"Batman\")}}\n", + "\n", + "{{!-- Step 2: Construct the joke --}}\n", + "{{set \"joke\" (concat \"Why did \" alterEgo \" go fishing? Because he heard there were great bat-\" \"manatee\" \" sightings!\")}}\n", + "\n", + "{{!-- Step 3: Construct the final out-of-office message --}}\n", + "{{set \"message\" (concat \"I'm out of the office right now, just like \" alterEgo \", maybe I have gone fishing. In the meantime, here's a joke for you: \" joke)}}\n", + "\n", + "{{!-- Step 4: Output the final message --}}\n", + "{{json message}}\n" + ] + } + ], "source": [ "using System.Text.Json;\n", "\n", @@ -1027,7 +1143,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1039,7 +1155,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original Plan results:\n", + "\n", + "I'm out of the office right now, just like Terry McGinnis, maybe I have gone fishing. In the meantime, here's a joke for you: Why did Terry McGinnis go fishing? Because he heard there were great bat-manatee sightings!\n" + ] + } + ], "source": [ "// executing the plan\n", "#pragma warning disable SKEXP0060\n", @@ -1060,7 +1186,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1072,7 +1198,24 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plan:\n", + "\n", + "{{!-- Step 1: Use the HeroInfo-GetAlterEgo helper to get IronMan's alter ego --}}\n", + "{{set \"alterEgo\" (HeroInfo-GetAlterEgo \"IronMan\")}}\n", + "\n", + "{{!-- Step 2: Use the concat helper to create the out-of-office message --}}\n", + "{{set \"message\" (concat \"I, as \" alterEgo \", am currently out of office. I will get back to you when I'm back in. Best, \" alterEgo)}}\n", + "\n", + "{{!-- Step 3: Use the json helper to print out the final out-of-office message --}}\n", + "{{json message}}\n" + ] + } + ], "source": [ "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, signing it with his alter ego.\";\n", "\n", @@ -1092,7 +1235,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1104,7 +1247,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Complex Plan results:\n", + "\n", + "I, as Tony Stark, am currently out of office. I will get back to you when I'm back in. Best, Tony Stark\n" + ] + } + ], "source": [ "#pragma warning disable SKEXP0060\n", "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", @@ -1133,7 +1286,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1145,7 +1298,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
  • System.Linq.Async, 6.0.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" @@ -1164,7 +1327,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1209,7 +1372,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1242,7 +1405,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1254,7 +1417,18 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "what is Bruno's favourite super hero? Bruno's favourite super hero is Invincible\n", + "what was the last movie watched by Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", + "Which is the prefered super hero for Gisela? Gisela's favourite super hero is Batman\n", + "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n" + ] + } + ], "source": [ "var questions = new[]\n", "{\n", @@ -1270,6 +1444,57 @@ " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", "}\n" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the following code cell, we will demonstrate how we can also search the memory kernel using another language. We will use the same questions as before, but this time they will be translated into Spanish.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "¿Cuál es el superhéroe favorito de Bruno? Bruno's favourite super hero is Invincible\n", + "¿Cuál fue la última película vista por Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", + "¿Cuál es el superhéroe preferido de Gisela? Gisela's favourite super hero is Batman\n", + "¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última? The last super hero movie watched by Bruno was Aquaman II\n", + "Cual es la pelicula que no le gusta a Bruno? Bruno don't like the super hero movie: Eternals\n" + ] + } + ], + "source": [ + "var preguntas = new[]\n", + "{\n", + " \"¿Cuál es el superhéroe favorito de Bruno?\",\n", + " \"¿Cuál fue la última película vista por Gisela?\",\n", + " \"¿Cuál es el superhéroe preferido de Gisela?\",\n", + " \"¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última?\",\n", + " \"Cual es la pelicula que no le gusta a Bruno?\"\n", + "};\n", + "\n", + "foreach (var q in preguntas)\n", + "{\n", + " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", + "}" + ] } ], "metadata": { diff --git a/notebook-es.ipynb b/notebook-es.ipynb index eebf722..d6cfe4d 100644 --- a/notebook-es.ipynb +++ b/notebook-es.ipynb @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -41,23 +41,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[31;1mWARNING: A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.\u001b[0m\r\n" - ] - }, - { - "ename": "Error", - "evalue": "Command cancelled.", - "output_type": "error", - "traceback": [ - "Command cancelled." - ] - } - ], + "outputs": [], "source": [ "az login" ] @@ -626,7 +610,7 @@ "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Cuentame un chiste de futbol\",\n", - " [\"hero\"] = \"Ironman\"\n", + " [\"hero\"] = \"Batman\"\n", "};" ] }, @@ -891,7 +875,7 @@ "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", - " [\"input\"] = \"Ironman\"\n", + " [\"input\"] = \"Batman\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", @@ -1258,7 +1242,8 @@ " \"¿Cuál es el superhéroe favorito de Bruno?\",\n", " \"¿Cuál fue la última película vista por Gisela?\",\n", " \"¿Cuál es el superhéroe preferido de Gisela?\",\n", - " \"¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última?\"\n", + " \"¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última?\",\n", + " \"Cual es la pelicula que no le gusta a Bruno?\"\n", "};\n", "\n", "foreach (var q in preguntas)\n", From 9057b21fbd68b3400aa3fb5ee07402527dcb8bbc Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Tue, 9 Apr 2024 14:42:41 -0400 Subject: [PATCH 19/25] split azure resource creation in a new notebook update pacakges to the latest version fix code to use latest packages --- create-azure-resources-en .ipynb | 287 ++++++++++++++++++++ notebook-en.ipynb | 440 +++++++------------------------ 2 files changed, 378 insertions(+), 349 deletions(-) create mode 100644 create-azure-resources-en .ipynb diff --git a/create-azure-resources-en .ipynb b/create-azure-resources-en .ipynb new file mode 100644 index 0000000..bb6e52f --- /dev/null +++ b/create-azure-resources-en .ipynb @@ -0,0 +1,287 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 🦸🏻 Understanding Semantic Kernel with Heroes 🦸🏼‍♀️\n", + "\n", + "Semantic Kernel has been created to allow developers to seamlessly integrate Artificial Intelligence into their applications. To achieve this, it provides a set of features that will enable you to add models, prompts, native functions, and memories without requiring deep knowledge of AI 🥲. That's why it's said that Semantic Kernel simulates the brain 🧠 of your application.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## (Optional) - Creating an Azure Open AI 🤖 Service and Deployments\n", + "\n", + "Before diving into Semantic Kernel 🛝, you'll need to have one of the supported services set up. Currently, you can choose from the following options: [Azure Open AI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), [Open AI](https://openai.com/), or [Hugging Face](https://huggingface.co/).\n", + "\n", + "In this example, I am going to use Azure Open AI.\n", + "\n", + "Therefore, through Azure CLI, I need to log in:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "tags": [], + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az login" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you need it, because you have many tenants and subscriptions under your account, you can select the one that interests you (or has access to Azure Open AI 😊) through the following command:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az account set -n \"Visual Studio Enterprise Subscription\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, to be able to create what you need for this notebook, set the following variables with your preferred values:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "$RESOURCE_GROUP=\"understanding-semantic-kernel\"\n", + "$LOCATION=\"canadaeast\"\n", + "$AZURE_OPEN_AI=\"ai-for-heroes\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With them, you can now create the resource group:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az group create `\n", + "--name $RESOURCE_GROUP `\n", + "--location $LOCATION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An Azure Open AI resource:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az cognitiveservices account create `\n", + "--name $AZURE_OPEN_AI `\n", + "--custom-domain $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--kind OpenAI `\n", + "--sku S0 `\n", + "--location $LOCATION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And finally, you need a deployment of any of the models you have available. In this example, I am going to use gpt-4:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az cognitiveservices account deployment create `\n", + "--name $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--deployment-name \"gpt-4\" `\n", + "--model-name \"gpt-4\" `\n", + "--model-version \"0613\" `\n", + "--model-format OpenAI `\n", + "--sku-capacity \"10\" `\n", + "--sku-name \"Standard\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The **sku-capacity** parameter allows us to specify how many tokens per minute we can send to this model. To see how your quota usage is, you can use this other command:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "az cognitiveservices usage list `\n", + "-l $LOCATION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load enviroment variables with your Azure Open AI endpoint and key" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "$env:AZURE_OPEN_AI_KEY =$(az cognitiveservices account keys list `\n", + "--name $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--query \"key1\" `\n", + "--output tsv)\n", + "\n", + "$env:AZURE_OPEN_AI_ENDPOINT =$(az cognitiveservices account show `\n", + "--name $AZURE_OPEN_AI `\n", + "--resource-group $RESOURCE_GROUP `\n", + "--query \"properties.endpoint\" `\n", + "--output tsv)\n", + "\n", + "#dir env:AZURE_OPEN_AI_KEY\n", + "#dir env:AZURE_OPEN_AI_ENDPOINT" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "python" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebook-en.ipynb b/notebook-en.ipynb index f664e64..5481f08 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -13,253 +13,6 @@ "
" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## (Optional) - Creating an Azure Open AI 🤖 Service and Deployments\n", - "\n", - "Before diving into Semantic Kernel 🛝, you'll need to have one of the supported services set up. Currently, you can choose from the following options: [Azure Open AI](https://azure.microsoft.com/en-us/products/ai-services/openai-service), [Open AI](https://openai.com/), or [Hugging Face](https://huggingface.co/).\n", - "\n", - "In this example, I am going to use Azure Open AI.\n", - "\n", - "Therefore, through Azure CLI, I need to log in:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "tags": [], - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "az login" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you need it, because you have many tenants and subscriptions under your account, you can select the one that interests you (or has access to Azure Open AI 😊) through the following command:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "az account set -n \"Visual Studio Enterprise Subscription\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, to be able to create what you need for this notebook, set the following variables with your preferred values:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "$RESOURCE_GROUP=\"understanding-semantic-kernel\"\n", - "$LOCATION=\"canadaeast\"\n", - "$AZURE_OPEN_AI=\"ai-for-heroes\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With them, you can now create the resource group:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "az group create `\n", - "--name $RESOURCE_GROUP `\n", - "--location $LOCATION" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "An Azure Open AI resource:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "az cognitiveservices account create `\n", - "--name $AZURE_OPEN_AI `\n", - "--custom-domain $AZURE_OPEN_AI `\n", - "--resource-group $RESOURCE_GROUP `\n", - "--kind OpenAI `\n", - "--sku S0 `\n", - "--location $LOCATION" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And finally, you need a deployment of any of the models you have available. In this example, I am going to use gpt-4:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "az cognitiveservices account deployment create `\n", - "--name $AZURE_OPEN_AI `\n", - "--resource-group $RESOURCE_GROUP `\n", - "--deployment-name \"gpt-4\" `\n", - "--model-name \"gpt-4\" `\n", - "--model-version \"0613\" `\n", - "--model-format OpenAI `\n", - "--sku-capacity \"10\" `\n", - "--sku-name \"Standard\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The **sku-capacity** parameter allows us to specify how many tokens per minute we can send to this model. To see how your quota usage is, you can use this other command:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "az cognitiveservices usage list `\n", - "-l $LOCATION" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Load enviroment variables with your Azure Open AI endpoint and key" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "$env:AZURE_OPEN_AI_KEY =$(az cognitiveservices account keys list `\n", - "--name $AZURE_OPEN_AI `\n", - "--resource-group $RESOURCE_GROUP `\n", - "--query \"key1\" `\n", - "--output tsv)\n", - "\n", - "$env:AZURE_OPEN_AI_ENDPOINT =$(az cognitiveservices account show `\n", - "--name $AZURE_OPEN_AI `\n", - "--resource-group $RESOURCE_GROUP `\n", - "--query \"properties.endpoint\" `\n", - "--output tsv)\n", - "\n", - "#dir env:AZURE_OPEN_AI_KEY\n", - "#dir env:AZURE_OPEN_AI_ENDPOINT" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -271,7 +24,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The first thing you need to be able to run Semantic Kernel in this notebook is to install the **Microsoft.SemanticKernel** library, which is currently in version **1.5.0** (I promise to keep updating 🤓). \n", + "The first thing you need to be able to run Semantic Kernel in this notebook is to install the **Microsoft.SemanticKernel** library, which is currently in version **1.7.1** (I promise to keep updating 🤓). \n", "\n", "You can find more information about this library and its updates on the official NuGet page [here](https://www.nuget.org/packages/Microsoft.SemanticKernel).\n", "\n" @@ -279,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -291,19 +44,9 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel, 1.5.0
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 1.5.0\"" + "#r \"nuget: Microsoft.SemanticKernel, 1.7.1\"" ] }, { @@ -315,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -344,7 +87,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -383,9 +126,29 @@ "outputs": [], "source": [ "// Azure OpenAI keys\n", - "var deploymentName = \"gpt-4\";\n", - "var endpoint = Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_ENDPOINT\");\n", - "var apiKey = Environment.GetEnvironmentVariable(\"AZURE_OPEN_AI_KEY\");\n", + "var deploymentName = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Azure OpenAI deployment name\")).GetClearTextPassword();\n", + "var endpoint = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Azure Open AI endpoint\")).GetClearTextPassword();\n", + "var apiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Azure Open AI key\")).GetClearTextPassword();\n", + "\n", + "// Create a chat completion service\n", + "builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Azure OpenAI keys \n", + "var keys = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Azure OpenAI information\")).GetClearTextPassword().Split(';');\n", + "var deploymentName = keys[0];\n", + "var endpoint = keys[1];\n", + "var apiKey = keys[2];\n", "\n", "// Create a chat completion service\n", "builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);" @@ -400,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 18, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -457,7 +220,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -485,7 +248,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -512,7 +275,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -596,7 +359,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -613,9 +376,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why don't heroes ever play cards with the jungle villain?\n", + "Why did the hero bring a ladder to the bar?\n", "\n", - "Because they're terrified the villain might have a cheetah up his sleeve!\r\n" + "Because he heard the drinks were on the house!\r\n" ] } ], @@ -632,7 +395,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -661,7 +424,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -687,7 +450,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -704,9 +467,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why did Ironman help Santa with delivering presents on Christmas Eve?\n", + "Why did Ironman get coal in his stocking for Christmas?\n", "\n", - "Because he heard Santa's sleigh was low on \"Stark Power!\"\r\n" + "Because he's always \"ironing\" out his problems!\r\n" ] } ], @@ -723,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -752,7 +515,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -769,21 +532,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "Once upon a time in the hustle and bustle of New York City 🌃, our hero Ironman, aka Tony Stark, knitted his eyebrows as he noticed something strange. Even as the Christmas 🎄 season dawned, New Yorkers seemed downcast, and their faces lacked the usual festive cheer 😔.\n", - "\n", - "Atop the Stark Tower, Ironman analyzed 💻 the situation, realizing that the economic downturn 📉 had hit people’s pockets heavily. It had snuffed out the Christmas spirit. But our hero, Ironman, had plans to bring Christmas cheer back. He organized an event called 'Stark's Winter Carnival' 🎪 and publicly invited everyone through the city screens 🏢📺. \n", + "Once upon a time, in a city far, far away, there was a man named Tony Stark. He was a brilliant scientist and inventor, but he was also known as the fearless superhero Ironman. It was a snowy Christmas Eve and the city was bustling with holiday cheer. People were bustling around, buying last-minute gifts and decorations for their homes.\n", "\n", - "The day of the carnival arrived, and Ironman donned his suit 🦾. With a deafening whoosh, he flew into the night sky 🌃, leaving a trail of dazzling sparkles ✨, followed by a shower of Christmas presents 🎁 falling over the city. People gazed in awe, their faces lighting up with smiles 😃.\n", + "Meanwhile, Tony Stark was busy in his lab, working on his latest invention. As he tinkered away, he received a distress call from the city. It seems that a group of villains were causing chaos and ruining Christmas for everyone. Without hesitation, Tony suited up in his Ironman armor and flew out to save the day.\n", "\n", - "Back at the carnival, food 🍔🍕, games 🎳, and music 🎵 filled the air. There was laughter and joy, the air thick with anticipation and the sweet smell of roasted chestnuts. Then, with a grand entrance, Ironman landed 🦾. He was met with cheers and clapping 👏. Inside the suit was Tony Stark, the billionaire philanthropist, celebrating Christmas with the city he loved.\n", + "As Ironman arrived at the scene, he saw the villains wreaking havoc, stealing presents, and causing chaos. Using his special powers and gadgets, Ironman fought valiantly to protect the city and its people. The battle was fierce, but Ironman was determined to save Christmas for everyone.\n", "\n", - "Amidst the festivities, Tony urged people to remember the spirit of giving, unity, and love 💖. Inspired by Ironman, the people of New York promised to carry forward this spirit beyond Christmas 🤝🏽.\n", + "Finally, Ironman managed to defeat the villains and restore peace to the city. The people cheered and thanked him for his bravery. In the end, Ironman flew back to his lab, satisfied that he had saved Christmas for the city.\n", "\n", - "Eventually, Ironman flew off into the night sky, leaving behind a city sparkling with Christmas lights and hearts warmed by his kind act. The economic downturn had cast a shadow, but Ironman fought it back, not with his fists but with his heart. 💖\n", - "\n", - "And so this was the story of a Christmas 🎄 unlike any other, where our hero Ironman reminded everyone, a spirit of unity, giving, love and joy can conquer any hardship. And Christmas was indeed merry in New York once again 🎅🎆🎉.\n", - "\n", - "The End.\r\n" + "As Tony Stark took off his armor and sat down to rest, he reflected on the true meaning of Christmas. It wasn't about the presents or the decorations, but about coming together to help and protect others. With a smile on his face, Tony felt proud to have been able to spread the spirit of Christmas and make the city a little brighter. And with that, he wished everyone a merry Christmas and a happy new year. 🎄🦸‍♂️✨\r\n" ] } ], @@ -806,7 +563,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -823,25 +580,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "Subject: 🎄🎅 \"Hulk Out for Holiday Smashing! But Don't Worry, There's Backup! 🎅🎄\"\n", - "\n", - "Hello,\n", - "\n", - "If you're reading this message, it means that I, Hulk, am currently unavailable. I am taking a break from smashing to enjoy some 🎄 Christmas cookies and milk 🍪, and try to squeeze myself into a woefully undersize 🎅 Santa hat.\n", - "\n", - "I'll admit, despite my superhuman strength, endless stamina, and invulnerability, even a gamma radiation-filled hero like me needs the occasisonal 💤 rest and time to charge the old batteries.\n", - "\n", - "While the power of Hulk Smash 💪 won't be around to save the day in the immediate future, fear not! You're not left helpless. My very competent and technologically advanced buddy, 🦾 Iron Man, has generously agreed to cover for me while I'm away. Trust me, he's fully equipped and smarter than most. You're in good repulsor-blasting hands with him 🚀.\n", + "Hey there! 👋\n", "\n", - "Just shoot him a message at: StarkSuitsYouBetter@avengers.com\n", + "Thank you for reaching out! I'm currently out of the office, smashing some bad guys and saving the world. 💪💥 I won't be able to respond to any messages until I return.\n", "\n", - "Expect my return after the festive period when I've sufficiently chimed the jingle bells, decked the halls, and had enough of Santa Hulk🎅💚.\n", + "In my absence, you can reach out to my super friend Thor, the God of Thunder, for any help or assistance. ⚡\n", "\n", - "Until then, Hulk out! Enjoy the holiday season and remember - peace on Earth. No smashing while Hulk's away - got it? \n", + "Sorry for any inconvenience, but I promise I'll be back to help soon! Until then, stay safe and remember - Hulk is always watching out for you! 👀\n", "\n", - "Goodbye and rawwwwwr-y Christmas! 🎄\n", - "\n", - "Hulk 💪💚\r\n" + "Goodbye for now! 🌟\r\n" ] } ], @@ -896,7 +643,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 29, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -924,7 +671,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 30, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -954,7 +701,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 31, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1021,7 +768,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 32, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1037,7 +784,7 @@ { "data": { "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview
" + "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.7.1-preview
" ] }, "metadata": {}, @@ -1045,7 +792,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.5.0-preview\"" + "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.7.1-preview\"" ] }, { @@ -1057,7 +804,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 33, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1088,7 +835,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 34, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1107,17 +854,14 @@ "text": [ "Original plan:\n", "\n", - "{{!-- Step 1: Get the alter ego of Batman --}}\n", - "{{set \"alterEgo\" (HeroInfo-GetAlterEgo \"Batman\")}}\n", + "{{!-- Step 0: Extract Key Values --}}\n", + "{{set \"joke\" \"Why did Batman refuse to fight the Joker? Because he always wanted to punch up, not down!\"}}\n", "\n", - "{{!-- Step 2: Construct the joke --}}\n", - "{{set \"joke\" (concat \"Why did \" alterEgo \" go fishing? Because he heard there were great bat-\" \"manatee\" \" sightings!\")}}\n", + "{{!-- Step 1: Create the out-of-office message using the joke --}}\n", + "{{set \"outOfOfficeMessage\" (concat \"Hello, I'm currently out of the Batcave, taking a break from protecting Gotham. Here's a lighthearted joke to brighten your day: \" joke \" Feel free to reach out to Alfred if you have any urgent Bat-signal needs. I'll be back soon!\")}}\n", "\n", - "{{!-- Step 3: Construct the final out-of-office message --}}\n", - "{{set \"message\" (concat \"I'm out of the office right now, just like \" alterEgo \", maybe I have gone fishing. In the meantime, here's a joke for you: \" joke)}}\n", - "\n", - "{{!-- Step 4: Output the final message --}}\n", - "{{json message}}\n" + "{{!-- Step 2: Output the final message as JSON --}}\n", + "{{json outOfOfficeMessage}}\n" ] } ], @@ -1143,7 +887,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 35, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1162,7 +906,7 @@ "text": [ "Original Plan results:\n", "\n", - "I'm out of the office right now, just like Terry McGinnis, maybe I have gone fishing. In the meantime, here's a joke for you: Why did Terry McGinnis go fishing? Because he heard there were great bat-manatee sightings!\n" + "Hello, I'm currently out of the Batcave, taking a break from protecting Gotham. Here's a lighthearted joke to brighten your day: Why did Batman refuse to fight the Joker? Because he always wanted to punch up, not down! Feel free to reach out to Alfred if you have any urgent Bat-signal needs. I'll be back soon!\n" ] } ], @@ -1186,7 +930,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 36, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1205,14 +949,16 @@ "text": [ "Plan:\n", "\n", - "{{!-- Step 1: Use the HeroInfo-GetAlterEgo helper to get IronMan's alter ego --}}\n", - "{{set \"alterEgo\" (HeroInfo-GetAlterEgo \"IronMan\")}}\n", + "{{! Step 0: Extract Key Values}}\n", + "{{set \"superhero\" \"IronMan\"}}\n", "\n", - "{{!-- Step 2: Use the concat helper to create the out-of-office message --}}\n", - "{{set \"message\" (concat \"I, as \" alterEgo \", am currently out of office. I will get back to you when I'm back in. Best, \" alterEgo)}}\n", + "{{! Step 1: Get IronMan's alter ego and create the out of office message signed with his alter ego}}\n", + "{{#with (HeroInfo-GetAlterEgo input=superhero)}}\n", + " {{set \"outOfOfficeMsg\" (concat \"Out of office. Signed, \" this)}}\n", + "{{/with}}\n", "\n", - "{{!-- Step 3: Use the json helper to print out the final out-of-office message --}}\n", - "{{json message}}\n" + "{{! Step 2: Output the result}}\n", + "{{json outOfOfficeMsg}}\n" ] } ], @@ -1235,7 +981,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 37, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1254,7 +1000,7 @@ "text": [ "Complex Plan results:\n", "\n", - "I, as Tony Stark, am currently out of office. I will get back to you when I'm back in. Best, Tony Stark\n" + "Out of office. Signed, Tony Stark\n" ] } ], @@ -1286,7 +1032,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 38, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1302,7 +1048,7 @@ { "data": { "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha
  • System.Linq.Async, 6.0.1
" + "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.7.1-alpha
  • System.Linq.Async, 6.0.1
" ] }, "metadata": {}, @@ -1310,7 +1056,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.5.0-alpha\"\n", + "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.7.1-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" ] }, @@ -1327,7 +1073,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 43, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1345,18 +1091,14 @@ "using Microsoft.SemanticKernel.Connectors.OpenAI;\n", "\n", "// create the memory builder\n", - "#pragma warning disable SKEXP0003, SKEXP0011, SKEXP0052\n", + "#pragma warning disable SKEXP0001,SKEXP0003, SKEXP0011, SKEXP0010, SKEXP0050, SKEXP0052\n", "var memoryBuilder = new MemoryBuilder();\n", "\n", "// Using OpenAI\n", - "memoryBuilder.WithOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey);\n", + "//memoryBuilder.WithOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey);\n", "\n", "// Using Azure OpenAI \n", - "// memoryBuilder.WithAzureOpenAITextEmbeddingGeneration(\n", - "// AzureOpenAI.EmbeddingsModel,\n", - "// AzureOpenAI.Endpoint,\n", - "// AzureOpenAI.ApiKey,\n", - "// \"text-embedding-ada-002\");\n", + " memoryBuilder.WithAzureOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", endpoint, apiKey);\n", "\n", "memoryBuilder.WithMemoryStore(new VolatileMemoryStore());\n", "var memory = memoryBuilder.Build();" @@ -1372,7 +1114,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 44, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1405,7 +1147,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 45, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1454,7 +1196,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 46, "metadata": { "dotnet_interactive": { "language": "csharp" From f3c1c6b59a26025768f171c44835dd23bab7fa06 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Wed, 17 Apr 2024 10:33:44 -0400 Subject: [PATCH 20/25] feat: Add Spanish translations for code samples and notebooks --- notebook-en-10min.ipynb | 501 ++++++++++++++++++++++++++++++++++++++++ notebook-en.ipynb | 166 +++++++------ 2 files changed, 595 insertions(+), 72 deletions(-) create mode 100644 notebook-en-10min.ipynb diff --git a/notebook-en-10min.ipynb b/notebook-en-10min.ipynb new file mode 100644 index 0000000..d8fd3da --- /dev/null +++ b/notebook-en-10min.ipynb @@ -0,0 +1,501 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Azure Developer Days .NET 2024\n", + "\n", + "## 🦸🏻 Help your Super Hero friend with AI 🦸🏼‍♀️\n", + "\n", + "Semantic Kernel has been created to allow developers to seamlessly integrate Artificial Intelligence into their applications. To achieve this, it provides a set of features that will enable you to add models, prompts, native functions, and memories without requiring deep knowledge of AI 🥲. That's why it's said that Semantic Kernel simulates the brain 🧠 of your application.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## How to get started with Semantic Kernel\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first thing you need to be able to run Semantic Kernel in this notebook is to install the **Microsoft.SemanticKernel** library, which is currently in version **1.7.1** (I promise to keep updating 🤓). \n", + "\n", + "You can find more information about this library and its updates on the official NuGet page [here](https://www.nuget.org/packages/Microsoft.SemanticKernel).\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget: Microsoft.SemanticKernel, 1.7.1\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using Microsoft.SemanticKernel;\n", + "\n", + "var keys = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Azure OpenAI information\")).GetClearTextPassword().Split(';');\n", + "\n", + "// Create a Builder\n", + "var builder = Kernel.CreateBuilder();\n", + "// Create a chat completion service\n", + "builder.AddAzureOpenAIChatCompletion(deploymentName: keys[0], endpoint: keys[1], apiKey: keys[2]);\n", + "var kernel = builder.Build();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Semantic Kernel plugins\n", + "\n", + "Plugins are the core of Semantic Kernel. With them, you encapsulate capabilities so that they can be reusable, maintainable, and plannable (you will understand it later 🙃). There are two types: those that consist of prompt templates called **Semantic Functions** and native functions of the chosen programming language called **Native Functions**.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Semantic Functions\n", + "\n", + "When you talk to artificial intelligence models, you must do so with what is known as a *prompt*. This can range from a simple phrase to something more elaborate, allowing the model to understand not only what we want but also how we want it. If you take a look at the official documentation, it defines this type of function as the mouth 👄 and ears 👂🏻 of your brain 🧠. 🤖🌐\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As part of this repo, you have a folder called **SemanticFunctions** that has different functions of this type:\n", + "\n", + "- **FunPlugin**: This allows us to ask the model to make jokes about heroes under certain conditions, through the **Joke** function.\n", + "- **WritePlugin**: To show you that within a plugin you can have different functions, in this directory we have two related to the art of writing: the first one, **OOF**, allows us to generate the \"Out of Office\" 🏢📧 message for superheroes and the second **StoryGen** will help us create stories, also about superheroes 🦸🏻‍♂️🦸🏻‍♀️.\n", + "\n", + "For our kernel to know that these plugins are available, you first need to get the path of the directory:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using System.IO;\n", + "\n", + "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"FunPlugIn\");\n", + "\n", + "// Load the FunPlugin from the Plugins Directory\n", + "var funPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectory);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Tell me a April's fools joke\",\n", + " [\"hero\"] = \"Batman\"\n", + "};\n", + "var result = await kernel.InvokeAsync(funPluginFunctions[\"Joke\"], variables);\n", + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the same way, we can use the functions included in **WriterPlugin**:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Load the WriterPlugin from the Plugins Directory\n", + "var pluginsDirectoryWriter = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"WriterPlugin\");\n", + "\n", + "var writerPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectoryWriter);\n", + "\n", + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Tell me a Spring Story\",\n", + " [\"hero\"] = \"Superman\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", + "Console.WriteLine(result);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or even to create messages for when the heroes 🦸🏻‍♀️ are on vacation ✈️🚢🌴:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var variables = new KernelArguments() {\n", + " [\"input\"] = \"Create an OOF for Christmas\",\n", + " [\"hero\"] = \"Hulk\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOF\"], variables);\n", + "Console.WriteLine(result.GetValue());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Native Functions\n", + "\n", + "While semantic functions allow us to define and reuse prompts, **with native functions you can make the semantic kernel call functions written in C# or Python**, for tasks that go beyond a call through a prompt.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this example, I'm going to use an API called **SuperHero API**, which requires an API key. You can get it from their website: [https://superheroapi.com/](https://superheroapi.com/)\n", + "\n", + "Now, to load a native function, we must add this before we build the Kernel.\n", + "\n", + "Let's create a new Super Hero Info class and add it as a Plugin.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#load \"NativeFunctions/HeroInfo.cs\"\n", + "\n", + "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();\n", + "\n", + "var heroInfo = new HeroInfo(superHeroApiKey);\n", + "builder.Plugins.AddFromObject(heroInfo, \"HeroInfo\");\n", + "Kernel kernel = builder.Build();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The builder now can interact with the local function. Let's make a call to get the alter ego of a super hero." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var kernelArgs = new KernelArguments()\n", + "{\n", + " [\"input\"] = \"Batman\"\n", + "};\n", + "\n", + "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", + "Console.WriteLine(result);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Planner\n", + "\n", + "So far, all the plugins you have seen have been executed intentionally. That is, no one has chosen them for you and you can run them based on your needs. However, this is the most *static* way to interact with Semantic Kernel. There is another option called **Planner** that will leave you astounded 😮\n", + "\n", + "Planner is a function that takes a user's request and returns a plan on how to carry out the request. To do this, it uses AI to combine the plugins registered in the core and recombine them into a series of steps that complete a goal.\n", + "\n", + "
\n", + " \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.7.1-preview\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we are ready to create a planner." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "using System.Text.Json;\n", + "using Microsoft.SemanticKernel.Planning.Handlebars;\n", + "\n", + "#pragma warning disable SKEXP0060\n", + "var planner = new HandlebarsPlanner();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var ask = @\"I would like you to tell me a joke about Batman, \" + \n", + "\"and with that joke, create an out-of-office message using the joke.\";\n", + "\n", + "#pragma warning disable SKEXP0060\n", + "var originalPlan = await planner.CreatePlanAsync(kernel, ask);\n", + "\n", + "Console.WriteLine(\"Original plan:\\n\");\n", + "Console.WriteLine(originalPlan);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// executing the plan\n", + "#pragma warning disable SKEXP0060\n", + "var originalPlanResult = await originalPlan.InvokeAsync(kernel, new KernelArguments());\n", + "\n", + "Console.WriteLine(\"Original Plan results:\\n\");\n", + "Console.WriteLine(originalPlanResult.ToString());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Advanced Scenario\n", + "\n", + "The kernel already has the plugins loaded, and the function, let's see if it can solve a more complex example:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "var ask_complex = @\"I would like you to find out IronMan's alter ego,\" + \n", + "\" and create an out of office message for IronMan, signing it with his alter ego.\";\n", + "\n", + "#pragma warning disable SKEXP0060\n", + "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", + "\n", + "Console.WriteLine(\"Plan:\\n\");\n", + "Console.WriteLine(plan_complex);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#pragma warning disable SKEXP0060\n", + "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", + "\n", + "Console.WriteLine(\"Complex Plan results:\\n\");\n", + "Console.WriteLine(complexPlanResult.ToString());" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "python" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 5481f08..306f4db 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -32,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -44,7 +44,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 1.7.1
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.7.1\"" ] @@ -58,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -136,8 +146,14 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 10, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } @@ -163,7 +179,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 11, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -220,7 +236,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -248,7 +264,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 13, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -275,7 +291,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 14, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -359,7 +375,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 15, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -376,9 +392,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why did the hero bring a ladder to the bar?\n", + "Why don't superheroes ever get scared at Halloween?\n", "\n", - "Because he heard the drinks were on the house!\r\n" + "Because they have no \"fright\" reflex!\r\n" ] } ], @@ -395,7 +411,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 16, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -410,8 +426,8 @@ "outputs": [], "source": [ "var variables = new KernelArguments() {\n", - " [\"input\"] = \"Tell me a Christmas joke\",\n", - " [\"hero\"] = \"Ironman\"\n", + " [\"input\"] = \"Tell me a April's fools joke\",\n", + " [\"hero\"] = \"Batman\"\n", "};" ] }, @@ -424,7 +440,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 17, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -450,7 +466,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 18, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -467,9 +483,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why did Ironman get coal in his stocking for Christmas?\n", + "Why did Batman bring a bat to fight crime on April Fool's Day?\n", "\n", - "Because he's always \"ironing\" out his problems!\r\n" + "Because he heard it was the perfect time to play \"the ultimate joke on crime!\"\r\n" ] } ], @@ -486,7 +502,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -515,7 +531,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -532,22 +548,22 @@ "name": "stdout", "output_type": "stream", "text": [ - "Once upon a time, in a city far, far away, there was a man named Tony Stark. He was a brilliant scientist and inventor, but he was also known as the fearless superhero Ironman. It was a snowy Christmas Eve and the city was bustling with holiday cheer. People were bustling around, buying last-minute gifts and decorations for their homes.\n", + "One sunny spring day, Superman was flying above the city, keeping an eye out for any trouble. As he soared through the sky, he noticed a group of children playing in the park below. He decided to swoop down and join in the fun.\n", "\n", - "Meanwhile, Tony Stark was busy in his lab, working on his latest invention. As he tinkered away, he received a distress call from the city. It seems that a group of villains were causing chaos and ruining Christmas for everyone. Without hesitation, Tony suited up in his Ironman armor and flew out to save the day.\n", + "The kids were amazed to see their favorite superhero join them. They all ran around, playing games and laughing as Superman joined in with his super strength and speed. It felt good for Superman to take a break from saving the world and just enjoy a carefree moment with the children.\n", "\n", - "As Ironman arrived at the scene, he saw the villains wreaking havoc, stealing presents, and causing chaos. Using his special powers and gadgets, Ironman fought valiantly to protect the city and its people. The battle was fierce, but Ironman was determined to save Christmas for everyone.\n", + "As the afternoon turned to evening, the sun began to set and it was time for Superman to bid farewell to his new friends. The children waved goodbye, thanking Superman for the best day ever. With a warm smile, Superman flew back into the sky, ready to continue his duty of keeping the city safe.\n", "\n", - "Finally, Ironman managed to defeat the villains and restore peace to the city. The people cheered and thanked him for his bravery. In the end, Ironman flew back to his lab, satisfied that he had saved Christmas for the city.\n", + "As he flew into the sunset, Superman couldn't help but feel grateful for the simple joy of spending time with the kids. It reminded him of the importance of embracing the lighter moments in life, even amidst the chaos of being a hero.\n", "\n", - "As Tony Stark took off his armor and sat down to rest, he reflected on the true meaning of Christmas. It wasn't about the presents or the decorations, but about coming together to help and protect others. With a smile on his face, Tony felt proud to have been able to spread the spirit of Christmas and make the city a little brighter. And with that, he wished everyone a merry Christmas and a happy new year. 🎄🦸‍♂️✨\r\n" + "With that, Superman continued to watch over the city, knowing that he could always find joy in the little things. 🌞👦🦸‍♂️🌻🌇\r\n" ] } ], "source": [ "var variables = new KernelArguments() {\n", - " [\"input\"] = \"Tell me a Christmas Story\",\n", - " [\"hero\"] = \"Ironman\"\n", + " [\"input\"] = \"Tell me a Spring Story\",\n", + " [\"hero\"] = \"Superman\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", @@ -563,7 +579,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -580,15 +596,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "Hey there! 👋\n", + "Subject: Out of Office: Hulk Smashin' and Relaxin' for the Holidays\n", + "\n", + "Hey there!\n", + "\n", + "Thanks for reaching out! The big guy is currently out of the office and taking some time to unwind for the holiday season. 🎄 You see, all this smashing and saving the world can be pretty exhausting, so the Hulk needs to recharge his green batteries.\n", "\n", - "Thank you for reaching out! I'm currently out of the office, smashing some bad guys and saving the world. 💪💥 I won't be able to respond to any messages until I return.\n", + "In the meantime, if you need immediate superhero assistance, you can contact my good friend, Thor. He's always ready to lend a hand (and his mighty hammer) in my absence.\n", "\n", - "In my absence, you can reach out to my super friend Thor, the God of Thunder, for any help or assistance. ⚡\n", + "Don't worry, I'll be back to smashing and fighting for justice in no time! Until then, have a smashing good time and catch you on the flip side!\n", "\n", - "Sorry for any inconvenience, but I promise I'll be back to help soon! Until then, stay safe and remember - Hulk is always watching out for you! 👀\n", + "Smashfully yours,\n", "\n", - "Goodbye for now! 🌟\r\n" + "The Hulk 💥\r\n" ] } ], @@ -643,7 +663,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -671,7 +691,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -701,7 +721,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -718,14 +738,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "Bruce Banner\r\n" + "Diana Prince\r\n" ] } ], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", - " [\"input\"] = \"Hulk\"\n", + " [\"input\"] = \"Wonder Woman\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", @@ -768,7 +788,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -804,7 +824,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -835,7 +855,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -855,12 +875,12 @@ "Original plan:\n", "\n", "{{!-- Step 0: Extract Key Values --}}\n", - "{{set \"joke\" \"Why did Batman refuse to fight the Joker? Because he always wanted to punch up, not down!\"}}\n", + "{{set \"joke\" \"Why did Batman and Robin invest in the Batmobile? They were tired of the Batcycle.\"}}\n", "\n", - "{{!-- Step 1: Create the out-of-office message using the joke --}}\n", - "{{set \"outOfOfficeMessage\" (concat \"Hello, I'm currently out of the Batcave, taking a break from protecting Gotham. Here's a lighthearted joke to brighten your day: \" joke \" Feel free to reach out to Alfred if you have any urgent Bat-signal needs. I'll be back soon!\")}}\n", + "{{!-- Step 1: Create out-of-office message using the joke --}}\n", + "{{set \"outOfOfficeMessage\" (concat \"Hello, I'm currently out of the Batcave because I heard a good joke: \" joke \" Please leave a message and I'll get back to you when I return. Thanks!\")}}\n", "\n", - "{{!-- Step 2: Output the final message as JSON --}}\n", + "{{!-- Step 2: Print the out-of-office message as JSON --}}\n", "{{json outOfOfficeMessage}}\n" ] } @@ -887,7 +907,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -906,7 +926,7 @@ "text": [ "Original Plan results:\n", "\n", - "Hello, I'm currently out of the Batcave, taking a break from protecting Gotham. Here's a lighthearted joke to brighten your day: Why did Batman refuse to fight the Joker? Because he always wanted to punch up, not down! Feel free to reach out to Alfred if you have any urgent Bat-signal needs. I'll be back soon!\n" + "Hello, I'm currently out of the Batcave because I heard a good joke: Why did Batman and Robin invest in the Batmobile? They were tired of the Batcycle. Please leave a message and I'll get back to you when I return. Thanks!\n" ] } ], @@ -930,7 +950,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 29, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -952,13 +972,10 @@ "{{! Step 0: Extract Key Values}}\n", "{{set \"superhero\" \"IronMan\"}}\n", "\n", - "{{! Step 1: Get IronMan's alter ego and create the out of office message signed with his alter ego}}\n", - "{{#with (HeroInfo-GetAlterEgo input=superhero)}}\n", - " {{set \"outOfOfficeMsg\" (concat \"Out of office. Signed, \" this)}}\n", - "{{/with}}\n", - "\n", - "{{! Step 2: Output the result}}\n", - "{{json outOfOfficeMsg}}\n" + "{{! Step 1: Use Custom Helper to Get Alter Ego and Create Message}}\n", + "{{set \"alterEgo\" (HeroInfo-GetAlterEgo input=superhero)}}\n", + "{{set \"message\" (concat \"Out of office message: I'm out saving the world! - \" alterEgo)}}\n", + "{{json message}}\n" ] } ], @@ -981,7 +998,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 30, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1000,7 +1017,7 @@ "text": [ "Complex Plan results:\n", "\n", - "Out of office. Signed, Tony Stark\n" + "Out of office message: I'm out saving the world! - Tony Stark\n" ] } ], @@ -1032,7 +1049,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 31, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1073,7 +1090,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 32, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1114,7 +1131,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 37, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1135,7 +1152,8 @@ "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info2\", text: \"The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\");\n", "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info3\", text: \"Bruno's favourite super hero is Invincible\");\n", "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"The last super hero movie watched by Bruno was Aquaman II\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");" + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info6\", text: \"Alixia don't like the super hero movie: The Batman\");" ] }, { @@ -1147,7 +1165,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 38, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1164,7 +1182,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "what is Bruno's favourite super hero? Bruno's favourite super hero is Invincible\n", + "What is Bruno's favourite super hero? Bruno's favourite super hero is Invincible\n", + "How about Alixia? Alixia don't like the super hero movie: The Batman\n", "what was the last movie watched by Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", "Which is the prefered super hero for Gisela? Gisela's favourite super hero is Batman\n", "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n" @@ -1174,7 +1193,8 @@ "source": [ "var questions = new[]\n", "{\n", - " \"what is Bruno's favourite super hero?\",\n", + " \"What is Bruno's favourite super hero?\",\n", + " \"How about Alixia?\",\n", " \"what was the last movie watched by Gisela?\",\n", " \"Which is the prefered super hero for Gisela?\",\n", " \"Did Bruno watched a super hero movie in the past, which was the last one?\"\n", @@ -1196,7 +1216,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 41, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1213,11 +1233,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "¿Cuál es el superhéroe favorito de Bruno? Bruno's favourite super hero is Invincible\n", - "¿Cuál fue la última película vista por Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", - "¿Cuál es el superhéroe preferido de Gisela? Gisela's favourite super hero is Batman\n", - "¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última? The last super hero movie watched by Bruno was Aquaman II\n", - "Cual es la pelicula que no le gusta a Bruno? Bruno don't like the super hero movie: Eternals\n" + "¿Cuál es el superhéroe favorito de Bruno? Bruno's favourite super hero is Invincible info3\n", + "¿Cuál fue la última película vista por Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3 info2\n", + "¿Cuál es el superhéroe preferido de Gisela? Gisela's favourite super hero is Batman info1\n", + "¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última? The last super hero movie watched by Bruno was Aquaman II info4\n", + "Cual es la pelicula que no le gusta a Bruno? Bruno don't like the super hero movie: Eternals info5\n", + "Sabes algo de Alixia? Alixia don't like the super hero movie: The Batman info6\n" ] } ], @@ -1228,13 +1249,14 @@ " \"¿Cuál fue la última película vista por Gisela?\",\n", " \"¿Cuál es el superhéroe preferido de Gisela?\",\n", " \"¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última?\",\n", - " \"Cual es la pelicula que no le gusta a Bruno?\"\n", + " \"Cual es la pelicula que no le gusta a Bruno?\",\n", + " \"Sabes algo de Alixia?\"\n", "};\n", "\n", "foreach (var q in preguntas)\n", "{\n", " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", - " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text + \" \" + response?.Metadata.Id);\n", "}" ] } From 7105d86a3e69a61f2501b1a052c44c8458ede331 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Wed, 17 Apr 2024 10:37:02 -0400 Subject: [PATCH 21/25] chore: Update paths for plugin directories in notebook --- notebook-en-10min.ipynb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/notebook-en-10min.ipynb b/notebook-en-10min.ipynb index d8fd3da..b7888ef 100644 --- a/notebook-en-10min.ipynb +++ b/notebook-en-10min.ipynb @@ -134,7 +134,8 @@ "source": [ "using System.IO;\n", "\n", - "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"FunPlugIn\");\n", + "var pluginsDirectory = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \n", + " \"SemanticFunctions\", \"FunPlugIn\");\n", "\n", "// Load the FunPlugin from the Plugins Directory\n", "var funPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectory);" @@ -182,7 +183,8 @@ "outputs": [], "source": [ "// Load the WriterPlugin from the Plugins Directory\n", - "var pluginsDirectoryWriter = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \"SemanticFunctions\", \"WriterPlugin\");\n", + "var pluginsDirectoryWriter = Path.Combine(System.IO.Directory.GetCurrentDirectory(), \n", + " \"SemanticFunctions\", \"WriterPlugin\");\n", "\n", "var writerPluginFunctions = kernel.ImportPluginFromPromptDirectory(pluginsDirectoryWriter);\n", "\n", @@ -269,7 +271,8 @@ "source": [ "#load \"NativeFunctions/HeroInfo.cs\"\n", "\n", - "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();\n", + "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel\n", + " .GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();\n", "\n", "var heroInfo = new HeroInfo(superHeroApiKey);\n", "builder.Plugins.AddFromObject(heroInfo, \"HeroInfo\");\n", From 7fb04110eb83f1efeff774dc3572ee1c32d19568 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Thu, 18 Apr 2024 12:58:01 -0400 Subject: [PATCH 22/25] chore: Update paths for plugin directories in notebook --- NativeFunctions/sampleResponse.json | 155 ++++++++++++++++++++++++++++ Utils/consoleUtils.cs | 44 ++++++++ notebook-en-10min.ipynb | 120 ++++++++++++++++++--- 3 files changed, 306 insertions(+), 13 deletions(-) create mode 100644 NativeFunctions/sampleResponse.json create mode 100644 Utils/consoleUtils.cs diff --git a/NativeFunctions/sampleResponse.json b/NativeFunctions/sampleResponse.json new file mode 100644 index 0000000..0995503 --- /dev/null +++ b/NativeFunctions/sampleResponse.json @@ -0,0 +1,155 @@ +{ + "response": "success", + "results-for": "batman", + "results": [ + { + "id": "69", + "name": "Batman", + "powerstats": { + "intelligence": "81", + "strength": "40", + "speed": "29", + "durability": "55", + "power": "63", + "combat": "90" + }, + "biography": { + "full-name": "Terry McGinnis", + "alter-egos": "No alter egos found.", + "aliases": [ + "Batman II", + "The Tomorrow Knight", + "The second Dark Knight", + "The Dark Knight of Tomorrow", + "Batman Beyond" + ], + "place-of-birth": "Gotham City, 25th Century", + "first-appearance": "Batman Beyond #1", + "publisher": "DC Comics", + "alignment": "good" + }, + "appearance": { + "gender": "Male", + "race": "Human", + "height": [ + "5'10", + "178 cm" + ], + "weight": [ + "170 lb", + "77 kg" + ], + "eye-color": "Blue", + "hair-color": "Black" + }, + "work": { + "occupation": "-", + "base": "21st Century Gotham City" + }, + "connections": { + "group-affiliation": "Batman Family, Justice League Unlimited", + "relatives": "Bruce Wayne (biological father), Warren McGinnis (father, deceased), Mary McGinnis (mother), Matt McGinnis (brother)" + }, + "image": { + "url": "https://www.superherodb.com/pictures2/portraits/10/100/10441.jpg" + } + }, + { + "id": "70", + "name": "Batman", + "powerstats": { + "intelligence": "100", + "strength": "26", + "speed": "27", + "durability": "50", + "power": "47", + "combat": "100" + }, + "biography": { + "full-name": "Bruce Wayne", + "alter-egos": "No alter egos found.", + "aliases": [ + "Insider", + "Matches Malone" + ], + "place-of-birth": "Crest Hill, Bristol Township; Gotham County", + "first-appearance": "Detective Comics #27", + "publisher": "DC Comics", + "alignment": "good" + }, + "appearance": { + "gender": "Male", + "race": "Human", + "height": [ + "6'2", + "188 cm" + ], + "weight": [ + "210 lb", + "95 kg" + ], + "eye-color": "blue", + "hair-color": "black" + }, + "work": { + "occupation": "Businessman", + "base": "Batcave, Stately Wayne Manor, Gotham City; Hall of Justice, Justice League Watchtower" + }, + "connections": { + "group-affiliation": "Batman Family, Batman Incorporated, Justice League, Outsiders, Wayne Enterprises, Club of Heroes, formerly White Lantern Corps, Sinestro Corps", + "relatives": "Damian Wayne (son), Dick Grayson (adopted son), Tim Drake (adopted son), Jason Todd (adopted son), Cassandra Cain (adopted ward)\nMartha Wayne (mother, deceased), Thomas Wayne (father, deceased), Alfred Pennyworth (former guardian), Roderick Kane (grandfather, deceased), Elizabeth Kane (grandmother, deceased), Nathan Kane (uncle, deceased), Simon Hurt (ancestor), Wayne Family" + }, + "image": { + "url": "https://www.superherodb.com/pictures2/portraits/10/100/639.jpg" + } + }, + { + "id": "71", + "name": "Batman II", + "powerstats": { + "intelligence": "88", + "strength": "11", + "speed": "33", + "durability": "28", + "power": "36", + "combat": "100" + }, + "biography": { + "full-name": "Dick Grayson", + "alter-egos": "Nightwing, Robin", + "aliases": [ + "Dick Grayson" + ], + "place-of-birth": "-", + "first-appearance": "-", + "publisher": "Nightwing", + "alignment": "good" + }, + "appearance": { + "gender": "Male", + "race": "Human", + "height": [ + "5'10", + "178 cm" + ], + "weight": [ + "175 lb", + "79 kg" + ], + "eye-color": "Blue", + "hair-color": "Black" + }, + "work": { + "occupation": "-", + "base": "Gotham City; formerly Bludhaven, New York City" + }, + "connections": { + "group-affiliation": "Justice League Of America, Batman Family", + "relatives": "John Grayson (father, deceased), Mary Grayson (mother, deceased), Bruce Wayne / Batman (adoptive father), Damian Wayne / Robin (foster brother), Jason Todd / Red Hood (adoptive brother), Tim Drake / Red Robin (adoptive brother), Cassandra Cain / Batgirl IV (adoptive sister)" + }, + "image": { + "url": "https://www.superherodb.com/pictures2/portraits/10/100/1496.jpg" + } + } + ] +} \ No newline at end of file diff --git a/Utils/consoleUtils.cs b/Utils/consoleUtils.cs new file mode 100644 index 0000000..97c3678 --- /dev/null +++ b/Utils/consoleUtils.cs @@ -0,0 +1,44 @@ + +/// +/// Writes a long story to the console, splitting it into multiple lines if necessary. +/// +/// The long story to write. +public static void WriteLongStory(string story) +{ + var lines = SplitStory(story); + + foreach (var line in lines) + { + Console.WriteLine(line); + } +} + +/// +/// Splits a story into multiple lines, ensuring that each line does not exceed 80 characters. +/// +/// The story to split. +/// A list of lines containing the split story. +public static List SplitStory(string story) +{ + var words = story.Split(' '); + var lines = new List(); + var currentLine = ""; + + foreach (var word in words) + { + if ((currentLine + word).Length > 80) + { + lines.Add(currentLine.Trim()); + currentLine = ""; + } + + currentLine += word + " "; + } + + if (!string.IsNullOrWhiteSpace(currentLine)) + { + lines.Add(currentLine.Trim()); + } + + return lines; +} \ No newline at end of file diff --git a/notebook-en-10min.ipynb b/notebook-en-10min.ipynb index b7888ef..5ecd046 100644 --- a/notebook-en-10min.ipynb +++ b/notebook-en-10min.ipynb @@ -15,6 +15,63 @@ "
" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Environment variables\n", + "\n", + "Let's start importing the keys and utils that we will need for this demo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// Azure OpenAI information\n", + "var keys = (await Microsoft.DotNet.Interactive.Kernel\n", + " .GetPasswordAsync(\"Give me your Azure OpenAI information\"))\n", + " .GetClearTextPassword().Split(';');\n", + "\n", + "var azureOpenAIDeploymentName = keys[0];\n", + "var azureOpenAIEndpoint = keys[1];\n", + "var azureOpenAIKey = keys[2];" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "// get super hero api key\n", + "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel\n", + " .GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#load \"Utils/consoleUtils.cs\"" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -69,12 +126,12 @@ "source": [ "using Microsoft.SemanticKernel;\n", "\n", - "var keys = (await Microsoft.DotNet.Interactive.Kernel.GetPasswordAsync(\"Give me your Azure OpenAI information\")).GetClearTextPassword().Split(';');\n", - "\n", "// Create a Builder\n", "var builder = Kernel.CreateBuilder();\n", - "// Create a chat completion service\n", - "builder.AddAzureOpenAIChatCompletion(deploymentName: keys[0], endpoint: keys[1], apiKey: keys[2]);\n", + "builder.AddAzureOpenAIChatCompletion(\n", + " deploymentName: azureOpenAIDeploymentName, \n", + " endpoint: azureOpenAIEndpoint, \n", + " apiKey: azureOpenAIKey);\n", "var kernel = builder.Build();" ] }, @@ -145,6 +202,12 @@ "cell_type": "code", "execution_count": null, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } @@ -206,7 +269,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -218,7 +281,35 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello there!\n", + "\n", + "🦸‍♂️ Hulk here, smashing through emails and saving the day!\n", + "\n", + "I'm\n", + "currently out of the office to celebrate the holiday season with my friends and\n", + "family. 🎄 Don't worry, I'll be back to smash some more villains soon!\n", + "\n", + "In the\n", + "meantime, if you need immediate superhero help, please contact my good friend\n", + "Thor. He's always ready to lend a helping hand...or hammer! ⚡️\n", + "\n", + "Thank you for\n", + "your understanding and patience. I'll respond to your messages as soon as I\n", + "return!\n", + "\n", + "👊 Stay incredible and have a smashing good time! 👊\n", + "\n", + "Best\n", + "regards,\n", + "Hulk\n" + ] + } + ], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Create an OOF for Christmas\",\n", @@ -226,7 +317,7 @@ "};\n", "\n", "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOF\"], variables);\n", - "Console.WriteLine(result.GetValue());" + "WriteLongStory(result.GetValue());" ] }, { @@ -271,9 +362,6 @@ "source": [ "#load \"NativeFunctions/HeroInfo.cs\"\n", "\n", - "var superHeroApiKey = (await Microsoft.DotNet.Interactive.Kernel\n", - " .GetPasswordAsync(\"Give me your Super Hero Api key\")).GetClearTextPassword();\n", - "\n", "var heroInfo = new HeroInfo(superHeroApiKey);\n", "builder.Plugins.AddFromObject(heroInfo, \"HeroInfo\");\n", "Kernel kernel = builder.Build();" @@ -304,7 +392,7 @@ "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", - " [\"input\"] = \"Batman\"\n", + " [\"input\"] = \"Wonder Woman\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", @@ -379,6 +467,12 @@ "cell_type": "code", "execution_count": null, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } @@ -416,7 +510,7 @@ "var originalPlanResult = await originalPlan.InvokeAsync(kernel, new KernelArguments());\n", "\n", "Console.WriteLine(\"Original Plan results:\\n\");\n", - "Console.WriteLine(originalPlanResult.ToString());" + "WriteLongStory(originalPlanResult.ToString());" ] }, { @@ -474,7 +568,7 @@ "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", "\n", "Console.WriteLine(\"Complex Plan results:\\n\");\n", - "Console.WriteLine(complexPlanResult.ToString());" + "WriteLongStory(complexPlanResult.ToString());" ] } ], From c8ba832eec05f528b0547d933ce417b1f2defe95 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Mon, 27 May 2024 14:41:39 -0400 Subject: [PATCH 23/25] update nuget pkgs to latest versions and test the code --- notebook-en-10min.ipynb | 18 +++ notebook-en.ipynb | 307 +++++++++++++++++++++++++++------------- 2 files changed, 227 insertions(+), 98 deletions(-) diff --git a/notebook-en-10min.ipynb b/notebook-en-10min.ipynb index 5ecd046..c31d101 100644 --- a/notebook-en-10min.ipynb +++ b/notebook-en-10min.ipynb @@ -28,6 +28,12 @@ "cell_type": "code", "execution_count": null, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } @@ -48,6 +54,12 @@ "cell_type": "code", "execution_count": null, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } @@ -63,6 +75,12 @@ "cell_type": "code", "execution_count": 25, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } diff --git a/notebook-en.ipynb b/notebook-en.ipynb index 306f4db..e11b199 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -24,7 +24,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The first thing you need to be able to run Semantic Kernel in this notebook is to install the **Microsoft.SemanticKernel** library, which is currently in version **1.7.1** (I promise to keep updating 🤓). \n", + "The first thing you need to be able to run Semantic Kernel in this notebook is to install the **Microsoft.SemanticKernel** library, which is currently in version **1.13.0** (I promise to keep updating 🤓). \n", "\n", "You can find more information about this library and its updates on the official NuGet page [here](https://www.nuget.org/packages/Microsoft.SemanticKernel).\n", "\n" @@ -32,7 +32,20 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 12, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#load \"Utils/consoleUtils.cs\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -44,19 +57,9 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel, 1.7.1
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 1.7.1\"" + "#r \"nuget: Microsoft.SemanticKernel, 1.13.0\"" ] }, { @@ -68,7 +71,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -146,7 +149,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -179,7 +182,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 4, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -236,7 +239,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -264,7 +267,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -291,7 +294,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 7, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -375,7 +378,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -392,9 +395,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why don't superheroes ever get scared at Halloween?\n", + "Why did the scarecrow win an award?\n", "\n", - "Because they have no \"fright\" reflex!\r\n" + "Because he was outstanding in his field!\r\n" ] } ], @@ -411,7 +414,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -427,7 +430,7 @@ "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Tell me a April's fools joke\",\n", - " [\"hero\"] = \"Batman\"\n", + " [\"hero\"] = \"Hulk\"\n", "};" ] }, @@ -440,7 +443,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 10, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -466,7 +469,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 14, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -483,14 +486,31 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why did Batman bring a bat to fight crime on April Fool's Day?\n", + "One April Fool's Day, Tony Stark thought it would be hilarious to prank the\n", + "Hulk. He outfitted Bruce Banner's lab with voice-activated lights that responded\n", + "to Hulk's catchphrase, \"HULK SMASH!\"\n", + "\n", + "Later that evening, Bruce walked into his\n", + "lab, and the lights were off. Slightly confused, he muttered, \"Hulk smash?\" The\n", + "lights flickered on. Amused, he tried again, \"HULK SMASH!\" The lights dimmed and\n", + "then brightened. Intrigued, he continued, \"Hulk Smash?\" The lights danced around\n", + "like they were at a disco.\n", + "\n", + "Just then, Tony walked in with a smug grin. Bruce\n", + "looked at him and said, \"Nice prank, Tony. But remember, when Hulk smashes, Hulk\n", + "REALLY smashes.\"\n", + "\n", + "Then the entire building experienced a sudden and unexpected\n", + "power outage. Tony turned pale as Bruce flashed a mischievous smile. \"April\n", + "Fool's,\" Bruce said calmly, brandishing a remote control.\n", "\n", - "Because he heard it was the perfect time to play \"the ultimate joke on crime!\"\r\n" + "Turns out, Iron Man\n", + "isn't the only one who knows how to pull a prank.\n" ] } ], "source": [ - "Console.WriteLine(result.GetValue());" + "WriteLongStory(result.GetValue());" ] }, { @@ -502,7 +522,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 15, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -531,7 +551,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -548,26 +568,86 @@ "name": "stdout", "output_type": "stream", "text": [ - "One sunny spring day, Superman was flying above the city, keeping an eye out for any trouble. As he soared through the sky, he noticed a group of children playing in the park below. He decided to swoop down and join in the fun.\n", + "Sure! Here are the stories:\n", + "\n", + "### 🦇 Batman and the Enchanted Forest 🌳\n", + "\n", + "####\n", + "Beginning 🌆\n", + "As the sun set over Gotham City, the Bat-Signal shone brightly in\n", + "the sky. 🦇 Batman, always ready to protect his city, suited up and leaped into\n", + "the Batmobile. Tonight, the signal led him not to the usual villains but to a\n", + "mysterious, enchanted forest that had appeared overnight in the heart of Gotham.\n", + "🌲\n", + "\n", + "#### Middle 🌕\n", + "Batman ventured into the forest, finding it filled with\n", + "glowing plants and strange creatures. Suddenly, he heard a child's cry for help.\n", + "🛡️ With heightened senses, he maneuvered through dense foliage until he reached\n", + "a clearing where an enormous, enchanting tree stood. Its ancient bark was\n", + "inscribed with runes, and at its base was a young girl trapped by thick vines.\n", + "\"Fear not, I am here to help,\" Batman assured. Using his bat-tools, he\n", + "skillfully cut through the magical vines, freeing the girl. She revealed that\n", + "the forest had been cursed by an evil sorcerer, and only a pure heart could lift\n", + "the spell.\n", + "\n", + "#### End 🌟\n", + "Batman knew what had to be done. Guided by the girl's\n", + "knowledge, he approached the enchanted tree and placed his hand on its runes.\n", + "His pure intent and unwavering commitment to justice began to break the curse.\n", + "The forest brightened, the creatures became friendly, and the thicket vanished.\n", + "Batman escorted the girl back to Gotham, where the morning sun brought new hope.\n", + "🌞 \n", + "\n", + "Gotham City was safe once again, thanks to its ever-vigilant guardian. As\n", + "Batman disappeared into the dawn, he knew his true strength lay not just in his\n", + "skills, but in the purity of his heart. 🦇🌟\n", "\n", - "The kids were amazed to see their favorite superhero join them. They all ran around, playing games and laughing as Superman joined in with his super strength and speed. It felt good for Superman to take a break from saving the world and just enjoy a carefree moment with the children.\n", + "---\n", "\n", - "As the afternoon turned to evening, the sun began to set and it was time for Superman to bid farewell to his new friends. The children waved goodbye, thanking Superman for the best day ever. With a warm smile, Superman flew back into the sky, ready to continue his duty of keeping the city safe.\n", + "### 🐶 Daisy and 🐱 Whiskers:\n", + "An Unlikely Friendship\n", "\n", - "As he flew into the sunset, Superman couldn't help but feel grateful for the simple joy of spending time with the kids. It reminded him of the importance of embracing the lighter moments in life, even amidst the chaos of being a hero.\n", + "#### Beginning 🌈\n", + "In a quiet countryside lived two pets\n", + "with very different lives. Daisy, a playful Golden Retriever, loved to chase\n", + "butterflies and roll in the grass. 🐶 Whiskers, a curious tabby cat, preferred\n", + "climbing trees and napping in sun-drenched spots. 🐱 They had never met but were\n", + "destined to become great friends.\n", "\n", - "With that, Superman continued to watch over the city, knowing that he could always find joy in the little things. 🌞👦🦸‍♂️🌻🌇\r\n" + "#### Middle 🌤️\n", + "One sunny day, Daisy was\n", + "chasing a butterfly that led her to the edge of her yard, right where Whiskers\n", + "was perched on a low branch. They eyed each other curiously. Daisy barked in\n", + "excitement, causing Whiskers to arch his back defensively. \n", + "\n", + "But soon, Daisy\n", + "laid down and wagged her tail in a friendly invitation. Whiskers hesitated, then\n", + "hopped down cautiously. They started to explore the countryside together; Daisy\n", + "showed Whiskers her favorite fields while Whiskers introduced Daisy to the best\n", + "climbing spots.\n", + "\n", + "#### End 🌟\n", + "Days turned into weeks, and the two became\n", + "inseparable. They shared their adventures, from catching frogs by the pond to\n", + "watching the stars at night. As different as they were, Daisy and Whiskers found\n", + "joy in each other's company and learned the true meaning of friendship.\n", + "🐾🐶🐱\n", + "\n", + "In their little corner of the world, the unlikely pair stood as a\n", + "testament to how beautiful and enriching friendships can be, no matter how\n", + "different we are. 🌈💖\n" ] } ], "source": [ "var variables = new KernelArguments() {\n", - " [\"input\"] = \"Tell me a Spring Story\",\n", - " [\"hero\"] = \"Superman\"\n", + " [\"input\"] = \"Tell me a story about 2 pets that meet each other\",\n", + " [\"hero\"] = \"Batman\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", - "Console.WriteLine(result);" + "WriteLongStory(result.GetValue());" ] }, { @@ -579,7 +659,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -596,19 +676,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "Subject: Out of Office: Hulk Smashin' and Relaxin' for the Holidays\n", + "**Subject: Hulk on Holiday! 🎅🎄**\n", "\n", - "Hey there!\n", + "Hello there,\n", "\n", - "Thanks for reaching out! The big guy is currently out of the office and taking some time to unwind for the holiday season. 🎄 You see, all this smashing and saving the world can be pretty exhausting, so the Hulk needs to recharge his green batteries.\n", + "It's time for Hulk to take a\n", + "well-deserved break! 💪😁 This big, green, smashing machine is off celebrating\n", + "Christmas and enjoying some rest until (date you're returning). Even heroes need\n", + "some downtime to recharge! 🌟\n", "\n", - "In the meantime, if you need immediate superhero assistance, you can contact my good friend, Thor. He's always ready to lend a hand (and his mighty hammer) in my absence.\n", + "But don't you worry! While Hulk is away, our\n", + "friendly neighborhood Spider-Man 🕸️🕷️ has got you covered. If you need any\n", + "assistance, feel free to reach out to Spidey. He's got the web-slinging skills\n", + "to handle any situation! \n", "\n", - "Don't worry, I'll be back to smashing and fighting for justice in no time! Until then, have a smashing good time and catch you on the flip side!\n", + "Wishing you a smashing holiday season! 🎁✨\n", "\n", - "Smashfully yours,\n", + "See you\n", + "all soon!\n", + "Hulk (and Bruce Banner) \n", "\n", - "The Hulk 💥\r\n" + "👋🎄🎅\n" ] } ], @@ -619,7 +707,7 @@ "};\n", "\n", "var result = await kernel.InvokeAsync(writerPluginFunctions[\"OOF\"], variables);\n", - "Console.WriteLine(result.GetValue());" + "WriteLongStory(result.GetValue());" ] }, { @@ -663,7 +751,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -691,7 +779,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -721,7 +809,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -738,14 +826,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "Diana Prince\r\n" + "Tim Drake\r\n" ] } ], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", - " [\"input\"] = \"Wonder Woman\"\n", + " [\"input\"] = \"Robin\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", @@ -788,7 +876,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -804,7 +892,7 @@ { "data": { "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.7.1-preview
" + "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.13.0-preview
" ] }, "metadata": {}, @@ -812,7 +900,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.7.1-preview\"" + "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.13.0-preview\"" ] }, { @@ -824,7 +912,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -855,7 +943,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -874,14 +962,20 @@ "text": [ "Original plan:\n", "\n", - "{{!-- Step 0: Extract Key Values --}}\n", - "{{set \"joke\" \"Why did Batman and Robin invest in the Batmobile? They were tired of the Batcycle.\"}}\n", + "{{!-- Step 1: Set the joke about Batman --}}\n", + "{{set \"joke\" \"¿Por qué Batman y\n", + "Robin no usan el navegador Google Chrome? Porque prefieren ir en modo\n", + "incógnito.\"}}\n", "\n", - "{{!-- Step 1: Create out-of-office message using the joke --}}\n", - "{{set \"outOfOfficeMessage\" (concat \"Hello, I'm currently out of the Batcave because I heard a good joke: \" joke \" Please leave a message and I'll get back to you when I return. Thanks!\")}}\n", + "{{!-- Step 2: Create the out-of-office message in Spanish using\n", + "the joke --}}\n", + "{{set \"outOfOfficeMessage\" (concat \"Hola, gracias por tu mensaje.\n", + "Actualmente estoy fuera de la oficina. Mientras esperas mi respuesta, aquí\n", + "tienes un chiste: \" joke)}}\n", "\n", - "{{!-- Step 2: Print the out-of-office message as JSON --}}\n", - "{{json outOfOfficeMessage}}\n" + "{{!-- Output the out-of-office message --}}\n", + "{{json\n", + "outOfOfficeMessage}}\n" ] } ], @@ -893,7 +987,7 @@ "var originalPlan = await planner.CreatePlanAsync(kernel, ask);\n", "\n", "Console.WriteLine(\"Original plan:\\n\");\n", - "Console.WriteLine(originalPlan);" + "WriteLongStory(originalPlan.ToString());" ] }, { @@ -907,7 +1001,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 29, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -926,7 +1020,9 @@ "text": [ "Original Plan results:\n", "\n", - "Hello, I'm currently out of the Batcave because I heard a good joke: Why did Batman and Robin invest in the Batmobile? They were tired of the Batcycle. Please leave a message and I'll get back to you when I return. Thanks!\n" + "Hola, gracias por tu mensaje. Actualmente estoy fuera de la oficina. Mientras\n", + "esperas mi respuesta, aquí tienes un chiste: ¿Por qué Batman y Robin no usan el\n", + "navegador Google Chrome? Porque prefieren ir en modo incógnito.\n" ] } ], @@ -936,7 +1032,7 @@ "var originalPlanResult = await originalPlan.InvokeAsync(kernel, new KernelArguments());\n", "\n", "Console.WriteLine(\"Original Plan results:\\n\");\n", - "Console.WriteLine(originalPlanResult.ToString());" + "WriteLongStory(originalPlanResult.ToString());" ] }, { @@ -950,7 +1046,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 30, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -969,24 +1065,32 @@ "text": [ "Plan:\n", "\n", - "{{! Step 0: Extract Key Values}}\n", - "{{set \"superhero\" \"IronMan\"}}\n", + "{{!-- Step 1: Get IronMan's alter ego --}}\n", + "{{set \"heroName\" \"IronMan\"}}\n", + "{{set\n", + "\"alterEgo\" (HeroInfo-GetAlterEgo input=heroName)}}\n", "\n", - "{{! Step 1: Use Custom Helper to Get Alter Ego and Create Message}}\n", - "{{set \"alterEgo\" (HeroInfo-GetAlterEgo input=superhero)}}\n", - "{{set \"message\" (concat \"Out of office message: I'm out saving the world! - \" alterEgo)}}\n", - "{{json message}}\n" + "{{!-- Step 2: Create the out\n", + "of office message --}}\n", + "{{set \"ooMessage\" (concat \"Hello,\" \"\\n\\nIronMan is\n", + "currently out of the office saving the world.\" \"\\n\\nWhy did IronMan decide to\n", + "become a superhero? Because he couldn't find any iron-clad alibis!\" \"\\n\\nBest\n", + "regards,\" \"\\n\" alterEgo)}}\n", + "\n", + "{{!-- Step 3: Print the out of office message\n", + "--}}\n", + "{{json ooMessage}}\n" ] } ], "source": [ - "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, signing it with his alter ego.\";\n", + "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, add a jobe about the heroe and signing it with his alter ego.\";\n", "\n", "#pragma warning disable SKEXP0060\n", "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", "\n", "Console.WriteLine(\"Plan:\\n\");\n", - "Console.WriteLine(plan_complex);" + "WriteLongStory(plan_complex.ToString());" ] }, { @@ -998,7 +1102,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 31, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1017,7 +1121,9 @@ "text": [ "Complex Plan results:\n", "\n", - "Out of office message: I'm out saving the world! - Tony Stark\n" + "Hello,\\n\\nIronMan is currently out of the office saving the world.\\n\\nWhy did\n", + "IronMan decide to become a superhero? Because he couldn't find any iron-clad\n", + "alibis!\\n\\nBest regards,\\nTony Stark\n" ] } ], @@ -1026,7 +1132,7 @@ "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", "\n", "Console.WriteLine(\"Complex Plan results:\\n\");\n", - "Console.WriteLine(complexPlanResult.ToString());" + "WriteLongStory(complexPlanResult.ToString());" ] }, { @@ -1049,7 +1155,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 32, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1065,7 +1171,7 @@ { "data": { "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.7.1-alpha
  • System.Linq.Async, 6.0.1
" + "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.13.0-alpha
  • System.Linq.Async, 6.0.1
" ] }, "metadata": {}, @@ -1073,7 +1179,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.7.1-alpha\"\n", + "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.13.0-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" ] }, @@ -1090,7 +1196,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 33, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1131,7 +1237,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 34, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1153,7 +1259,8 @@ "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info3\", text: \"Bruno's favourite super hero is Invincible\");\n", "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"The last super hero movie watched by Bruno was Aquaman II\");\n", "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info6\", text: \"Alixia don't like the super hero movie: The Batman\");" + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info6\", text: \"Alixia don't like the super hero movie: The Batman\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info7\", text: \"Susana likes a lot an Argentinian super hero named SuperHijitus\");" ] }, { @@ -1165,7 +1272,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 35, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1186,7 +1293,9 @@ "How about Alixia? Alixia don't like the super hero movie: The Batman\n", "what was the last movie watched by Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", "Which is the prefered super hero for Gisela? Gisela's favourite super hero is Batman\n", - "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n" + "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n", + "What is the super hero that Susana suggested? Susana likes a lot an Argentinian super hero named SuperHijitus\n", + "Is there any super hero from Argentina? Susana likes a lot an Argentinian super hero named SuperHijitus\n" ] } ], @@ -1197,7 +1306,9 @@ " \"How about Alixia?\",\n", " \"what was the last movie watched by Gisela?\",\n", " \"Which is the prefered super hero for Gisela?\",\n", - " \"Did Bruno watched a super hero movie in the past, which was the last one?\"\n", + " \"Did Bruno watched a super hero movie in the past, which was the last one?\",\n", + " \"What is the super hero that Susana suggested?\",\n", + " \"Is there any super hero from Argentina?\"\n", "};\n", "\n", "foreach (var q in questions)\n", @@ -1216,7 +1327,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 36, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1233,12 +1344,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "¿Cuál es el superhéroe favorito de Bruno? Bruno's favourite super hero is Invincible info3\n", - "¿Cuál fue la última película vista por Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3 info2\n", - "¿Cuál es el superhéroe preferido de Gisela? Gisela's favourite super hero is Batman info1\n", - "¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última? The last super hero movie watched by Bruno was Aquaman II info4\n", - "Cual es la pelicula que no le gusta a Bruno? Bruno don't like the super hero movie: Eternals info5\n", - "Sabes algo de Alixia? Alixia don't like the super hero movie: The Batman info6\n" + "¿Cuál es el superhéroe favorito de Bruno? Bruno's favourite super hero is Invincible info3 0.8802320957183838\n", + "¿Cuál fue la última película vista por Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3 info2 0.8631904125213623\n", + "¿Cuál es el superhéroe preferido de Gisela? Gisela's favourite super hero is Batman info1 0.8966557383537292\n", + "¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última? The last super hero movie watched by Bruno was Aquaman II info4 0.8627986311912537\n", + "Cual es la pelicula que no le gusta a Bruno? Bruno don't like the super hero movie: Eternals info5 0.8379150629043579\n", + "Sabes algo de Alixia? Susana likes a lot an Argentinian super hero named SuperHijitus info7 0.7820731997489929\n" ] } ], @@ -1256,7 +1367,7 @@ "foreach (var q in preguntas)\n", "{\n", " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", - " Console.WriteLine(q + \" \" + response?.Metadata.Text + \" \" + response?.Metadata.Id);\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text + \" \" + response?.Metadata.Id + \" \" + response?.Relevance);\n", "}" ] } From 6ad4d08edd018dd1272317390dd6233c5561298b Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Fri, 31 May 2024 10:49:54 -0400 Subject: [PATCH 24/25] update qas --- notebook-en.ipynb | 338 +++++++++++++++++++++++----------------------- 1 file changed, 166 insertions(+), 172 deletions(-) diff --git a/notebook-en.ipynb b/notebook-en.ipynb index e11b199..b84e881 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -32,8 +32,14 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 1, "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, "vscode": { "languageId": "polyglot-notebook" } @@ -45,7 +51,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -57,7 +63,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 1.13.0
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.13.0\"" ] @@ -71,7 +87,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -149,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -182,7 +198,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -239,7 +255,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -267,7 +283,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -294,7 +310,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -378,7 +394,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -395,9 +411,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Why did the scarecrow win an award?\n", + "Why don't scientists trust atoms?\n", "\n", - "Because he was outstanding in his field!\r\n" + "Because they make up everything!\r\n" ] } ], @@ -414,7 +430,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -430,7 +446,7 @@ "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Tell me a April's fools joke\",\n", - " [\"hero\"] = \"Hulk\"\n", + " [\"hero\"] = \"Batman\"\n", "};" ] }, @@ -443,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -469,7 +485,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -486,26 +502,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "One April Fool's Day, Tony Stark thought it would be hilarious to prank the\n", - "Hulk. He outfitted Bruce Banner's lab with voice-activated lights that responded\n", - "to Hulk's catchphrase, \"HULK SMASH!\"\n", - "\n", - "Later that evening, Bruce walked into his\n", - "lab, and the lights were off. Slightly confused, he muttered, \"Hulk smash?\" The\n", - "lights flickered on. Amused, he tried again, \"HULK SMASH!\" The lights dimmed and\n", - "then brightened. Intrigued, he continued, \"Hulk Smash?\" The lights danced around\n", - "like they were at a disco.\n", + "Why did Batman break up with Robin on April 1st?\n", "\n", - "Just then, Tony walked in with a smug grin. Bruce\n", - "looked at him and said, \"Nice prank, Tony. But remember, when Hulk smashes, Hulk\n", - "REALLY smashes.\"\n", - "\n", - "Then the entire building experienced a sudden and unexpected\n", - "power outage. Tony turned pale as Bruce flashed a mischievous smile. \"April\n", - "Fool's,\" Bruce said calmly, brandishing a remote control.\n", - "\n", - "Turns out, Iron Man\n", - "isn't the only one who knows how to pull a prank.\n" + "Because he thought Robin was\n", + "just winging it when he said, \"April Fools'! I'm actually Nightwing now!\"\n", + "Turns out, he wasn't fooling around!\n" ] } ], @@ -522,7 +523,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 13, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -551,7 +552,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 14, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -568,82 +569,81 @@ "name": "stdout", "output_type": "stream", "text": [ - "Sure! Here are the stories:\n", + "### IronMan and the Cosmic Rescue 🚀\n", "\n", - "### 🦇 Batman and the Enchanted Forest 🌳\n", + "#### Beginning:\n", + "Once upon a time in the\n", + "bustling city of New York, Tony Stark, also known as IronMan 🦾, was busy\n", + "tinkering in his lab. Suddenly, a distress signal 📡 from outer space caught his\n", + "attention. The signal was a cry for help from an alien planet 🌌 being\n", + "threatened by an evil warlord. Tony knew he had to act fast!\n", "\n", "####\n", - "Beginning 🌆\n", - "As the sun set over Gotham City, the Bat-Signal shone brightly in\n", - "the sky. 🦇 Batman, always ready to protect his city, suited up and leaped into\n", - "the Batmobile. Tonight, the signal led him not to the usual villains but to a\n", - "mysterious, enchanted forest that had appeared overnight in the heart of Gotham.\n", - "🌲\n", - "\n", - "#### Middle 🌕\n", - "Batman ventured into the forest, finding it filled with\n", - "glowing plants and strange creatures. Suddenly, he heard a child's cry for help.\n", - "🛡️ With heightened senses, he maneuvered through dense foliage until he reached\n", - "a clearing where an enormous, enchanting tree stood. Its ancient bark was\n", - "inscribed with runes, and at its base was a young girl trapped by thick vines.\n", - "\"Fear not, I am here to help,\" Batman assured. Using his bat-tools, he\n", - "skillfully cut through the magical vines, freeing the girl. She revealed that\n", - "the forest had been cursed by an evil sorcerer, and only a pure heart could lift\n", - "the spell.\n", + "Middle:\n", + "IronMan suited up in his advanced, cosmic armor 🔧💥 and blasted off\n", + "into space. He navigated through wormholes and asteroid fields 🌠 until he\n", + "reached the distant planet of Zogoria. The planet was under siege by the\n", + "warlord, Xyrax, and his robotic minions 🤖. The Zogorians, a peaceful race of\n", + "green-skinned beings, were trying to defend their home but were outmatched.\n", + "IronMan landed just in time to thwart a massive attack on Zogoria’s capital\n", + "🌆. Using his repulsor beams and advanced weapons, he fought off Xyrax’s robots\n", + "with the skill and precision of a true hero. The battle raged on, with IronMan\n", + "leveraging his intelligence and tech, creating ingenious traps and outsmarting\n", + "the mechanical foes. \n", "\n", - "#### End 🌟\n", - "Batman knew what had to be done. Guided by the girl's\n", - "knowledge, he approached the enchanted tree and placed his hand on its runes.\n", - "His pure intent and unwavering commitment to justice began to break the curse.\n", - "The forest brightened, the creatures became friendly, and the thicket vanished.\n", - "Batman escorted the girl back to Gotham, where the morning sun brought new hope.\n", - "🌞 \n", + "Finally, IronMan confronted Xyrax himself. It was a\n", + "fierce duel, but Tony's determination and innovative spirit won the day. With a\n", + "final, powerful blast, he shattered Xyrax's armor and the warlord fled, vowing\n", + "revenge.\n", "\n", - "Gotham City was safe once again, thanks to its ever-vigilant guardian. As\n", - "Batman disappeared into the dawn, he knew his true strength lay not just in his\n", - "skills, but in the purity of his heart. 🦇🌟\n", + "#### End:\n", + "With peace restored, the Zogorians expressed their immense\n", + "gratitude. They threw a grand celebration 🥳, and IronMan was hailed as a\n", + "legend. Tony set up a defense system for the Zogorians to ensure their safety in\n", + "the future. Feeling accomplished, he returned to Earth, knowing he had made the\n", + "universe a safer place. Tony Stark may have been a genius, billionaire, playboy,\n", + "philanthropist, but above all, he was a hero—IronMan 🦾✨.\n", "\n", "---\n", "\n", - "### 🐶 Daisy and 🐱 Whiskers:\n", - "An Unlikely Friendship\n", - "\n", - "#### Beginning 🌈\n", - "In a quiet countryside lived two pets\n", - "with very different lives. Daisy, a playful Golden Retriever, loved to chase\n", - "butterflies and roll in the grass. 🐶 Whiskers, a curious tabby cat, preferred\n", - "climbing trees and napping in sun-drenched spots. 🐱 They had never met but were\n", - "destined to become great friends.\n", + "### The Unlikely\n", + "Friendship of Whiskers 🐱 and Buster 🐶\n", "\n", - "#### Middle 🌤️\n", - "One sunny day, Daisy was\n", - "chasing a butterfly that led her to the edge of her yard, right where Whiskers\n", - "was perched on a low branch. They eyed each other curiously. Daisy barked in\n", - "excitement, causing Whiskers to arch his back defensively. \n", + "#### Beginning:\n", + "In a quaint little\n", + "town, nestled between rolling hills, lived a curious cat named Whiskers 🐱.\n", + "Whiskers loved to explore and laze in sunny spots. One sunny afternoon, while\n", + "basking in a sunbeam, she noticed a new sound— a cheerful bark from the other\n", + "side of the fence.\n", "\n", - "But soon, Daisy\n", - "laid down and wagged her tail in a friendly invitation. Whiskers hesitated, then\n", - "hopped down cautiously. They started to explore the countryside together; Daisy\n", - "showed Whiskers her favorite fields while Whiskers introduced Daisy to the best\n", - "climbing spots.\n", + "#### Middle:\n", + "Curious, Whiskers leaped over and found a\n", + "playful puppy named Buster 🐶. Buster wagged his tail excitedly and invited\n", + "Whiskers to join him in his games. Initially hesitant, Whiskers wasn't used to\n", + "the idea of playing with a dog. But Buster's infectious happiness soon melted\n", + "her reservations. They chased butterflies 🦋, played hide and seek in the\n", + "bushes, and napped under the shade of a large oak tree 🌳. \n", "\n", - "#### End 🌟\n", - "Days turned into weeks, and the two became\n", - "inseparable. They shared their adventures, from catching frogs by the pond to\n", - "watching the stars at night. As different as they were, Daisy and Whiskers found\n", - "joy in each other's company and learned the true meaning of friendship.\n", - "🐾🐶🐱\n", + "Days turned into\n", + "weeks, and the two became inseparable friends. They shared adventures that took\n", + "them through fields of flowers, across babbling brooks, and even on a daring\n", + "exploration of the old barn at the edge of town.\n", "\n", - "In their little corner of the world, the unlikely pair stood as a\n", - "testament to how beautiful and enriching friendships can be, no matter how\n", - "different we are. 🌈💖\n" + "#### End:\n", + "One day, a storm\n", + "rolled in with menacing clouds and booming thunder ⚡. Whiskers, who was usually\n", + "brave, felt frightened. Buster, sensing her fear, cuddled close to offer\n", + "comfort. The storm passed, but their bond was stronger than ever. Their\n", + "friendship showed that differences didn’t matter; together, they could face\n", + "anything. And so, in that quaint little town, Whiskers and Buster proved that\n", + "the most unlikely friendships often turned out to be the strongest of all 💕.\n" ] } ], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Tell me a story about 2 pets that meet each other\",\n", - " [\"hero\"] = \"Batman\"\n", + " [\"hero\"] = \"IronMan\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(writerPluginFunctions[\"StoryGen\"], variables);\n", @@ -659,7 +659,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 15, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -676,27 +676,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "**Subject: Hulk on Holiday! 🎅🎄**\n", + "Subject: 🎄💥 Hulk on Holiday Smash! 💥🎄\n", "\n", - "Hello there,\n", + "Hi there!\n", "\n", - "It's time for Hulk to take a\n", - "well-deserved break! 💪😁 This big, green, smashing machine is off celebrating\n", - "Christmas and enjoying some rest until (date you're returning). Even heroes need\n", - "some downtime to recharge! 🌟\n", + "Hulk here! I’ve gone off\n", + "to celebrate Christmas and recharge my energy with some much-needed R&R (Relax &\n", + "Rampage 😉). During this time, I won't be able to respond to emails, participate\n", + "in missions, or help with your daily smashing requirements.\n", "\n", - "But don't you worry! While Hulk is away, our\n", - "friendly neighborhood Spider-Man 🕸️🕷️ has got you covered. If you need any\n", - "assistance, feel free to reach out to Spidey. He's got the web-slinging skills\n", - "to handle any situation! \n", + "But don’t you\n", + "worry! 🛡️ Our reliable friend, Captain America, is here to assist you in my\n", + "absence. You can reach out to him for any heroic duties or assistance you might\n", + "need. Just shoot him an email at cap@avengers.com, and he’ll take good care of\n", + "you.\n", "\n", - "Wishing you a smashing holiday season! 🎁✨\n", + "Wishing everyone a peaceful and Hulk-sized joyful Christmas! 🎅🎁\n", "\n", "See you\n", - "all soon!\n", - "Hulk (and Bruce Banner) \n", + "in the new year!\n", + "\n", + "Hulk SMASH…ing off! 💚👊\n", "\n", - "👋🎄🎅\n" + "Goodbye! 🟢\n" ] } ], @@ -751,7 +753,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 16, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -779,7 +781,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 17, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -809,7 +811,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 19, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -826,14 +828,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "Tim Drake\r\n" + "Terry McGinnis\r\n" ] } ], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", - " [\"input\"] = \"Robin\"\n", + " [\"input\"] = \"Batman\"\n", "};\n", "\n", "var result = await kernel.InvokeAsync(\"HeroInfo\", \"GetAlterEgo\", kernelArgs);\n", @@ -876,7 +878,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 20, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -912,7 +914,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -943,7 +945,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -962,20 +964,19 @@ "text": [ "Original plan:\n", "\n", - "{{!-- Step 1: Set the joke about Batman --}}\n", - "{{set \"joke\" \"¿Por qué Batman y\n", - "Robin no usan el navegador Google Chrome? Porque prefieren ir en modo\n", - "incógnito.\"}}\n", + "{{!-- Step 1: Set the joke as a variable --}}\n", + "{{set \"joke\" \"Why is Batman so\n", + "good at hitting home runs? Because he's got a bat.\"}}\n", "\n", - "{{!-- Step 2: Create the out-of-office message in Spanish using\n", - "the joke --}}\n", - "{{set \"outOfOfficeMessage\" (concat \"Hola, gracias por tu mensaje.\n", - "Actualmente estoy fuera de la oficina. Mientras esperas mi respuesta, aquí\n", - "tienes un chiste: \" joke)}}\n", + "{{!-- Step 2: Set the\n", + "out-of-office message using the joke --}}\n", + "{{set \"outOfOfficeMessage\" (concat\n", + "\"I'm currently out of the Batcave. Here's a joke to keep you entertained: \" joke\n", + "\" I will respond to your message as soon as I return.\")}}\n", "\n", - "{{!-- Output the out-of-office message --}}\n", - "{{json\n", - "outOfOfficeMessage}}\n" + "{{!-- Step 3: Display\n", + "the out-of-office message --}}\n", + "{{json outOfOfficeMessage}}\n" ] } ], @@ -1001,7 +1002,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1020,9 +1021,9 @@ "text": [ "Original Plan results:\n", "\n", - "Hola, gracias por tu mensaje. Actualmente estoy fuera de la oficina. Mientras\n", - "esperas mi respuesta, aquí tienes un chiste: ¿Por qué Batman y Robin no usan el\n", - "navegador Google Chrome? Porque prefieren ir en modo incógnito.\n" + "I'm currently out of the Batcave. Here's a joke to keep you entertained: Why is\n", + "Batman so good at hitting home runs? Because he's got a bat. I will respond to\n", + "your message as soon as I return.\n" ] } ], @@ -1046,7 +1047,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1065,26 +1066,29 @@ "text": [ "Plan:\n", "\n", - "{{!-- Step 1: Get IronMan's alter ego --}}\n", - "{{set \"heroName\" \"IronMan\"}}\n", + "{{!-- Step 1: Create a variable for the superhero name --}}\n", "{{set\n", - "\"alterEgo\" (HeroInfo-GetAlterEgo input=heroName)}}\n", + "\"superheroName\" \"IronMan\"}}\n", "\n", - "{{!-- Step 2: Create the out\n", - "of office message --}}\n", - "{{set \"ooMessage\" (concat \"Hello,\" \"\\n\\nIronMan is\n", - "currently out of the office saving the world.\" \"\\n\\nWhy did IronMan decide to\n", - "become a superhero? Because he couldn't find any iron-clad alibis!\" \"\\n\\nBest\n", - "regards,\" \"\\n\" alterEgo)}}\n", - "\n", - "{{!-- Step 3: Print the out of office message\n", + "{{!-- Step 2: Get the alter ego of the superhero\n", "--}}\n", - "{{json ooMessage}}\n" + "{{set \"alterEgo\" (HeroInfo-GetAlterEgo superheroName)}}\n", + "\n", + "{{!-- Step 3:\n", + "Create the out of office message --}}\n", + "{{set \"outOfOfficeMessage\" (concat \"Hello,\n", + "this is \" superheroName \". I am currently out of office saving the world. \"\n", + "\"Please contact me later.\\n\\n\" \"Why don't scientists trust atoms? Because they\n", + "make up everything!\\n\\n\" \"Best regards,\\n\" alterEgo)}}\n", + "\n", + "{{!-- Step 4: Print the\n", + "out of office message --}}\n", + "{{json outOfOfficeMessage}}\n" ] } ], "source": [ - "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, add a jobe about the heroe and signing it with his alter ego.\";\n", + "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, add a joke about the heroe and signing it with his alter ego.\";\n", "\n", "#pragma warning disable SKEXP0060\n", "var plan_complex = await planner.CreatePlanAsync(kernel, ask_complex);\n", @@ -1102,7 +1106,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1121,9 +1125,9 @@ "text": [ "Complex Plan results:\n", "\n", - "Hello,\\n\\nIronMan is currently out of the office saving the world.\\n\\nWhy did\n", - "IronMan decide to become a superhero? Because he couldn't find any iron-clad\n", - "alibis!\\n\\nBest regards,\\nTony Stark\n" + "Hello, this is IronMan. I am currently out of office saving the world. Please\n", + "contact me later.\\n\\nWhy don't scientists trust atoms? Because they make up\n", + "everything!\\n\\nBest regards,\\nTony Stark\n" ] } ], @@ -1155,7 +1159,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1196,7 +1200,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1237,7 +1241,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 33, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1260,7 +1264,9 @@ "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info4\", text: \"The last super hero movie watched by Bruno was Aquaman II\");\n", "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info5\", text: \"Bruno don't like the super hero movie: Eternals\");\n", "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info6\", text: \"Alixia don't like the super hero movie: The Batman\");\n", - "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info7\", text: \"Susana likes a lot an Argentinian super hero named SuperHijitus\");" + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info7\", text: \"Susana likes a lot an Argentinian super hero named SuperHijitus\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info8\", text: \"Dave likes Robin, the sidekick of Batman\");\n", + "await memory.SaveInformationAsync(MemoryCollectionName, id: \"info9\", text: \"Dave last movie was Oppenheimer, a movie about the scientist that created the atomic bomb\");" ] }, { @@ -1289,32 +1295,20 @@ "name": "stdout", "output_type": "stream", "text": [ - "What is Bruno's favourite super hero? Bruno's favourite super hero is Invincible\n", - "How about Alixia? Alixia don't like the super hero movie: The Batman\n", - "what was the last movie watched by Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3\n", - "Which is the prefered super hero for Gisela? Gisela's favourite super hero is Batman\n", - "Did Bruno watched a super hero movie in the past, which was the last one? The last super hero movie watched by Bruno was Aquaman II\n", - "What is the super hero that Susana suggested? Susana likes a lot an Argentinian super hero named SuperHijitus\n", - "Is there any super hero from Argentina? Susana likes a lot an Argentinian super hero named SuperHijitus\n" + "Does anyone watched a movie not from superheros? Alixia don't like the super hero movie: The Batman 0.8190542459487915\r\n" ] } ], "source": [ "var questions = new[]\n", "{\n", - " \"What is Bruno's favourite super hero?\",\n", - " \"How about Alixia?\",\n", - " \"what was the last movie watched by Gisela?\",\n", - " \"Which is the prefered super hero for Gisela?\",\n", - " \"Did Bruno watched a super hero movie in the past, which was the last one?\",\n", - " \"What is the super hero that Susana suggested?\",\n", - " \"Is there any super hero from Argentina?\"\n", + " \"Does anyone watched a movie not from superheros?\",\n", "};\n", "\n", "foreach (var q in questions)\n", "{\n", " var response = await memory.SearchAsync(MemoryCollectionName, q).FirstOrDefaultAsync();\n", - " Console.WriteLine(q + \" \" + response?.Metadata.Text);\n", + " Console.WriteLine(q + \" \" + response?.Metadata.Text + \" \" + response?.Relevance);\n", "}\n" ] }, @@ -1327,7 +1321,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 31, "metadata": { "dotnet_interactive": { "language": "csharp" From 4c0beaca1f81c0a639cc799a8bd73cc7d3872d04 Mon Sep 17 00:00:00 2001 From: Bruno Capuano Date: Fri, 31 May 2024 10:50:44 -0400 Subject: [PATCH 25/25] update qas --- notebook-en.ipynb | 345 ++++++---------------------------------------- 1 file changed, 43 insertions(+), 302 deletions(-) diff --git a/notebook-en.ipynb b/notebook-en.ipynb index b84e881..836fe4f 100644 --- a/notebook-en.ipynb +++ b/notebook-en.ipynb @@ -32,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -51,7 +51,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -63,17 +63,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel, 1.13.0
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel, 1.13.0\"" ] @@ -87,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -165,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -198,7 +188,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -255,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -283,7 +273,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -310,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -394,7 +384,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -406,17 +396,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Why don't scientists trust atoms?\n", - "\n", - "Because they make up everything!\r\n" - ] - } - ], + "outputs": [], "source": [ "Console.WriteLine(result.GetValue());" ] @@ -430,7 +410,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -459,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -485,7 +465,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -497,19 +477,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Why did Batman break up with Robin on April 1st?\n", - "\n", - "Because he thought Robin was\n", - "just winging it when he said, \"April Fools'! I'm actually Nightwing now!\"\n", - "Turns out, he wasn't fooling around!\n" - ] - } - ], + "outputs": [], "source": [ "WriteLongStory(result.GetValue());" ] @@ -523,7 +491,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -552,7 +520,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -564,82 +532,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "### IronMan and the Cosmic Rescue 🚀\n", - "\n", - "#### Beginning:\n", - "Once upon a time in the\n", - "bustling city of New York, Tony Stark, also known as IronMan 🦾, was busy\n", - "tinkering in his lab. Suddenly, a distress signal 📡 from outer space caught his\n", - "attention. The signal was a cry for help from an alien planet 🌌 being\n", - "threatened by an evil warlord. Tony knew he had to act fast!\n", - "\n", - "####\n", - "Middle:\n", - "IronMan suited up in his advanced, cosmic armor 🔧💥 and blasted off\n", - "into space. He navigated through wormholes and asteroid fields 🌠 until he\n", - "reached the distant planet of Zogoria. The planet was under siege by the\n", - "warlord, Xyrax, and his robotic minions 🤖. The Zogorians, a peaceful race of\n", - "green-skinned beings, were trying to defend their home but were outmatched.\n", - "IronMan landed just in time to thwart a massive attack on Zogoria’s capital\n", - "🌆. Using his repulsor beams and advanced weapons, he fought off Xyrax’s robots\n", - "with the skill and precision of a true hero. The battle raged on, with IronMan\n", - "leveraging his intelligence and tech, creating ingenious traps and outsmarting\n", - "the mechanical foes. \n", - "\n", - "Finally, IronMan confronted Xyrax himself. It was a\n", - "fierce duel, but Tony's determination and innovative spirit won the day. With a\n", - "final, powerful blast, he shattered Xyrax's armor and the warlord fled, vowing\n", - "revenge.\n", - "\n", - "#### End:\n", - "With peace restored, the Zogorians expressed their immense\n", - "gratitude. They threw a grand celebration 🥳, and IronMan was hailed as a\n", - "legend. Tony set up a defense system for the Zogorians to ensure their safety in\n", - "the future. Feeling accomplished, he returned to Earth, knowing he had made the\n", - "universe a safer place. Tony Stark may have been a genius, billionaire, playboy,\n", - "philanthropist, but above all, he was a hero—IronMan 🦾✨.\n", - "\n", - "---\n", - "\n", - "### The Unlikely\n", - "Friendship of Whiskers 🐱 and Buster 🐶\n", - "\n", - "#### Beginning:\n", - "In a quaint little\n", - "town, nestled between rolling hills, lived a curious cat named Whiskers 🐱.\n", - "Whiskers loved to explore and laze in sunny spots. One sunny afternoon, while\n", - "basking in a sunbeam, she noticed a new sound— a cheerful bark from the other\n", - "side of the fence.\n", - "\n", - "#### Middle:\n", - "Curious, Whiskers leaped over and found a\n", - "playful puppy named Buster 🐶. Buster wagged his tail excitedly and invited\n", - "Whiskers to join him in his games. Initially hesitant, Whiskers wasn't used to\n", - "the idea of playing with a dog. But Buster's infectious happiness soon melted\n", - "her reservations. They chased butterflies 🦋, played hide and seek in the\n", - "bushes, and napped under the shade of a large oak tree 🌳. \n", - "\n", - "Days turned into\n", - "weeks, and the two became inseparable friends. They shared adventures that took\n", - "them through fields of flowers, across babbling brooks, and even on a daring\n", - "exploration of the old barn at the edge of town.\n", - "\n", - "#### End:\n", - "One day, a storm\n", - "rolled in with menacing clouds and booming thunder ⚡. Whiskers, who was usually\n", - "brave, felt frightened. Buster, sensing her fear, cuddled close to offer\n", - "comfort. The storm passed, but their bond was stronger than ever. Their\n", - "friendship showed that differences didn’t matter; together, they could face\n", - "anything. And so, in that quaint little town, Whiskers and Buster proved that\n", - "the most unlikely friendships often turned out to be the strongest of all 💕.\n" - ] - } - ], + "outputs": [], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Tell me a story about 2 pets that meet each other\",\n", @@ -659,7 +552,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -671,37 +564,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Subject: 🎄💥 Hulk on Holiday Smash! 💥🎄\n", - "\n", - "Hi there!\n", - "\n", - "Hulk here! I’ve gone off\n", - "to celebrate Christmas and recharge my energy with some much-needed R&R (Relax &\n", - "Rampage 😉). During this time, I won't be able to respond to emails, participate\n", - "in missions, or help with your daily smashing requirements.\n", - "\n", - "But don’t you\n", - "worry! 🛡️ Our reliable friend, Captain America, is here to assist you in my\n", - "absence. You can reach out to him for any heroic duties or assistance you might\n", - "need. Just shoot him an email at cap@avengers.com, and he’ll take good care of\n", - "you.\n", - "\n", - "Wishing everyone a peaceful and Hulk-sized joyful Christmas! 🎅🎁\n", - "\n", - "See you\n", - "in the new year!\n", - "\n", - "Hulk SMASH…ing off! 💚👊\n", - "\n", - "Goodbye! 🟢\n" - ] - } - ], + "outputs": [], "source": [ "var variables = new KernelArguments() {\n", " [\"input\"] = \"Create an OOF for Christmas\",\n", @@ -753,7 +616,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -781,7 +644,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -811,7 +674,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -823,15 +686,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Terry McGinnis\r\n" - ] - } - ], + "outputs": [], "source": [ "var kernelArgs = new KernelArguments()\n", "{\n", @@ -878,7 +733,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -890,17 +745,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Planners.Handlebars, 1.13.0-preview
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Planners.Handlebars, 1.13.0-preview\"" ] @@ -914,7 +759,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -945,7 +790,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -957,29 +802,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original plan:\n", - "\n", - "{{!-- Step 1: Set the joke as a variable --}}\n", - "{{set \"joke\" \"Why is Batman so\n", - "good at hitting home runs? Because he's got a bat.\"}}\n", - "\n", - "{{!-- Step 2: Set the\n", - "out-of-office message using the joke --}}\n", - "{{set \"outOfOfficeMessage\" (concat\n", - "\"I'm currently out of the Batcave. Here's a joke to keep you entertained: \" joke\n", - "\" I will respond to your message as soon as I return.\")}}\n", - "\n", - "{{!-- Step 3: Display\n", - "the out-of-office message --}}\n", - "{{json outOfOfficeMessage}}\n" - ] - } - ], + "outputs": [], "source": [ "using System.Text.Json;\n", "\n", @@ -1002,7 +825,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1014,19 +837,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original Plan results:\n", - "\n", - "I'm currently out of the Batcave. Here's a joke to keep you entertained: Why is\n", - "Batman so good at hitting home runs? Because he's got a bat. I will respond to\n", - "your message as soon as I return.\n" - ] - } - ], + "outputs": [], "source": [ "// executing the plan\n", "#pragma warning disable SKEXP0060\n", @@ -1047,7 +858,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1059,34 +870,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Plan:\n", - "\n", - "{{!-- Step 1: Create a variable for the superhero name --}}\n", - "{{set\n", - "\"superheroName\" \"IronMan\"}}\n", - "\n", - "{{!-- Step 2: Get the alter ego of the superhero\n", - "--}}\n", - "{{set \"alterEgo\" (HeroInfo-GetAlterEgo superheroName)}}\n", - "\n", - "{{!-- Step 3:\n", - "Create the out of office message --}}\n", - "{{set \"outOfOfficeMessage\" (concat \"Hello,\n", - "this is \" superheroName \". I am currently out of office saving the world. \"\n", - "\"Please contact me later.\\n\\n\" \"Why don't scientists trust atoms? Because they\n", - "make up everything!\\n\\n\" \"Best regards,\\n\" alterEgo)}}\n", - "\n", - "{{!-- Step 4: Print the\n", - "out of office message --}}\n", - "{{json outOfOfficeMessage}}\n" - ] - } - ], + "outputs": [], "source": [ "var ask_complex = \"I would like you to find out IronMan's alter ego, and create an out of office message for IronMan, add a joke about the heroe and signing it with his alter ego.\";\n", "\n", @@ -1106,7 +890,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1118,19 +902,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Complex Plan results:\n", - "\n", - "Hello, this is IronMan. I am currently out of office saving the world. Please\n", - "contact me later.\\n\\nWhy don't scientists trust atoms? Because they make up\n", - "everything!\\n\\nBest regards,\\nTony Stark\n" - ] - } - ], + "outputs": [], "source": [ "#pragma warning disable SKEXP0060\n", "var complexPlanResult = await plan_complex.InvokeAsync(kernel, new KernelArguments());\n", @@ -1159,7 +931,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1171,17 +943,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel.Plugins.Memory, 1.13.0-alpha
  • System.Linq.Async, 6.0.1
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "#r \"nuget: Microsoft.SemanticKernel.Plugins.Memory, 1.13.0-alpha\"\n", "#r \"nuget: System.Linq.Async, 6.0.1\"\n" @@ -1200,7 +962,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1241,7 +1003,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1278,7 +1040,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1290,15 +1052,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Does anyone watched a movie not from superheros? Alixia don't like the super hero movie: The Batman 0.8190542459487915\r\n" - ] - } - ], + "outputs": [], "source": [ "var questions = new[]\n", "{\n", @@ -1321,7 +1075,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1333,20 +1087,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "¿Cuál es el superhéroe favorito de Bruno? Bruno's favourite super hero is Invincible info3 0.8802320957183838\n", - "¿Cuál fue la última película vista por Gisela? The last super hero movie watched by Gisela was Guardians of the Galaxy Vol 3 info2 0.8631904125213623\n", - "¿Cuál es el superhéroe preferido de Gisela? Gisela's favourite super hero is Batman info1 0.8966557383537292\n", - "¿Bruno ha visto alguna película de superhéroes en el pasado? ¿Cuál fue la última? The last super hero movie watched by Bruno was Aquaman II info4 0.8627986311912537\n", - "Cual es la pelicula que no le gusta a Bruno? Bruno don't like the super hero movie: Eternals info5 0.8379150629043579\n", - "Sabes algo de Alixia? Susana likes a lot an Argentinian super hero named SuperHijitus info7 0.7820731997489929\n" - ] - } - ], + "outputs": [], "source": [ "var preguntas = new[]\n", "{\n",