diff --git a/python/README.md b/python/README.md index fabb307aae..f06aa204e2 100644 --- a/python/README.md +++ b/python/README.md @@ -97,6 +97,7 @@ Python notebooks: * [Running AI prompts from file](../samples/notebooks/python/02-running-prompts-from-file.ipynb) * [Creating Semantic Functions at runtime (i.e. inline functions)](../samples/notebooks/python/03-semantic-function-inline.ipynb) * [Using Context Variables to Build a Chat Experience](../samples/notebooks/python/04-context-variables-chat.ipynb) +* [Introduction to planners](../samples/notebooks/python/05-using-the-planner.ipynb) * [Building Memory with Embeddings](../samples/notebooks/python/06-memory-and-embeddings.ipynb) # SK Frequently Asked Questions diff --git a/samples/notebooks/python/00-getting-started.ipynb b/samples/notebooks/python/00-getting-started.ipynb index be2fcfe32a..6d1ac7e1ec 100644 --- a/samples/notebooks/python/00-getting-started.ipynb +++ b/samples/notebooks/python/00-getting-started.ipynb @@ -1,135 +1,134 @@ { - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Setup\n", - "\n", - "**Step 1**: Import Semantic Kernel SDK from pypi.org" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt\n", - "\n", - "# Alternatively, you can install from the local workspace using this command\n", - "#!python -m pip install ../../../python\n", - "\n", - "import semantic_kernel as sk\n", - "\n", - "kernel = sk.Kernel()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Option 1: using OpenAI\n", - "\n", - "**Step 2**: Add your [Open AI Key](https://openai.com/api/) key to a `.env` file in the same folder (org Id only if you have multiple orgs):\n", - "\n", - "```\n", - "OPENAI_API_KEY=\"sk-...\"\n", - "OPENAI_ORG_ID=\"\"\n", - "```\n", - "\n", - "and add OpenAI Text Completion to the kernel:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from semantic_kernel.connectors.ai.open_ai import OpenAITextCompletion\n", - "\n", - "api_key, org_id = sk.openai_settings_from_dot_env()\n", - "\n", - "kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Option 2: using Azure OpenAI\n", - "\n", - "**Step 2**: Add your [Azure Open AI Service key](https://learn.microsoft.com/azure/cognitive-services/openai/quickstart?pivots=programming-language-studio) settings to a `.env` file in the same folder:\n", - "\n", - "```\n", - "AZURE_OPENAI_API_KEY=\"...\"\n", - "AZURE_OPENAI_ENDPOINT=\"https://...\"\n", - "AZURE_OPENAI_DEPLOYMENT_NAME=\"...\"\n", - "```\n", - "\n", - "and add Azure OpenAI Text Completion to the kernel:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion\n", - "\n", - "deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", - "\n", - "kernel.add_text_completion_service(\"dv\", AzureTextCompletion(deployment, endpoint, api_key))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Run a Semantic Function\n", - "\n", - "**Step 3**: Load a Skill and run a semantic function:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "skill = kernel.import_semantic_skill_from_directory(\"../../skills\", \"FunSkill\")\n", - "joke_function = skill[\"Joke\"]\n", - "\n", - "print(joke_function(\"time travel to dinosaur age\"))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.5" - }, - "orig_nbformat": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Setup\n", + "\n", + "**Step 1**: Import Semantic Kernel SDK from pypi.org" + ] }, - "nbformat": 4, - "nbformat_minor": 2 + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import semantic_kernel as sk\n", + "\n", + "kernel = sk.Kernel()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Option 1: using OpenAI\n", + "\n", + "**Step 2**: Add your [Open AI Key](https://openai.com/api/) key to a `.env` file in the same folder (org Id only if you have multiple orgs):\n", + "\n", + "```\n", + "OPENAI_API_KEY=\"sk-...\"\n", + "OPENAI_ORG_ID=\"\"\n", + "```\n", + "\n", + "and add OpenAI Text Completion to the kernel:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from semantic_kernel.connectors.ai.open_ai import OpenAITextCompletion\n", + "\n", + "api_key, org_id = sk.openai_settings_from_dot_env()\n", + "\n", + "kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Option 2: using Azure OpenAI\n", + "\n", + "**Step 2**: Add your [Azure Open AI Service key](https://learn.microsoft.com/azure/cognitive-services/openai/quickstart?pivots=programming-language-studio) settings to a `.env` file in the same folder:\n", + "\n", + "```\n", + "AZURE_OPENAI_API_KEY=\"...\"\n", + "AZURE_OPENAI_ENDPOINT=\"https://...\"\n", + "AZURE_OPENAI_DEPLOYMENT_NAME=\"...\"\n", + "```\n", + "\n", + "and add Azure OpenAI Text Completion to the kernel:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion\n", + "\n", + "deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", + "\n", + "kernel.add_text_completion_service(\"dv\", AzureTextCompletion(deployment, endpoint, api_key))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run a Semantic Function\n", + "\n", + "**Step 3**: Load a Skill and run a semantic function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "skill = kernel.import_semantic_skill_from_directory(\"../../skills\", \"FunSkill\")\n", + "joke_function = skill[\"Joke\"]\n", + "\n", + "print(joke_function(\"time travel to dinosaur age\"))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/samples/notebooks/python/01-basic-loading-the-kernel.ipynb b/samples/notebooks/python/01-basic-loading-the-kernel.ipynb index 0524c9ffec..c25e29e58f 100644 --- a/samples/notebooks/python/01-basic-loading-the-kernel.ipynb +++ b/samples/notebooks/python/01-basic-loading-the-kernel.ipynb @@ -1,171 +1,168 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Basic Loading of the Kernel" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To run the notebooks we recommend using Poetry and starting a shell with a virtual environment\n", - "prepared to use SK. \n", - "\n", - "See [DEV_SETUP.md](../../../python/DEV_SETUP.md) for more information." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import semantic_kernel as sk\n", - "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can instantiate the kernel in a few ways, depending on your use case." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Simple instance\n", - "kernel_1 = sk.Kernel()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Instance with a custom logger\n", - "my_logger = sk.NullLogger()\n", - "kernel_2 = sk.Kernel(log=my_logger)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When using the kernel for AI requests, the kernel needs some settings like URL and credentials to the AI models.\n", - "\n", - "The SDK currently supports OpenAI and Azure OpenAI, other services will be added over time.\n", - "\n", - "If you need an Azure OpenAI key, go [here](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "kernel = sk.Kernel()\n", - "\n", - "kernel.add_text_completion_service( # We are adding a text service\n", - " \"Azure_curie\", # The alias we can use in prompt templates' config.json\n", - " AzureTextCompletion(\n", - " \"my-finetuned-Curie\", # Azure OpenAI *Deployment ID*\n", - " \"https://contoso.openai.azure.com/\", # Azure OpenAI *Endpoint*\n", - " \"...your Azure OpenAI Key...\" # Azure OpenAI *Key*\n", - " )\n", - ")\n", - "\n", - "kernel.add_text_completion_service( # We are adding a text service\n", - " \"OpenAI_davinci\", # The alias we can use in prompt templates' config.json\n", - " OpenAITextCompletion(\n", - " \"text-davinci-003\", # OpenAI Model Name\n", - " \"...your OpenAI API Key...\", # OpenAI API key\n", - " \"...your OpenAI Org ID...\" # *optional* OpenAI Organization ID\n", - " )\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When working with multiple services and multiple models, the **first service** defined\n", - "is also the \"**default**\" used in these scenarios:\n", - "\n", - "* a prompt configuration doesn't specify which AI service to use\n", - "* a prompt configuration requires a service unknown to the kernel\n", - "\n", - "The default can be set and changed programmatically:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "kernel.set_default_text_completion_service(\"Azure_curie\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Great, now that you're familiar with setting up the Semantic Kernel, let's see [how we can use it to run prompts](02-running-prompts-from-file.ipynb)." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.10" - }, - "polyglot_notebook": { - "kernelInfo": { - "items": [ - { - "aliases": [ - "frontend" - ], - "name": "vscode" - } - ] - } - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic Loading of the Kernel" + ] }, - "nbformat": 4, - "nbformat_minor": 2 + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run the notebooks we recommend using Poetry and starting a shell with a virtual environment\n", + "prepared to use SK. \n", + "\n", + "See [DEV_SETUP.md](../../../python/DEV_SETUP.md) for more information." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import semantic_kernel as sk\n", + "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can instantiate the kernel in a few ways, depending on your use case." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Simple instance\n", + "kernel_1 = sk.Kernel()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Instance with a custom logger\n", + "my_logger = sk.NullLogger()\n", + "kernel_2 = sk.Kernel(log=my_logger)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When using the kernel for AI requests, the kernel needs some settings like URL and credentials to the AI models.\n", + "\n", + "The SDK currently supports OpenAI and Azure OpenAI, other services will be added over time.\n", + "\n", + "If you need an Azure OpenAI key, go [here](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "kernel = sk.Kernel()\n", + "\n", + "kernel.add_text_completion_service( # We are adding a text service\n", + " \"Azure_curie\", # The alias we can use in prompt templates' config.json\n", + " AzureTextCompletion(\n", + " \"my-finetuned-Curie\", # Azure OpenAI *Deployment ID*\n", + " \"https://contoso.openai.azure.com/\", # Azure OpenAI *Endpoint*\n", + " \"...your Azure OpenAI Key...\" # Azure OpenAI *Key*\n", + " )\n", + ")\n", + "\n", + "kernel.add_text_completion_service( # We are adding a text service\n", + " \"OpenAI_davinci\", # The alias we can use in prompt templates' config.json\n", + " OpenAITextCompletion(\n", + " \"text-davinci-003\", # OpenAI Model Name\n", + " \"...your OpenAI API Key...\", # OpenAI API key\n", + " \"...your OpenAI Org ID...\" # *optional* OpenAI Organization ID\n", + " )\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When working with multiple services and multiple models, the **first service** defined\n", + "is also the \"**default**\" used in these scenarios:\n", + "\n", + "* a prompt configuration doesn't specify which AI service to use\n", + "* a prompt configuration requires a service unknown to the kernel\n", + "\n", + "The default can be set and changed programmatically:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "kernel.set_default_text_completion_service(\"Azure_curie\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Great, now that you're familiar with setting up the Semantic Kernel, let's see [how we can use it to run prompts](02-running-prompts-from-file.ipynb)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + }, + "polyglot_notebook": { + "kernelInfo": { + "items": [ + { + "aliases": [ + "frontend" + ], + "name": "vscode" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/samples/notebooks/python/02-running-prompts-from-file.ipynb b/samples/notebooks/python/02-running-prompts-from-file.ipynb index e81cae833f..cbbca0c7e3 100644 --- a/samples/notebooks/python/02-running-prompts-from-file.ipynb +++ b/samples/notebooks/python/02-running-prompts-from-file.ipynb @@ -1,191 +1,190 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "692e361b", - "metadata": {}, - "source": [ - "# How to run a semantic skills from file\n", - "Now that you're familiar with Kernel basics, let's see how the kernel allows you to run Semantic Skills and Semantic Functions stored on disk. \n", - "\n", - "A Semantic Skill is a collection of Semantic Functions, where each function is defined with natural language that can be provided with a text file. \n", - "\n", - "Refer to our [glossary](https://github.com/microsoft/semantic-kernel/blob/main/docs/GLOSSARY.md) for an in-depth guide to the terms.\n", - "\n", - "The repository includes some examples under the [samples](https://github.com/microsoft/semantic-kernel/tree/main/samples) folder.\n", - "\n", - "For instance, [this](../../skills/FunSkill/Joke/skprompt.txt) is the **Joke function** part of the **FunSkill skill**:" - ] - }, - { - "cell_type": "markdown", - "id": "f3ce1efe", - "metadata": {}, - "source": [ - "```\n", - "WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE TOPIC BELOW.\n", - "JOKE MUST BE:\n", - "- G RATED\n", - "- WORKPLACE/FAMILY SAFE\n", - "NO SEXISM, RACISM OR OTHER BIAS/BIGOTRY.\n", - "BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n", - "+++++\n", - "{{$input}}\n", - "+++++\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "afdb96d6", - "metadata": {}, - "source": [ - "Note the special **`{{$input}}`** token, which is a variable that is automatically passed when invoking the function, commonly referred to as a \"function parameter\". \n", - "\n", - "We'll explore later how functions can accept multiple variables, as well as invoke other functions." - ] - }, - { - "cell_type": "markdown", - "id": "c3bd5134", - "metadata": {}, - "source": [ - "\n", - "In the same folder you'll notice a second [config.json](../../skills/FunSkill/Joke/config.json) file. The file is optional, and is used to set some parameters for large language models like Temperature, TopP, Stop Sequences, etc.\n", - "\n", - "```\n", - "{\n", - " \"schema\": 1,\n", - " \"type\": \"completion\",\n", - " \"description\": \"Generate a funny joke\",\n", - " \"completion\": {\n", - " \"max_tokens\": 500,\n", - " \"temperature\": 0.5,\n", - " \"top_p\": 0.5\n", - " }\n", - "}\n", - "```" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "384ff07f", - "metadata": {}, - "source": [ - "Given a semantic function defined by these files, this is how to load and use a file based semantic function.\n", - "\n", - "Load and configure the kernel, as usual, loading also the AI service settings defined in the [Setup notebook](00-getting-started.ipynb):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "365cfc01", - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b0062a24", - "metadata": {}, - "outputs": [], - "source": [ - "import semantic_kernel as sk\n", - "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n", - "\n", - "kernel = sk.Kernel()\n", - "\n", - "useAzureOpenAI = False\n", - "\n", - "# Configure AI service used by the kernel\n", - "if useAzureOpenAI:\n", - " deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", - " kernel.add_text_completion_service(\"dv\", AzureTextCompletion(deployment, endpoint, api_key))\n", - "else:\n", - " api_key, org_id = sk.openai_settings_from_dot_env()\n", - " kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" - ] - }, - { - "cell_type": "markdown", - "id": "fd5ff1f4", - "metadata": {}, - "source": [ - "Import the skill and all its functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "56ee184d", - "metadata": {}, - "outputs": [], - "source": [ - "# note: using skills from the samples folder\n", - "skills_directory = \"../../skills\"\n", - "\n", - "funFunctions = kernel.import_semantic_skill_from_directory(skills_directory, \"FunSkill\")\n", - "\n", - "jokeFunction = funFunctions[\"Joke\"]" - ] - }, - { - "cell_type": "markdown", - "id": "edd99fa0", - "metadata": {}, - "source": [ - "How to use the skill functions, e.g. generate a joke about \"*time travel to dinosaur age*\":" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6effe63b", - "metadata": {}, - "outputs": [], - "source": [ - "result = jokeFunction(\"time travel to dinosaur age\")\n", - "\n", - "print(result)\n", - "\n", - "# You can also invoke functions asynchronously\n", - "# result = await jokeFunction.invoke_async(\"time travel to dinosaur age\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "2281a1fc", - "metadata": {}, - "source": [ - "Great, now that you know how to load a skill from disk, let's show how you can [create and run a semantic function inline.](./03-semantic-function-inline.ipynb)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.10" - } + "cells": [ + { + "cell_type": "markdown", + "id": "692e361b", + "metadata": {}, + "source": [ + "# How to run a semantic skills from file\n", + "Now that you're familiar with Kernel basics, let's see how the kernel allows you to run Semantic Skills and Semantic Functions stored on disk. \n", + "\n", + "A Semantic Skill is a collection of Semantic Functions, where each function is defined with natural language that can be provided with a text file. \n", + "\n", + "Refer to our [glossary](https://github.com/microsoft/semantic-kernel/blob/main/docs/GLOSSARY.md) for an in-depth guide to the terms.\n", + "\n", + "The repository includes some examples under the [samples](https://github.com/microsoft/semantic-kernel/tree/main/samples) folder.\n", + "\n", + "For instance, [this](../../skills/FunSkill/Joke/skprompt.txt) is the **Joke function** part of the **FunSkill skill**:" + ] }, - "nbformat": 4, - "nbformat_minor": 5 + { + "cell_type": "markdown", + "id": "f3ce1efe", + "metadata": {}, + "source": [ + "```\n", + "WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE TOPIC BELOW.\n", + "JOKE MUST BE:\n", + "- G RATED\n", + "- WORKPLACE/FAMILY SAFE\n", + "NO SEXISM, RACISM OR OTHER BIAS/BIGOTRY.\n", + "BE CREATIVE AND FUNNY. I WANT TO LAUGH.\n", + "+++++\n", + "{{$input}}\n", + "+++++\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "afdb96d6", + "metadata": {}, + "source": [ + "Note the special **`{{$input}}`** token, which is a variable that is automatically passed when invoking the function, commonly referred to as a \"function parameter\". \n", + "\n", + "We'll explore later how functions can accept multiple variables, as well as invoke other functions." + ] + }, + { + "cell_type": "markdown", + "id": "c3bd5134", + "metadata": {}, + "source": [ + "\n", + "In the same folder you'll notice a second [config.json](../../skills/FunSkill/Joke/config.json) file. The file is optional, and is used to set some parameters for large language models like Temperature, TopP, Stop Sequences, etc.\n", + "\n", + "```\n", + "{\n", + " \"schema\": 1,\n", + " \"type\": \"completion\",\n", + " \"description\": \"Generate a funny joke\",\n", + " \"completion\": {\n", + " \"max_tokens\": 500,\n", + " \"temperature\": 0.5,\n", + " \"top_p\": 0.5\n", + " }\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "384ff07f", + "metadata": {}, + "source": [ + "Given a semantic function defined by these files, this is how to load and use a file based semantic function.\n", + "\n", + "Load and configure the kernel, as usual, loading also the AI service settings defined in the [Setup notebook](00-getting-started.ipynb):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "365cfc01", + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b0062a24", + "metadata": {}, + "outputs": [], + "source": [ + "import semantic_kernel as sk\n", + "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n", + "\n", + "kernel = sk.Kernel()\n", + "\n", + "useAzureOpenAI = False\n", + "\n", + "# Configure AI service used by the kernel\n", + "if useAzureOpenAI:\n", + " deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", + " kernel.add_text_completion_service(\"dv\", AzureTextCompletion(deployment, endpoint, api_key))\n", + "else:\n", + " api_key, org_id = sk.openai_settings_from_dot_env()\n", + " kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" + ] + }, + { + "cell_type": "markdown", + "id": "fd5ff1f4", + "metadata": {}, + "source": [ + "Import the skill and all its functions:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56ee184d", + "metadata": {}, + "outputs": [], + "source": [ + "# note: using skills from the samples folder\n", + "skills_directory = \"../../skills\"\n", + "\n", + "funFunctions = kernel.import_semantic_skill_from_directory(skills_directory, \"FunSkill\")\n", + "\n", + "jokeFunction = funFunctions[\"Joke\"]" + ] + }, + { + "cell_type": "markdown", + "id": "edd99fa0", + "metadata": {}, + "source": [ + "How to use the skill functions, e.g. generate a joke about \"*time travel to dinosaur age*\":" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6effe63b", + "metadata": {}, + "outputs": [], + "source": [ + "result = jokeFunction(\"time travel to dinosaur age\")\n", + "\n", + "print(result)\n", + "\n", + "# You can also invoke functions asynchronously\n", + "# result = await jokeFunction.invoke_async(\"time travel to dinosaur age\")\n", + "# print(result)" + ] + }, + { + "cell_type": "markdown", + "id": "2281a1fc", + "metadata": {}, + "source": [ + "Great, now that you know how to load a skill from disk, let's show how you can [create and run a semantic function inline.](./03-semantic-function-inline.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/samples/notebooks/python/03-semantic-function-inline.ipynb b/samples/notebooks/python/03-semantic-function-inline.ipynb index dd5533d78a..fde4e6aa9c 100644 --- a/samples/notebooks/python/03-semantic-function-inline.ipynb +++ b/samples/notebooks/python/03-semantic-function-inline.ipynb @@ -1,219 +1,216 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "3c93ac5b", - "metadata": {}, - "source": [ - "# Running Semantic Functions Inline" - ] - }, - { - "cell_type": "markdown", - "id": "ebcabb91", - "metadata": {}, - "source": [] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "40201641", - "metadata": {}, - "source": [ - "The [previous notebook](./02-running-prompts-from-file.ipynb)\n", - "showed how to define a semantic function using a prompt template stored on a file.\n", - "\n", - "In this notebook, we'll show how to use the Semantic Kernel to define functions inline with your python code. This can be useful in a few scenarios:\n", - "\n", - "* Dynamically generating the prompt using complex rules at runtime\n", - "* Writing prompts by editing Python code instead of TXT files.\n", - "* Easily creating demos, like this document\n", - "\n", - "Prompt templates are defined using the SK template language, which allows to reference variables and functions. Read [this doc](https://aka.ms/sk/howto/configurefunction) to learn more about the design decisions for prompt templating. \n", - "\n", - "For now we'll use only the `{{$input}}` variable, and see more complex templates later.\n", - "\n", - "Almost all semantic function prompts have a reference to `{{$input}}`, which is the default way\n", - "a user can import content from the context variables." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "d90b0c13", - "metadata": {}, - "source": [ - "Prepare a semantic kernel instance first, loading also the AI service settings defined in the [Setup notebook](00-getting-started.ipynb):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1da651d4", - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3712b7c3", - "metadata": {}, - "outputs": [], - "source": [ - "import semantic_kernel as sk\n", - "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n", - "\n", - "kernel = sk.Kernel()\n", - "\n", - "useAzureOpenAI = False\n", - "\n", - "# Configure AI service used by the kernel\n", - "if useAzureOpenAI:\n", - " deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", - " kernel.add_text_completion_service(\"dv\", AzureTextCompletion(deployment, endpoint, api_key))\n", - "else:\n", - " api_key, org_id = sk.openai_settings_from_dot_env()\n", - " kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "589733c5", - "metadata": {}, - "source": [ - "Let's use a prompt to create a semantic function used to summarize content, allowing for some creativity and a sufficient number of tokens.\n", - "\n", - "The function will take in input the text to summarize." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ae29c207", - "metadata": {}, - "outputs": [], - "source": [ - "prompt = \"\"\"{{$input}}\n", - "Summarize the content above.\n", - "\"\"\"\n", - "\n", - "summarize = kernel.create_semantic_function(prompt, max_tokens=2000, temperature=0.2, top_p=0.5)" - ] - }, - { - "cell_type": "markdown", - "id": "f26b90c4", - "metadata": {}, - "source": [ - "Set up some content to summarize, here's an extract about Demo, an ancient Greek poet, taken from Wikipedia (https://en.wikipedia.org/wiki/Demo_(ancient_Greek_poet)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "314557fb", - "metadata": {}, - "outputs": [], - "source": [ - "input_text = \"\"\"\n", - "Demo (ancient Greek poet)\n", - "From Wikipedia, the free encyclopedia\n", - "Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the Roman period, known for a single epigram, engraved upon the Colossus of Memnon, which bears her name. She speaks of herself therein as a lyric poetess dedicated to the Muses, but nothing is known of her life.[1]\n", - "Identity\n", - "Demo was evidently Greek, as her name, a traditional epithet of Demeter, signifies. The name was relatively common in the Hellenistic world, in Egypt and elsewhere, and she cannot be further identified. The date of her visit to the Colossus of Memnon cannot be established with certainty, but internal evidence on the left leg suggests her poem was inscribed there at some point in or after AD 196.[2]\n", - "Epigram\n", - "There are a number of graffiti inscriptions on the Colossus of Memnon. Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the Greek inscription is difficult to read), is a dedication to the Muses.[2] The poem is traditionally published with the works of Balbilla, though the internal evidence suggests a different author.[1]\n", - "In the poem, Demo explains that Memnon has shown her special respect. In return, Demo offers the gift for poetry, as a gift to the hero. At the end of this epigram, she addresses Memnon, highlighting his divine status by recalling his strength and holiness.[2]\n", - "Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect. The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift', for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2] \n", - "\"\"\"" - ] - }, - { - "cell_type": "markdown", - "id": "bf0f2330", - "metadata": {}, - "source": [ - "...and run the summary function:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7b0e3b0c", - "metadata": {}, - "outputs": [], - "source": [ - "# If needed, async is available too: summary = await summarize.invoke_async(input_text)\n", - "summary = summarize(input_text)\n", - "\n", - "print(summary)" - ] - }, - { - "cell_type": "markdown", - "id": "4777f447", - "metadata": {}, - "source": [ - "Here's one more example of how to write an inline Semantic Function that gives a TLDR for a piece of text.\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ea8128c8", - "metadata": {}, - "outputs": [], - "source": [ - "sk_prompt = \"\"\"\n", - "{{$input}}\n", - "\n", - "Give me the TLDR in 5 words.\n", - "\"\"\"\n", - "\n", - "text = \"\"\"\n", - " 1) A robot may not injure a human being or, through inaction,\n", - " allow a human being to come to harm.\n", - "\n", - " 2) A robot must obey orders given it by human beings except where\n", - " such orders would conflict with the First Law.\n", - "\n", - " 3) A robot must protect its own existence as long as such protection\n", - " does not conflict with the First or Second Law.\n", - "\"\"\"\n", - "\n", - "tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)\n", - "\n", - "summary = tldr_function(text)\n", - "\n", - "print(f\"Output: {summary}\") # Output: Robots must not harm humans." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.10" - } + "cells": [ + { + "cell_type": "markdown", + "id": "3c93ac5b", + "metadata": {}, + "source": [ + "# Running Semantic Functions Inline" + ] }, - "nbformat": 4, - "nbformat_minor": 5 + { + "cell_type": "markdown", + "id": "ebcabb91", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "40201641", + "metadata": {}, + "source": [ + "The [previous notebook](./02-running-prompts-from-file.ipynb)\n", + "showed how to define a semantic function using a prompt template stored on a file.\n", + "\n", + "In this notebook, we'll show how to use the Semantic Kernel to define functions inline with your python code. This can be useful in a few scenarios:\n", + "\n", + "* Dynamically generating the prompt using complex rules at runtime\n", + "* Writing prompts by editing Python code instead of TXT files.\n", + "* Easily creating demos, like this document\n", + "\n", + "Prompt templates are defined using the SK template language, which allows to reference variables and functions. Read [this doc](https://aka.ms/sk/howto/configurefunction) to learn more about the design decisions for prompt templating. \n", + "\n", + "For now we'll use only the `{{$input}}` variable, and see more complex templates later.\n", + "\n", + "Almost all semantic function prompts have a reference to `{{$input}}`, which is the default way\n", + "a user can import content from the context variables." + ] + }, + { + "cell_type": "markdown", + "id": "d90b0c13", + "metadata": {}, + "source": [ + "Prepare a semantic kernel instance first, loading also the AI service settings defined in the [Setup notebook](00-getting-started.ipynb):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1da651d4", + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3712b7c3", + "metadata": {}, + "outputs": [], + "source": [ + "import semantic_kernel as sk\n", + "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n", + "\n", + "kernel = sk.Kernel()\n", + "\n", + "useAzureOpenAI = False\n", + "\n", + "# Configure AI service used by the kernel\n", + "if useAzureOpenAI:\n", + " deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", + " kernel.add_text_completion_service(\"dv\", AzureTextCompletion(deployment, endpoint, api_key))\n", + "else:\n", + " api_key, org_id = sk.openai_settings_from_dot_env()\n", + " kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" + ] + }, + { + "cell_type": "markdown", + "id": "589733c5", + "metadata": {}, + "source": [ + "Let's use a prompt to create a semantic function used to summarize content, allowing for some creativity and a sufficient number of tokens.\n", + "\n", + "The function will take in input the text to summarize." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae29c207", + "metadata": {}, + "outputs": [], + "source": [ + "prompt = \"\"\"{{$input}}\n", + "Summarize the content above.\n", + "\"\"\"\n", + "\n", + "summarize = kernel.create_semantic_function(prompt, max_tokens=2000, temperature=0.2, top_p=0.5)" + ] + }, + { + "cell_type": "markdown", + "id": "f26b90c4", + "metadata": {}, + "source": [ + "Set up some content to summarize, here's an extract about Demo, an ancient Greek poet, taken from Wikipedia (https://en.wikipedia.org/wiki/Demo_(ancient_Greek_poet)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "314557fb", + "metadata": {}, + "outputs": [], + "source": [ + "input_text = \"\"\"\n", + "Demo (ancient Greek poet)\n", + "From Wikipedia, the free encyclopedia\n", + "Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the Roman period, known for a single epigram, engraved upon the Colossus of Memnon, which bears her name. She speaks of herself therein as a lyric poetess dedicated to the Muses, but nothing is known of her life.[1]\n", + "Identity\n", + "Demo was evidently Greek, as her name, a traditional epithet of Demeter, signifies. The name was relatively common in the Hellenistic world, in Egypt and elsewhere, and she cannot be further identified. The date of her visit to the Colossus of Memnon cannot be established with certainty, but internal evidence on the left leg suggests her poem was inscribed there at some point in or after AD 196.[2]\n", + "Epigram\n", + "There are a number of graffiti inscriptions on the Colossus of Memnon. Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the Greek inscription is difficult to read), is a dedication to the Muses.[2] The poem is traditionally published with the works of Balbilla, though the internal evidence suggests a different author.[1]\n", + "In the poem, Demo explains that Memnon has shown her special respect. In return, Demo offers the gift for poetry, as a gift to the hero. At the end of this epigram, she addresses Memnon, highlighting his divine status by recalling his strength and holiness.[2]\n", + "Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic dialect. The language indicates she was knowledgeable in Homeric poetry—'bearing a pleasant gift', for example, alludes to the use of that phrase throughout the Iliad and Odyssey.[a][2] \n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "bf0f2330", + "metadata": {}, + "source": [ + "...and run the summary function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b0e3b0c", + "metadata": {}, + "outputs": [], + "source": [ + "# If needed, async is available too: summary = await summarize.invoke_async(input_text)\n", + "summary = summarize(input_text)\n", + "\n", + "print(summary)" + ] + }, + { + "cell_type": "markdown", + "id": "4777f447", + "metadata": {}, + "source": [ + "Here's one more example of how to write an inline Semantic Function that gives a TLDR for a piece of text.\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea8128c8", + "metadata": {}, + "outputs": [], + "source": [ + "sk_prompt = \"\"\"\n", + "{{$input}}\n", + "\n", + "Give me the TLDR in 5 words.\n", + "\"\"\"\n", + "\n", + "text = \"\"\"\n", + " 1) A robot may not injure a human being or, through inaction,\n", + " allow a human being to come to harm.\n", + "\n", + " 2) A robot must obey orders given it by human beings except where\n", + " such orders would conflict with the First Law.\n", + "\n", + " 3) A robot must protect its own existence as long as such protection\n", + " does not conflict with the First or Second Law.\n", + "\"\"\"\n", + "\n", + "tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)\n", + "\n", + "summary = tldr_function(text)\n", + "\n", + "print(f\"Output: {summary}\") # Output: Robots must not harm humans." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/samples/notebooks/python/04-context-variables-chat.ipynb b/samples/notebooks/python/04-context-variables-chat.ipynb index a31a1755c2..826b20ae56 100644 --- a/samples/notebooks/python/04-context-variables-chat.ipynb +++ b/samples/notebooks/python/04-context-variables-chat.ipynb @@ -1,246 +1,246 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "fde98ddf", - "metadata": {}, - "source": [ - "# Creating a basic chat experience with context variables\n", - "\n", - "In this example, we show how you can build a simple chat bot by sending and updating context with your requests. \n", - "\n", - "We introduce the Context Variables object which in this demo functions similarly as a key-value store that you can use when running the kernel.\n", - "\n", - "The context is local (i.e. in your computer's RAM) and not persisted anywhere beyond the life of this Jupyter session.\n", - "\n", - "In future examples, we will show how to persist the context on disk so that you can bring it into your applications. \n", - "\n", - "In this chat scenario, as the user talks back and forth with the bot, the context gets populated with the history of the conversation. During each new run of the kernel, the context can provide the AI with its variables' content. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "92f69b34", - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "68301108", - "metadata": {}, - "outputs": [], - "source": [ - "import semantic_kernel as sk\n", - "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n", - "\n", - "kernel = sk.Kernel()\n", - "\n", - "useAzureOpenAI = False\n", - "\n", - "# Configure AI service used by the kernel\n", - "if useAzureOpenAI:\n", - " api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", - " kernel.add_text_completion_service(\"dv\", AzureTextCompletion(\"text-davinci-003\", api_key, endpoint))\n", - "else:\n", - " api_key, org_id = sk.openai_settings_from_dot_env()\n", - " kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" - ] - }, - { - "cell_type": "markdown", - "id": "7971783d", - "metadata": {}, - "source": [ - "Let's define a prompt outlining a dialogue chat bot." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e84a05fc", - "metadata": {}, - "outputs": [], - "source": [ - "sk_prompt = \"\"\"\n", - "ChatBot can have a conversation with you about any topic.\n", - "It can give explicit instructions or say 'I don't know' if it does not have an answer.\n", - "\n", - "{{$history}}\n", - "User: {{$user_input}}\n", - "ChatBot: \"\"\"" - ] - }, - { - "cell_type": "markdown", - "id": "61716b16", - "metadata": {}, - "source": [ - "Register your semantic function" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a3e4b160", - "metadata": {}, - "outputs": [], - "source": [ - "chat_function = kernel.create_semantic_function(sk_prompt, \"ChatBot\", max_tokens=2000, temperature=0.7, top_p=0.5)" - ] - }, - { - "cell_type": "markdown", - "id": "6e8a676f", - "metadata": {}, - "source": [ - "Initialize your context" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a4be7394", - "metadata": {}, - "outputs": [], - "source": [ - "context_variables = sk.ContextVariables()\n", - "context_variables[\"history\"] = \"\"" - ] - }, - { - "cell_type": "markdown", - "id": "4ce7c497", - "metadata": {}, - "source": [ - "Chat with the Bot" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5ec41eb8", - "metadata": {}, - "outputs": [], - "source": [ - "context_variables[\"user_input\"] = \"Hi, I'm looking for book suggestions\"\n", - "bot_answer = await chat_function.invoke_async(variables=context_variables)\n", - "print(bot_answer)" - ] - }, - { - "cell_type": "markdown", - "id": "a5b03748", - "metadata": {}, - "source": [ - "Update the history with the output" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f50f517d", - "metadata": {}, - "outputs": [], - "source": [ - "context_variables[\"history\"] += f\"\\nUser: {context_variables['user_input']}\\nChatBot: {bot_answer}\\n\"\n", - "print(context_variables[\"history\"])" - ] - }, - { - "cell_type": "markdown", - "id": "23a2eb02", - "metadata": {}, - "source": [ - "Keep Chatting!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c59efe45", - "metadata": {}, - "outputs": [], - "source": [ - "async def chat(input_text: str) -> None:\n", - " # Save new message in the context variables\n", - " print(f\"User: {input_text}\")\n", - " context_variables[\"user_input\"] = input_text\n", - "\n", - " # Process the user message and get an answer\n", - " answer = await chat_function.invoke_async(variables=context_variables)\n", - "\n", - " # Show the response\n", - " print(f\"ChatBot: {answer}\")\n", - "\n", - " # Append the new interaction to the chat history\n", - " context_variables[\"history\"] += f\"\\nUser: {input_text}\\nChatBot: {answer}\\n\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "06ee244e", - "metadata": {}, - "outputs": [], - "source": [ - "await chat(\"I love history and philosophy, I'd like to learn something new about Greece, any suggestion?\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "82be4e7e", - "metadata": {}, - "outputs": [], - "source": [ - "await chat(\"that sounds interesting, what is it about?\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "82fe0139", - "metadata": {}, - "outputs": [], - "source": [ - "await chat(\"if I read that book, what exactly will I learn about Greece history?\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "55b3a9f2", - "metadata": {}, - "outputs": [], - "source": [ - "await chat(\"could you list some more books I could read about this topic?\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.5" - } + "cells": [ + { + "cell_type": "markdown", + "id": "fde98ddf", + "metadata": {}, + "source": [ + "# Creating a basic chat experience with context variables\n", + "\n", + "In this example, we show how you can build a simple chat bot by sending and updating context with your requests. \n", + "\n", + "We introduce the Context Variables object which in this demo functions similarly as a key-value store that you can use when running the kernel.\n", + "\n", + "The context is local (i.e. in your computer's RAM) and not persisted anywhere beyond the life of this Jupyter session.\n", + "\n", + "In future examples, we will show how to persist the context on disk so that you can bring it into your applications. \n", + "\n", + "In this chat scenario, as the user talks back and forth with the bot, the context gets populated with the history of the conversation. During each new run of the kernel, the context can provide the AI with its variables' content. " + ] }, - "nbformat": 4, - "nbformat_minor": 5 + { + "cell_type": "code", + "execution_count": null, + "id": "92f69b34", + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "68301108", + "metadata": {}, + "outputs": [], + "source": [ + "import semantic_kernel as sk\n", + "from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion\n", + "\n", + "kernel = sk.Kernel()\n", + "\n", + "useAzureOpenAI = False\n", + "\n", + "# Configure AI service used by the kernel\n", + "if useAzureOpenAI:\n", + " api_key, endpoint = sk.azure_openai_settings_from_dot_env()\n", + " kernel.add_text_completion_service(\"dv\", AzureTextCompletion(\"text-davinci-003\", api_key, endpoint))\n", + "else:\n", + " api_key, org_id = sk.openai_settings_from_dot_env()\n", + " kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))" + ] + }, + { + "cell_type": "markdown", + "id": "7971783d", + "metadata": {}, + "source": [ + "Let's define a prompt outlining a dialogue chat bot." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e84a05fc", + "metadata": {}, + "outputs": [], + "source": [ + "sk_prompt = \"\"\"\n", + "ChatBot can have a conversation with you about any topic.\n", + "It can give explicit instructions or say 'I don't know' if it does not have an answer.\n", + "\n", + "{{$history}}\n", + "User: {{$user_input}}\n", + "ChatBot: \"\"\"" + ] + }, + { + "cell_type": "markdown", + "id": "61716b16", + "metadata": {}, + "source": [ + "Register your semantic function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3e4b160", + "metadata": {}, + "outputs": [], + "source": [ + "chat_function = kernel.create_semantic_function(sk_prompt, \"ChatBot\", max_tokens=2000, temperature=0.7, top_p=0.5)" + ] + }, + { + "cell_type": "markdown", + "id": "6e8a676f", + "metadata": {}, + "source": [ + "Initialize your context" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4be7394", + "metadata": {}, + "outputs": [], + "source": [ + "context = kernel.create_new_context()\n", + "context[\"history\"] = \"\"" + ] + }, + { + "cell_type": "markdown", + "id": "4ce7c497", + "metadata": {}, + "source": [ + "Chat with the Bot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5ec41eb8", + "metadata": {}, + "outputs": [], + "source": [ + "context[\"user_input\"] = \"Hi, I'm looking for book suggestions\"\n", + "bot_answer = await chat_function.invoke_async(context=context)\n", + "print(bot_answer)" + ] + }, + { + "cell_type": "markdown", + "id": "a5b03748", + "metadata": {}, + "source": [ + "Update the history with the output" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f50f517d", + "metadata": {}, + "outputs": [], + "source": [ + "context[\"history\"] += f\"\\nUser: {context['user_input']}\\nChatBot: {bot_answer}\\n\"\n", + "print(context[\"history\"])" + ] + }, + { + "cell_type": "markdown", + "id": "23a2eb02", + "metadata": {}, + "source": [ + "Keep Chatting!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c59efe45", + "metadata": {}, + "outputs": [], + "source": [ + "async def chat(input_text: str) -> None:\n", + " # Save new message in the context variables\n", + " print(f\"User: {input_text}\")\n", + " context[\"user_input\"] = input_text\n", + "\n", + " # Process the user message and get an answer\n", + " answer = await chat_function.invoke_async(context=context)\n", + "\n", + " # Show the response\n", + " print(f\"ChatBot: {answer}\")\n", + "\n", + " # Append the new interaction to the chat history\n", + " context[\"history\"] += f\"\\nUser: {input_text}\\nChatBot: {answer}\\n\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06ee244e", + "metadata": {}, + "outputs": [], + "source": [ + "await chat(\"I love history and philosophy, I'd like to learn something new about Greece, any suggestion?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "82be4e7e", + "metadata": {}, + "outputs": [], + "source": [ + "await chat(\"that sounds interesting, what is it about?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "82fe0139", + "metadata": {}, + "outputs": [], + "source": [ + "await chat(\"if I read that book, what exactly will I learn about Greece history?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55b3a9f2", + "metadata": {}, + "outputs": [], + "source": [ + "await chat(\"could you list some more books I could read about this topic?\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/samples/notebooks/python/05-using-the-planner.ipynb b/samples/notebooks/python/05-using-the-planner.ipynb index dd111f9180..02f33efd1a 100644 --- a/samples/notebooks/python/05-using-the-planner.ipynb +++ b/samples/notebooks/python/05-using-the-planner.ipynb @@ -18,17 +18,17 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "04e5cf15", "metadata": {}, "outputs": [], "source": [ - "# !python -m pip install -r requirements.txt" + "!python -m pip install semantic-kernel==0.2.7.dev0" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "11e59885", "metadata": {}, "outputs": [], @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "e2e90624", "metadata": {}, "outputs": [], @@ -82,7 +82,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "ca0e7604", "metadata": {}, "outputs": [], @@ -105,7 +105,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "0d537981", "metadata": {}, "outputs": [], @@ -118,25 +118,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "88411884", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " {\n", - " \"input\": \"Valentine's Day Date Ideas\",\n", - " \"subtasks\": [\n", - " {\"function\": \"WriterSkill.Brainstorm\"},\n", - " {\"function\": \"WriterSkill.Translate\", \"args\": {\"language\": \"French\"}},\n", - " {\"function\": \"TextSkill.Uppercase\"}\n", - " ]\n", - " }\n" - ] - } - ], + "outputs": [], "source": [ "print(original_plan.generated_plan)" ] @@ -170,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "e973007f", "metadata": {}, "outputs": [], @@ -194,7 +179,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "bfd23ac4", "metadata": {}, "outputs": [], @@ -209,26 +194,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "b09c4834", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " {\n", - " \"input\": \"Valentine's Day Date Ideas\",\n", - " \"subtasks\": [\n", - " {\"function\": \"WriterSkill.Brainstorm\"},\n", - " {\"function\": \"ShakespeareSkill.shakespeare\"},\n", - " {\"function\": \"WriterSkill.Translate\", \"args\": {\"language\": \"French\"}},\n", - " {\"function\": \"TextSkill.uppercase\"}\n", - " ]\n", - " }\n" - ] - } - ], + "outputs": [], "source": [ "print(new_plan.generated_plan)" ] @@ -245,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "cf30b5da", "metadata": {}, "outputs": [], @@ -255,27 +224,10 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "eb9727c0", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. FAITES UN TOUR ROMANTIQUE À TRAVERS LE MERVEILLEUX PARC\n", - "2. ÉTALEZ UNE NAPPE JOYEUSE DANS LA COUR ÉQUITABLE\n", - "3. COMPOSER UN DÉLICIEUX REPAS MAIN DANS LA MAIN\n", - "4. ERRER DANS UN MUSÉE DIGNE DES ÉTOILES\n", - "5. VOIR UN FILM DOUX, UN CONTE MÉLODIEUX D'AMOUR\n", - "6. PRENDRE UNE LEÇON POLIE DE DANSE\n", - "7. VOYAGEZ DANS UNE PROSPÈRE VILLE À PROXIMITÉ\n", - "8. DESCENDEZ À UN MAGNIFIQUE PROMONTOIRE PRÈS DE LA MER\n", - "9. ACCORDER UNE JOURNÉE LUXUEUSE DE RELAXATION À L'AUTRE\n", - "10. ÉCRIRE DES NOTES AIMABLES ET CHALEUREUSES D'AMOUR\n" - ] - } - ], + "outputs": [], "source": [ "print(results)" ] diff --git a/samples/notebooks/python/06-memory-and-embeddings.ipynb b/samples/notebooks/python/06-memory-and-embeddings.ipynb index 1d8c776100..a4a38e60f4 100644 --- a/samples/notebooks/python/06-memory-and-embeddings.ipynb +++ b/samples/notebooks/python/06-memory-and-embeddings.ipynb @@ -1,408 +1,403 @@ { - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "id": "68e1c158", - "metadata": {}, - "source": [ - "# Building Semantic Memory with Embeddings\n", - "\n", - "So far, we've mostly been treating the kernel as a stateless orchestration engine.\n", - "We send text into a model API and receive text out. \n", - "\n", - "In a [previous notebook](04-context-variables-chat.ipynb), we used `context variables` to pass in additional\n", - "text into prompts to enrich them with more context. This allowed us to create a basic chat experience. \n", - "\n", - "However, if you solely relied on context variables, you would quickly realize that eventually your prompt\n", - "would grow so large that you would run into a the model's token limit. What we need is a way to persist state\n", - "and build both short-term and long-term memory to empower even more intelligent applications. \n", - "\n", - "To do this, we dive into the key concept of `Semantic Memory` in the Semantic Kernel. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a77bdf89", - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "508ad44f", - "metadata": {}, - "outputs": [], - "source": [ - "from typing import Tuple\n", - "\n", - "import semantic_kernel as sk\n", - "from semantic_kernel.connectors.ai.open_ai import OpenAITextCompletion, OpenAITextEmbedding" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "d8ddffc1", - "metadata": {}, - "source": [ - "In order to use memory, we need to instantiate the Kernel with a Memory Storage\n", - "and an Embedding service. 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). 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, - "id": "8f8dcbc6", - "metadata": {}, - "outputs": [], - "source": [ - "kernel = sk.Kernel()\n", - "\n", - "api_key, org_id = sk.openai_settings_from_dot_env()\n", - "kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))\n", - "kernel.add_text_embedding_generation_service(\"ada\", OpenAITextEmbedding(\"text-embedding-ada-002\", api_key, org_id))\n", - "\n", - "kernel.register_memory_store(memory_store=sk.memory.VolatileMemoryStore())\n", - "kernel.import_skill(sk.core_skills.TextMemorySkill())" - ] - }, - { - "cell_type": "markdown", - "id": "e7fefb6a", - "metadata": {}, - "source": [ - "At its core, Semantic Memory is a set of data structures that allow you to store the meaning of text that come from different data sources, and optionally to store the source text too. These texts can be from the web, e-mail providers, chats, a database, or from your local directory, and are hooked up to the Semantic Kernel through data source connectors.\n", - "\n", - "The texts are embedded or compressed into a vector of floats representing mathematically the texts' contents and meaning. You can read more about embeddings [here](https://aka.ms/sk/embeddings)." - ] - }, - { - "cell_type": "markdown", - "id": "2a7e7ca4", - "metadata": {}, - "source": [ - "### Manually adding memories\n", - "Let's create some initial memories \"About Me\". We can add memories to our `VolatileMemoryStore` by using `SaveInformationAsync`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d096504c", - "metadata": {}, - "outputs": [], - "source": [ - "async def populate_memory(kernel: sk.Kernel) -> None:\n", - " # Add some documents to the semantic memory\n", - " await kernel.memory.save_information_async(\n", - " \"aboutMe\", id=\"info1\", text=\"My name is Andrea\"\n", - " )\n", - " await kernel.memory.save_information_async(\n", - " \"aboutMe\", id=\"info2\", text=\"I currently work as a tour guide\"\n", - " )\n", - " await kernel.memory.save_information_async(\n", - " \"aboutMe\", id=\"info3\", text=\"I've been living in Seattle since 2005\"\n", - " )\n", - " await kernel.memory.save_information_async(\n", - " \"aboutMe\", id=\"info4\", text=\"I visited France and Italy five times since 2015\"\n", - " )\n", - " await kernel.memory.save_information_async(\n", - " \"aboutMe\", id=\"info5\", text=\"My family is from New York\"\n", - " )" - ] - }, - { - "cell_type": "markdown", - "id": "2caf8575", - "metadata": {}, - "source": [ - "Let's try searching the memory:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "628c843e", - "metadata": {}, - "outputs": [], - "source": [ - "async def search_memory_examples(kernel: sk.Kernel) -> None:\n", - " questions = [\n", - " \"what's my name\",\n", - " \"where do I live?\",\n", - " \"where's my family from?\",\n", - " \"where have I traveled?\",\n", - " \"what do I do for work\",\n", - " ]\n", - "\n", - " for question in questions:\n", - " print(f\"Question: {question}\")\n", - " result = await kernel.memory.search_async(\"aboutMe\", question)\n", - " print(f\"Answer: {result[0].text}\\n\")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "e70c2b22", - "metadata": {}, - "source": [ - "Let's now revisit the our chat sample from the [previous notebook](04-context-variables-chat.ipynb).\n", - "If you remember, we used context variables to fill the prompt with a `history` that continuously got populated as we chatted with the bot. Let's add also memory to it!" - ] - }, - { - "cell_type": "markdown", - "id": "1ed54a32", - "metadata": {}, - "source": [ - "This is done by using the `TextMemorySkill` which exposes the `recall` native function.\n", - "\n", - "`recall` takes an input ask and performs a similarity search on the contents that have\n", - "been embedded in the Memory Store and returns the most relevant memory. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fb8549b2", - "metadata": {}, - "outputs": [], - "source": [ - "async def setup_chat_with_memory(\n", - " kernel: sk.Kernel,\n", - ") -> Tuple[sk.SKFunctionBase, sk.SKContext]:\n", - " sk_prompt = \"\"\"\n", - " ChatBot can have a conversation with you about any topic.\n", - " It can give explicit instructions or say 'I don't know' if\n", - " it does not have an answer.\n", - "\n", - " Information about me, from previous conversations:\n", - " - {{$fact1}} {{recall $fact1}}\n", - " - {{$fact2}} {{recall $fact2}}\n", - " - {{$fact3}} {{recall $fact3}}\n", - " - {{$fact4}} {{recall $fact4}}\n", - " - {{$fact5}} {{recall $fact5}}\n", - "\n", - " Chat:\n", - " {{$chat_history}}\n", - " User: {{$user_input}}\n", - " ChatBot: \"\"\".strip()\n", - "\n", - " chat_func = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0.8)\n", - "\n", - " context = kernel.create_new_context()\n", - " context[\"fact1\"] = \"what is my name?\"\n", - " context[\"fact2\"] = \"where do I live?\"\n", - " context[\"fact3\"] = \"where's my family from?\"\n", - " context[\"fact4\"] = \"where have I traveled?\"\n", - " context[\"fact5\"] = \"what do I do for work?\"\n", - "\n", - " context[sk.core_skills.TextMemorySkill.COLLECTION_PARAM] = \"aboutMe\"\n", - " context[sk.core_skills.TextMemorySkill.RELEVANCE_PARAM] = 0.8\n", - "\n", - " context[\"chat_history\"] = \"\"\n", - "\n", - " return chat_func, context" - ] - }, - { - "cell_type": "markdown", - "id": "1ac62457", - "metadata": {}, - "source": [ - "The `RelevanceParam` is used in memory search and is a measure of the relevance score from 0.0 to 1.0, where 1.0 means a perfect match. We encourage users to experiment with different values." - ] - }, - { - "cell_type": "markdown", - "id": "645b55a1", - "metadata": {}, - "source": [ - "Now that we've included our memories, let's chat!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "75267a2f", - "metadata": {}, - "outputs": [], - "source": [ - "async def chat(\n", - " kernel: sk.Kernel, chat_func: sk.SKFunctionBase, context: sk.SKContext\n", - ") -> bool:\n", - " try:\n", - " user_input = input(\"User:> \")\n", - " context[\"user_input\"] = user_input\n", - " print(f\"User:> {user_input}\")\n", - " except KeyboardInterrupt:\n", - " print(\"\\n\\nExiting chat...\")\n", - " return False\n", - " except EOFError:\n", - " print(\"\\n\\nExiting chat...\")\n", - " return False\n", - "\n", - " if user_input == \"exit\":\n", - " print(\"\\n\\nExiting chat...\")\n", - " return False\n", - "\n", - " answer = await kernel.run_async(chat_func, input_vars=context.variables)\n", - " context[\"chat_history\"] += f\"\\nUser:> {user_input}\\nChatBot:> {answer}\\n\"\n", - "\n", - " print(f\"ChatBot:> {answer}\")\n", - " return True" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3875a34", - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Populating memory...\")\n", - "await populate_memory(kernel)\n", - "\n", - "print(\"Asking questions... (manually)\")\n", - "await search_memory_examples(kernel)\n", - "\n", - "print(\"Setting up a chat (with memory!)\")\n", - "chat_func, context = await setup_chat_with_memory(kernel)\n", - "\n", - "print(\"Begin chatting (type 'exit' to exit):\\n\")\n", - "chatting = True\n", - "while chatting:\n", - " chatting = await chat(kernel, chat_func, context)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "0a51542b", - "metadata": {}, - "source": [ - "### Adding documents to your memory\n", - "\n", - "Many times in your applications you'll want to bring in external documents into your memory. Let's see how we can do this using our VolatileMemoryStore.\n", - "\n", - "Let's first get some data using some of the links in the Semantic Kernel repo." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3d5a1b9", - "metadata": {}, - "outputs": [], - "source": [ - "github_files ={}\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/README.md\"] = \\\n", - " \"README: Installation, getting started, and how to contribute\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb\"] = \\\n", - " \"Jupyter notebook describing how to pass prompts from a file to a semantic skill or function\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb\"] = \\\n", - " \"Jupyter notebook describing how to get started with the Semantic Kernel\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT\"] = \\\n", - " \"Sample demonstrating how to create a chat skill interfacing with ChatGPT\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/Volatile/VolatileMemoryStore.cs\"] = \\\n", - " \"C# class that defines a volatile embedding store\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md\"] = \\\n", - " \"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4\"\n", - "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md\"] = \\\n", - " \"README: README associated with a sample starter react-based chat summary webapp\"" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "75f3ea5e", - "metadata": {}, - "source": [ - "Now let's add these files to our VolatileMemoryStore using `SaveReferenceAsync`. We'll separate these memories from the chat memories by putting them in a different collection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "170e7142", - "metadata": {}, - "outputs": [], - "source": [ - "memory_collection_name = \"SKGitHub\"\n", - "print(\"Adding some GitHub file URLs and their descriptions to a volatile Semantic Memory.\");\n", - "i = 0\n", - "for entry, value in github_files.items():\n", - " await kernel.memory.save_reference_async(\n", - " collection=memory_collection_name,\n", - " description=value,\n", - " text=value,\n", - " external_id=entry,\n", - " external_source_name=\"GitHub\"\n", - " )\n", - " i += 1\n", - " print(\" URL {} saved\".format(i))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "143911c3", - "metadata": {}, - "outputs": [], - "source": [ - "ask = \"I love Jupyter notebooks, how should I get started?\"\n", - "print(\"===========================\\n\" + \"Query: \" + ask + \"\\n\")\n", - "\n", - "memories = await kernel.memory.search_async(memory_collection_name, ask, limit=5, min_relevance_score=0.77)\n", - "\n", - "i = 0\n", - "for memory in memories:\n", - " i += 1\n", - " print(f\"Result {i}:\")\n", - " print(\" URL: : \" + memory.id)\n", - " print(\" Title : \" + memory.description)\n", - " print(\" Relevance: \" + str(memory.relevance))\n", - " print()" - ] - }, - { - "cell_type": "markdown", - "id": "59294dac", - "metadata": {}, - "source": [ - "Now you might be wondering what happens if you have so much data that it doesn't fit into your RAM? That's where you want to make use of an external Vector Database made specifically for storing and retrieving embeddings.\n", - "\n", - "Stay tuned for that!" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.5" - } + "cells": [ + { + "cell_type": "markdown", + "id": "68e1c158", + "metadata": {}, + "source": [ + "# Building Semantic Memory with Embeddings\n", + "\n", + "So far, we've mostly been treating the kernel as a stateless orchestration engine.\n", + "We send text into a model API and receive text out. \n", + "\n", + "In a [previous notebook](04-context-variables-chat.ipynb), we used `context variables` to pass in additional\n", + "text into prompts to enrich them with more context. This allowed us to create a basic chat experience. \n", + "\n", + "However, if you solely relied on context variables, you would quickly realize that eventually your prompt\n", + "would grow so large that you would run into a the model's token limit. What we need is a way to persist state\n", + "and build both short-term and long-term memory to empower even more intelligent applications. \n", + "\n", + "To do this, we dive into the key concept of `Semantic Memory` in the Semantic Kernel. " + ] }, - "nbformat": 4, - "nbformat_minor": 5 + { + "cell_type": "code", + "execution_count": null, + "id": "a77bdf89", + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "508ad44f", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Tuple\n", + "\n", + "import semantic_kernel as sk\n", + "from semantic_kernel.connectors.ai.open_ai import OpenAITextCompletion, OpenAITextEmbedding" + ] + }, + { + "cell_type": "markdown", + "id": "d8ddffc1", + "metadata": {}, + "source": [ + "In order to use memory, we need to instantiate the Kernel with a Memory Storage\n", + "and an Embedding service. 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). 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, + "id": "8f8dcbc6", + "metadata": {}, + "outputs": [], + "source": [ + "kernel = sk.Kernel()\n", + "\n", + "api_key, org_id = sk.openai_settings_from_dot_env()\n", + "kernel.add_text_completion_service(\"dv\", OpenAITextCompletion(\"text-davinci-003\", api_key, org_id))\n", + "kernel.add_text_embedding_generation_service(\"ada\", OpenAITextEmbedding(\"text-embedding-ada-002\", api_key, org_id))\n", + "\n", + "kernel.register_memory_store(memory_store=sk.memory.VolatileMemoryStore())\n", + "kernel.import_skill(sk.core_skills.TextMemorySkill())" + ] + }, + { + "cell_type": "markdown", + "id": "e7fefb6a", + "metadata": {}, + "source": [ + "At its core, Semantic Memory is a set of data structures that allow you to store the meaning of text that come from different data sources, and optionally to store the source text too. These texts can be from the web, e-mail providers, chats, a database, or from your local directory, and are hooked up to the Semantic Kernel through data source connectors.\n", + "\n", + "The texts are embedded or compressed into a vector of floats representing mathematically the texts' contents and meaning. You can read more about embeddings [here](https://aka.ms/sk/embeddings)." + ] + }, + { + "cell_type": "markdown", + "id": "2a7e7ca4", + "metadata": {}, + "source": [ + "### Manually adding memories\n", + "Let's create some initial memories \"About Me\". We can add memories to our `VolatileMemoryStore` by using `SaveInformationAsync`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d096504c", + "metadata": {}, + "outputs": [], + "source": [ + "async def populate_memory(kernel: sk.Kernel) -> None:\n", + " # Add some documents to the semantic memory\n", + " await kernel.memory.save_information_async(\n", + " \"aboutMe\", id=\"info1\", text=\"My name is Andrea\"\n", + " )\n", + " await kernel.memory.save_information_async(\n", + " \"aboutMe\", id=\"info2\", text=\"I currently work as a tour guide\"\n", + " )\n", + " await kernel.memory.save_information_async(\n", + " \"aboutMe\", id=\"info3\", text=\"I've been living in Seattle since 2005\"\n", + " )\n", + " await kernel.memory.save_information_async(\n", + " \"aboutMe\", id=\"info4\", text=\"I visited France and Italy five times since 2015\"\n", + " )\n", + " await kernel.memory.save_information_async(\n", + " \"aboutMe\", id=\"info5\", text=\"My family is from New York\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "2caf8575", + "metadata": {}, + "source": [ + "Let's try searching the memory:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "628c843e", + "metadata": {}, + "outputs": [], + "source": [ + "async def search_memory_examples(kernel: sk.Kernel) -> None:\n", + " questions = [\n", + " \"what's my name\",\n", + " \"where do I live?\",\n", + " \"where's my family from?\",\n", + " \"where have I traveled?\",\n", + " \"what do I do for work\",\n", + " ]\n", + "\n", + " for question in questions:\n", + " print(f\"Question: {question}\")\n", + " result = await kernel.memory.search_async(\"aboutMe\", question)\n", + " print(f\"Answer: {result[0].text}\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "e70c2b22", + "metadata": {}, + "source": [ + "Let's now revisit the our chat sample from the [previous notebook](04-context-variables-chat.ipynb).\n", + "If you remember, we used context variables to fill the prompt with a `history` that continuously got populated as we chatted with the bot. Let's add also memory to it!" + ] + }, + { + "cell_type": "markdown", + "id": "1ed54a32", + "metadata": {}, + "source": [ + "This is done by using the `TextMemorySkill` which exposes the `recall` native function.\n", + "\n", + "`recall` takes an input ask and performs a similarity search on the contents that have\n", + "been embedded in the Memory Store and returns the most relevant memory. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb8549b2", + "metadata": {}, + "outputs": [], + "source": [ + "async def setup_chat_with_memory(\n", + " kernel: sk.Kernel,\n", + ") -> Tuple[sk.SKFunctionBase, sk.SKContext]:\n", + " sk_prompt = \"\"\"\n", + " ChatBot can have a conversation with you about any topic.\n", + " It can give explicit instructions or say 'I don't know' if\n", + " it does not have an answer.\n", + "\n", + " Information about me, from previous conversations:\n", + " - {{$fact1}} {{recall $fact1}}\n", + " - {{$fact2}} {{recall $fact2}}\n", + " - {{$fact3}} {{recall $fact3}}\n", + " - {{$fact4}} {{recall $fact4}}\n", + " - {{$fact5}} {{recall $fact5}}\n", + "\n", + " Chat:\n", + " {{$chat_history}}\n", + " User: {{$user_input}}\n", + " ChatBot: \"\"\".strip()\n", + "\n", + " chat_func = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0.8)\n", + "\n", + " context = kernel.create_new_context()\n", + " context[\"fact1\"] = \"what is my name?\"\n", + " context[\"fact2\"] = \"where do I live?\"\n", + " context[\"fact3\"] = \"where's my family from?\"\n", + " context[\"fact4\"] = \"where have I traveled?\"\n", + " context[\"fact5\"] = \"what do I do for work?\"\n", + "\n", + " context[sk.core_skills.TextMemorySkill.COLLECTION_PARAM] = \"aboutMe\"\n", + " context[sk.core_skills.TextMemorySkill.RELEVANCE_PARAM] = 0.8\n", + "\n", + " context[\"chat_history\"] = \"\"\n", + "\n", + " return chat_func, context" + ] + }, + { + "cell_type": "markdown", + "id": "1ac62457", + "metadata": {}, + "source": [ + "The `RelevanceParam` is used in memory search and is a measure of the relevance score from 0.0 to 1.0, where 1.0 means a perfect match. We encourage users to experiment with different values." + ] + }, + { + "cell_type": "markdown", + "id": "645b55a1", + "metadata": {}, + "source": [ + "Now that we've included our memories, let's chat!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75267a2f", + "metadata": {}, + "outputs": [], + "source": [ + "async def chat(\n", + " kernel: sk.Kernel, chat_func: sk.SKFunctionBase, context: sk.SKContext\n", + ") -> bool:\n", + " try:\n", + " user_input = input(\"User:> \")\n", + " context[\"user_input\"] = user_input\n", + " print(f\"User:> {user_input}\")\n", + " except KeyboardInterrupt:\n", + " print(\"\\n\\nExiting chat...\")\n", + " return False\n", + " except EOFError:\n", + " print(\"\\n\\nExiting chat...\")\n", + " return False\n", + "\n", + " if user_input == \"exit\":\n", + " print(\"\\n\\nExiting chat...\")\n", + " return False\n", + "\n", + " answer = await kernel.run_async(chat_func, input_vars=context.variables)\n", + " context[\"chat_history\"] += f\"\\nUser:> {user_input}\\nChatBot:> {answer}\\n\"\n", + "\n", + " print(f\"ChatBot:> {answer}\")\n", + " return True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3875a34", + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Populating memory...\")\n", + "await populate_memory(kernel)\n", + "\n", + "print(\"Asking questions... (manually)\")\n", + "await search_memory_examples(kernel)\n", + "\n", + "print(\"Setting up a chat (with memory!)\")\n", + "chat_func, context = await setup_chat_with_memory(kernel)\n", + "\n", + "print(\"Begin chatting (type 'exit' to exit):\\n\")\n", + "chatting = True\n", + "while chatting:\n", + " chatting = await chat(kernel, chat_func, context)" + ] + }, + { + "cell_type": "markdown", + "id": "0a51542b", + "metadata": {}, + "source": [ + "### Adding documents to your memory\n", + "\n", + "Many times in your applications you'll want to bring in external documents into your memory. Let's see how we can do this using our VolatileMemoryStore.\n", + "\n", + "Let's first get some data using some of the links in the Semantic Kernel repo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3d5a1b9", + "metadata": {}, + "outputs": [], + "source": [ + "github_files ={}\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/README.md\"] = \\\n", + " \"README: Installation, getting started, and how to contribute\"\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb\"] = \\\n", + " \"Jupyter notebook describing how to pass prompts from a file to a semantic skill or function\"\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb\"] = \\\n", + " \"Jupyter notebook describing how to get started with the Semantic Kernel\"\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT\"] = \\\n", + " \"Sample demonstrating how to create a chat skill interfacing with ChatGPT\"\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/Volatile/VolatileMemoryStore.cs\"] = \\\n", + " \"C# class that defines a volatile embedding store\"\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md\"] = \\\n", + " \"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4\"\n", + "github_files[\"https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md\"] = \\\n", + " \"README: README associated with a sample starter react-based chat summary webapp\"" + ] + }, + { + "cell_type": "markdown", + "id": "75f3ea5e", + "metadata": {}, + "source": [ + "Now let's add these files to our VolatileMemoryStore using `SaveReferenceAsync`. We'll separate these memories from the chat memories by putting them in a different collection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "170e7142", + "metadata": {}, + "outputs": [], + "source": [ + "memory_collection_name = \"SKGitHub\"\n", + "print(\"Adding some GitHub file URLs and their descriptions to a volatile Semantic Memory.\");\n", + "i = 0\n", + "for entry, value in github_files.items():\n", + " await kernel.memory.save_reference_async(\n", + " collection=memory_collection_name,\n", + " description=value,\n", + " text=value,\n", + " external_id=entry,\n", + " external_source_name=\"GitHub\"\n", + " )\n", + " i += 1\n", + " print(\" URL {} saved\".format(i))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "143911c3", + "metadata": {}, + "outputs": [], + "source": [ + "ask = \"I love Jupyter notebooks, how should I get started?\"\n", + "print(\"===========================\\n\" + \"Query: \" + ask + \"\\n\")\n", + "\n", + "memories = await kernel.memory.search_async(memory_collection_name, ask, limit=5, min_relevance_score=0.77)\n", + "\n", + "i = 0\n", + "for memory in memories:\n", + " i += 1\n", + " print(f\"Result {i}:\")\n", + " print(\" URL: : \" + memory.id)\n", + " print(\" Title : \" + memory.description)\n", + " print(\" Relevance: \" + str(memory.relevance))\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "id": "59294dac", + "metadata": {}, + "source": [ + "Now you might be wondering what happens if you have so much data that it doesn't fit into your RAM? That's where you want to make use of an external Vector Database made specifically for storing and retrieving embeddings.\n", + "\n", + "Stay tuned for that!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/samples/notebooks/python/07-hugging-face-for-skills.ipynb b/samples/notebooks/python/07-hugging-face-for-skills.ipynb index 9b7fbc5d7a..50223b8a10 100644 --- a/samples/notebooks/python/07-hugging-face-for-skills.ipynb +++ b/samples/notebooks/python/07-hugging-face-for-skills.ipynb @@ -1,183 +1,179 @@ { - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "id": "68e1c158", - "metadata": {}, - "source": [ - "# Using Hugging Face With Skills\n", - "\n", - "In this notebook, we demonstrate using Hugging Face models for Skills using both SemanticMemory and text completions. \n", - "\n", - "SK supports downloading models from the Hugging Face that can perform the following tasks: text-generation, text2text-generation, summarization, and sentence-similarity. You can search for models by task at https://huggingface.co/models." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a77bdf89", - "metadata": {}, - "outputs": [], - "source": [ - "!python -m pip install -r requirements.txt\n", - "\n", - "# Note that additional dependencies are required for the Hugging Face connectors:\n", - "!python -m pip install torch==2.0.0\n", - "!python -m pip install transformers==4.28.1\n", - "!python -m pip install sentence-transformers==2.2.2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "508ad44f", - "metadata": {}, - "outputs": [], - "source": [ - "import semantic_kernel as sk\n", - "import semantic_kernel.connectors.ai.hugging_face as sk_hf" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "d8ddffc1", - "metadata": {}, - "source": [ - "First, we will create a kernel and add both text completion and embedding services. \n", - "\n", - "For text completion, we are chosing gp2. This is a text-generation model. (Note: text-generation will repeat the input in the output, text2text-generation will not.)\n", - "For embeddings, we are using sentence-transformers/all-MiniLM-L6-v2. Vectors generated for this model are of length 384 (compared to a length of 1536 from OpenAI ADA).\n", - "\n", - "The following step may take a few minutes when run for the first time as the models will be downloaded to your local machine." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f8dcbc6", - "metadata": {}, - "outputs": [], - "source": [ - "kernel = sk.Kernel()\n", - "\n", - "# Configure LLM service\n", - "kernel.config.add_text_completion_service(\n", - " \"gpt2\", sk_hf.HuggingFaceTextCompletion(\"gpt2\", task=\"text-generation\")\n", - ")\n", - "kernel.config.add_text_embedding_generation_service(\n", - " \"sentence-transformers/all-MiniLM-L6-v2\",\n", - " sk_hf.HuggingFaceTextEmbedding(\"sentence-transformers/all-MiniLM-L6-v2\"),\n", - ")\n", - "kernel.register_memory_store(memory_store=sk.memory.VolatileMemoryStore())\n", - "kernel.import_skill(sk.core_skills.TextMemorySkill())" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "2a7e7ca4", - "metadata": {}, - "source": [ - "### Add Memories and Define a skill to use them\n", - "\n", - "Most models available on huggingface.co are not as powerful as OpenAI GPT-3+. Your skills will likely need to be simpler to accomodate this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d096504c", - "metadata": {}, - "outputs": [], - "source": [ - "await kernel.memory.save_information_async(\n", - " \"animal-facts\", id=\"info1\", text=\"Sharks are fish.\"\n", - ")\n", - "await kernel.memory.save_information_async(\n", - " \"animal-facts\", id=\"info2\", text=\"Whales are mammals.\"\n", - ")\n", - "await kernel.memory.save_information_async(\n", - " \"animal-facts\", id=\"info3\", text=\"Penguins are birds.\"\n", - ")\n", - "await kernel.memory.save_information_async(\n", - " \"animal-facts\", id=\"info4\", text=\"Dolphins are mammals.\"\n", - ")\n", - "await kernel.memory.save_information_async(\n", - " \"animal-facts\", id=\"info5\", text=\"Flies are insects.\"\n", - ")\n", - "\n", - "# Define semantic function using SK prompt template language\n", - "my_prompt = \"\"\"I know these animal facts: {{recall $query1}} {{recall $query2}} {{recall $query3}} and \"\"\"\n", - "\n", - "# Create the semantic function\n", - "my_function = kernel.create_semantic_function(\n", - " my_prompt, max_tokens=45, temperature=0.5, top_p=0.5\n", - ")\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "2caf8575", - "metadata": {}, - "source": [ - "Let's now see what the completion looks like! Remember, \"gpt2\" is nowhere near as large as ChatGPT, so expect a much simpler answer." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "628c843e", - "metadata": {}, - "outputs": [], - "source": [ - "context = kernel.create_new_context()\n", - "context[sk.core_skills.TextMemorySkill.COLLECTION_PARAM] = \"animal-facts\"\n", - "context[sk.core_skills.TextMemorySkill.RELEVANCE_PARAM] = 0.3\n", - "\n", - "context[\"query1\"] = \"animal that swims\"\n", - "context[\"query2\"] = \"animal that flies\"\n", - "context[\"query3\"] = \"penguins are?\"\n", - "output = await kernel.run_async(my_function, input_vars=context.variables)\n", - "\n", - "output = str(output).strip()\n", - "\n", - "\n", - "query_result1 = await kernel.memory.search_async(\n", - " \"animal-facts\", context[\"query1\"], limit=1, min_relevance_score=0.3\n", - ")\n", - "query_result2 = await kernel.memory.search_async(\n", - " \"animal-facts\", context[\"query2\"], limit=1, min_relevance_score=0.3\n", - ")\n", - "query_result3 = await kernel.memory.search_async(\n", - " \"animal-facts\", context[\"query3\"], limit=1, min_relevance_score=0.3\n", - ")\n", - "\n", - "print(f\"gpt2 completed prompt with: '{output}'\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.10" - } + "cells": [ + { + "cell_type": "markdown", + "id": "68e1c158", + "metadata": {}, + "source": [ + "# Using Hugging Face With Skills\n", + "\n", + "In this notebook, we demonstrate using Hugging Face models for Skills using both SemanticMemory and text completions. \n", + "\n", + "SK supports downloading models from the Hugging Face that can perform the following tasks: text-generation, text2text-generation, summarization, and sentence-similarity. You can search for models by task at https://huggingface.co/models." + ] }, - "nbformat": 4, - "nbformat_minor": 5 + { + "cell_type": "code", + "execution_count": null, + "id": "a77bdf89", + "metadata": {}, + "outputs": [], + "source": [ + "!python -m pip install semantic-kernel==0.2.7.dev0\n", + "\n", + "# Note that additional dependencies are required for the Hugging Face connectors:\n", + "!python -m pip install torch==2.0.0\n", + "!python -m pip install transformers==4.28.1\n", + "!python -m pip install sentence-transformers==2.2.2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "508ad44f", + "metadata": {}, + "outputs": [], + "source": [ + "import semantic_kernel as sk\n", + "import semantic_kernel.connectors.ai.hugging_face as sk_hf" + ] + }, + { + "cell_type": "markdown", + "id": "d8ddffc1", + "metadata": {}, + "source": [ + "First, we will create a kernel and add both text completion and embedding services. \n", + "\n", + "For text completion, we are chosing gp2. This is a text-generation model. (Note: text-generation will repeat the input in the output, text2text-generation will not.)\n", + "For embeddings, we are using sentence-transformers/all-MiniLM-L6-v2. Vectors generated for this model are of length 384 (compared to a length of 1536 from OpenAI ADA).\n", + "\n", + "The following step may take a few minutes when run for the first time as the models will be downloaded to your local machine." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f8dcbc6", + "metadata": {}, + "outputs": [], + "source": [ + "kernel = sk.Kernel()\n", + "\n", + "# Configure LLM service\n", + "kernel.add_text_completion_service(\n", + " \"gpt2\", sk_hf.HuggingFaceTextCompletion(\"gpt2\", task=\"text-generation\")\n", + ")\n", + "kernel.add_text_embedding_generation_service(\n", + " \"sentence-transformers/all-MiniLM-L6-v2\",\n", + " sk_hf.HuggingFaceTextEmbedding(\"sentence-transformers/all-MiniLM-L6-v2\"),\n", + ")\n", + "kernel.register_memory_store(memory_store=sk.memory.VolatileMemoryStore())\n", + "kernel.import_skill(sk.core_skills.TextMemorySkill())" + ] + }, + { + "cell_type": "markdown", + "id": "2a7e7ca4", + "metadata": {}, + "source": [ + "### Add Memories and Define a skill to use them\n", + "\n", + "Most models available on huggingface.co are not as powerful as OpenAI GPT-3+. Your skills will likely need to be simpler to accomodate this." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d096504c", + "metadata": {}, + "outputs": [], + "source": [ + "await kernel.memory.save_information_async(\n", + " \"animal-facts\", id=\"info1\", text=\"Sharks are fish.\"\n", + ")\n", + "await kernel.memory.save_information_async(\n", + " \"animal-facts\", id=\"info2\", text=\"Whales are mammals.\"\n", + ")\n", + "await kernel.memory.save_information_async(\n", + " \"animal-facts\", id=\"info3\", text=\"Penguins are birds.\"\n", + ")\n", + "await kernel.memory.save_information_async(\n", + " \"animal-facts\", id=\"info4\", text=\"Dolphins are mammals.\"\n", + ")\n", + "await kernel.memory.save_information_async(\n", + " \"animal-facts\", id=\"info5\", text=\"Flies are insects.\"\n", + ")\n", + "\n", + "# Define semantic function using SK prompt template language\n", + "my_prompt = \"\"\"I know these animal facts: {{recall $query1}} {{recall $query2}} {{recall $query3}} and \"\"\"\n", + "\n", + "# Create the semantic function\n", + "my_function = kernel.create_semantic_function(\n", + " my_prompt, max_tokens=45, temperature=0.5, top_p=0.5\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "2caf8575", + "metadata": {}, + "source": [ + "Let's now see what the completion looks like! Remember, \"gpt2\" is nowhere near as large as ChatGPT, so expect a much simpler answer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "628c843e", + "metadata": {}, + "outputs": [], + "source": [ + "context = kernel.create_new_context()\n", + "context[sk.core_skills.TextMemorySkill.COLLECTION_PARAM] = \"animal-facts\"\n", + "context[sk.core_skills.TextMemorySkill.RELEVANCE_PARAM] = 0.3\n", + "\n", + "context[\"query1\"] = \"animal that swims\"\n", + "context[\"query2\"] = \"animal that flies\"\n", + "context[\"query3\"] = \"penguins are?\"\n", + "output = await kernel.run_async(my_function, input_vars=context.variables)\n", + "\n", + "output = str(output).strip()\n", + "\n", + "\n", + "query_result1 = await kernel.memory.search_async(\n", + " \"animal-facts\", context[\"query1\"], limit=1, min_relevance_score=0.3\n", + ")\n", + "query_result2 = await kernel.memory.search_async(\n", + " \"animal-facts\", context[\"query2\"], limit=1, min_relevance_score=0.3\n", + ")\n", + "query_result3 = await kernel.memory.search_async(\n", + " \"animal-facts\", context[\"query3\"], limit=1, min_relevance_score=0.3\n", + ")\n", + "\n", + "print(f\"gpt2 completed prompt with: '{output}'\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/samples/notebooks/python/requirements.txt b/samples/notebooks/python/requirements.txt deleted file mode 100644 index a79770b088..0000000000 --- a/samples/notebooks/python/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -semantic-kernel==0.2.6.dev0