Semantic Kernel
Semantic Kernel
Semantic Kernel is an open-source SDK that lets you easily combine AI services like
OpenAI , Azure OpenAI , and Hugging Face with conventional programming
languages like C# and Python. By doing so, you can create AI apps that combine the
best of both worlds.
During Kevin Scott's talk The era of the AI Copilot, he showed how Microsoft powers its
Copilot system with a stack of AI models and plugins. At the center of this stack is an AI
orchestration layer that allows us to combine AI models and plugins together to create
brand new experiences for users.
To help developers build their own Copilot experiences on top of AI plugins, we have
released Semantic Kernel, a lightweight open-source SDK that allows you to orchestrate
AI plugins. With Semantic Kernel, you can leverage the same AI orchestration patterns
that power Microsoft 365 Copilot and Bing in your own apps, while still leveraging your
existing development skills and investments.
Tip
If you are interested in seeing a sample of the copilot stack in action (with Semantic
Kernel at the center of it), check out Project Miyagi . Project Miyagi reimagines
the design, development, and deployment of intelligent applications on top of
Azure with all of the latest AI services and tools.
Additionally, Semantic Kernel makes it easy to add skills to your applications with AI
plugins that allow you to interact with the real world. These plugins are composed of
prompts and native functions that can respond to triggers and perform actions. In this
way, plugins are like the "body" of your AI app.
Because of the extensibility Semantic Kernel provides with connectors and plugins, you
can use it to orchestrate AI plugins from both OpenAI and Microsoft on top of nearly
any model. For example, you can use Semantic Kernel to orchestrate plugins built for
ChatGPT, Bing, and Microsoft 365 Copilot on top of models from OpenAI, Azure, or even
Hugging Face.
As a developer, you can use these pieces individually or together. For example, if you
just need an abstraction over OpenAI and Azure OpenAI services, you could use the SDK
to just run pre-configured prompts within your plugins, but the real power of Semantic
Kernel comes from combining these components together.
For example, with Semantic Kernel, you could create a pipeline that helps a user send an
email to their marketing team. With memory, you could retrieve information about the
project and then use planner to autogenerate the remaining steps using available
plugins (e.g., ground the user's ask with Microsoft Graph data, generate a response with
GPT-4, and send the email). Finally, you can display a success message back to your user
in your app using a custom plugin.
1 Ask It starts with a goal being sent to Semantic Kernel by either a user or
developer.
2 Kernel The kernel orchestrates a user's ask. To do so, the kernel runs a pipeline /
chain that is defined by a developer. While the chain is run, a common
context is provided by the kernel so data can be shared between functions.
2.1 Memories With a specialized plugin, a developer can recall and store context in vector
databases. This allows developers to simulate memory within their AI apps.
Step Component Description
2.2 Planner Developers can ask Semantic Kernel to auto create chains to address novel
needs for a user. Planner achieves this by mixing-and-matching plugins
that have already been loaded into the kernel to create additional steps.
This is similar to how ChatGPT, Bing, and Microsoft 365 Copilot combines
plugins together in their experiences.
2.3 Connectors To get additional data or to perform autonomous actions, you can use out-
of-the-box plugins like the Microsoft Graph Connector kit or create a
custom connector to provide data to your own services.
2.4 Custom As a developer, you can create custom plugins that run inside of Semantic
plugins Kernel. These plugins can consist of either LLM prompts (semantic
functions) or native C# or Python code (native function). This allows you to
add new AI capabilities and integrate your existing apps and services into
Semantic Kernel.
3 Response Once the kernel is done, you can send the response back to the user to let
them know the process is complete.
For new features, components, or extensions, please open an issue and discuss with us
before sending a PR. This will help avoid rejections since it will allow us to discuss the
impact to the larger ecosystem.
In just a few steps, you can start running the getting started guides for Semantic Kernel
in either C# or Python. After completing the guides, you'll know how to...
If you are an experienced developer, you can skip the guides and directly access the
packages from the Nuget feed or PyPI.
C#
Instructions for accessing the SemanticKernel Nuget feed is available here . It's as
easy as:
Nuget
Tip
Have your OpenAI or Azure OpenAI keys ready to enter when prompted by the
Jupyter notebook.
7 Note
If you are new to using GitHub and have never cloned a repo to your local
machine, please review this guide .
7 Note
If you are a new contributor to open source, please fork the repo to start
your journey.
If you have trouble cloning or forking the repo, you can watch the video below.
https://aka.ms/SK-Local-Setup
4. Choose either the dotnet or python folder based on your preferred programming
language.
6. Activate each code snippet with the "play" button on the left hand side.
If you need help running the 00-getting-started.ipynb notebook, you can watch the
video below.
https://aka.ms/SK-Getting-Started-Notebook
For beginners who are just starting to learn about AI Learn prompt engineering
For people who are well versed in prompt engineering Orchestrate AI plugins
For people familiar with using AI plugins Store and retrieve memory
For those who want to see how it all works together Run the sample apps
With these materials you can run your own Semantic Kernel Hackathon, a hands-on
event where you can learn and create AI solutions using Semantic Kernel tools and
resources.
By participating and running a Semantic Kernel hackathon, you will have the opportunity
to:
Explore the features and capabilities of Semantic Kernel and how it can help you
solve problems with AI
Work in teams to brainstorm and develop your own AI plugins or apps using
Semantic Kernel SDK and services
Present your results and get feedback from other participants
Have fun!
Once you have unzipped the file, you will find the following resources:
You should also familiarize yourself with the available documentation and tutorials. This
will ensure that you are knowledgeable of core Semantic Kernel concepts and features
so that you can help others during the hackathon. The following resources are highly
recommended:
Additionally, you can check out the available sample AI plugins and apps that
demonstrate how Semantic Kernel can be used for various scenarios. You can use them
as inspiration and even modify them for your own projects during the hackathon. You
can find them here:
Here is an approximate agenda and structure for each phase but feel free to modify this
based on your team:
60 Overview The facilitator will guide you through either a pre-recorded video or
a live presentation that will give you an overview of AI and why it is
important for solving problems in today's world. Along with an
overview of Semantic Kernel and its features, such the kernel,
planner, plugins, memories and more. You will also see demos of
how Semantic Kernel can be used for different scenarios.
120 Brainstorming The facilitator will help you form teams based on your interests or
skill levels. You will then brainstorm ideas for your own AI plugins or
apps using design thinking techniques.
360+ Development You will use Semantic Kernel SDKs tools, and resources to develop,
test, and deploy your projects. This could be for the rest of the day
or over multiple days based on the time available and problem to
be solved.
60 Presentation Each team will present their results using a PowerPoint template
provided. You will have about 15 minutes per team to showcase
your project, demonstrate how it works, and explain how it solves a
problem with AI. You will also receive feedback from other
participants.
30 Feedback Each team can share their feedback on the hackathon and Semantic
Kernel with the group and fill out the Hackathon Exit Survey .
If you want to continue developing your AI plugins or projects after the hackathon, you
can find more resources and support for Semantic Kernel.
Semantic Kernel Discord community
Semantic Kernel blog
Semantic Kernel GitHub repo
Thank you for your engagement and creativity during the hackathon. We look forward
to seeing what you create next with Semantic Kernel!
Additional learning for Semantic Kernel
Article • 07/11/2023
Want to learn more about Semantic Kernel? Check out these in-depth tutorials and
videos. We will add more content over time from our team and community, so check
back often!
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
" C#
" Python
" Java (coming soon )
While the overall architecture of the kernel is consistent across all languages, we made
sure the SDK for each language follows common paradigms and styles in each language
to make it feel native and easy to use.
Available features
Today, not all features are available in all languages. The following tables show which
features are available in each language. The *️symbol indicates that the feature is
partially implemented, please see the associated note column for more details. The ❌
symbol indicates that the feature is not yet available in that language; if you would like
to see a feature implemented in a language, please consider contributing to the project
or opening an issue.
AI Services
AI service endpoints
OpenAI ✅ ✅ ✅
AzureOpenAI ✅ ✅ ✅
Tokenizers
GPT2 ✅ ✅ ✅
GPT3 ✅ ❌ ❌
Core plugins
TextMemorySkill ✅ ✅ *️
ConversationSummarySkill ✅ ✅ ❌
FileIOSkill ✅ ✅ ❌
HttpSkill ✅ ✅ ❌
MathSkill ✅ ✅ ❌
TextSkill ✅ ✅ *️
Plugins C# Python Java Notes
TimeSkill ✅ ✅ *️
WaitSkill ✅ ❌ ❌
Planners
BasicPlanner ❌ ✅ ❌
ActionPlanner ✅ ❌ ❌
SequentialPlanner ✅ ❌ ❌
Connectors
Qdrant (Memory) ✅ ❌ ❌
ChromaDb (Memory) ❌ *️ ❌
Milvus (Memory) ❌ ❌ ❌
Pinecone (Memory) ✅ ❌ ❌
Weaviate (Memory) ❌ ❌ ❌
Azure Cognitive ✅ *️ ❌
Search
Plugins
OpenAPI ✅ ❌ ❌
Text chunkers *️ *️ ❌
To make the Kernel as lightweight as possible, the core pip package should have a
minimal set of external dependencies. On the other hand, the SDK should not reinvent
mature solutions already available, unless of major concerns.
Contributing to Semantic Kernel
Article • 06/21/2023
You can contribute to Semantic Kernel by submitting issues, starting discussions, and
submitting pull requests (PRs). Contributing code is greatly appreciated, but simply filing
issues for problems you encounter is also a great way to contribute since it helps us
focus our efforts.
Reporting issues
New issues for the SDK can be reported in our list of issues , but before you file a new
issue, please search the list of issues to make sure it does not already exist. If you have
issues with the Semantic Kernel documentation (this site), please file an issue in the
Semantic Kernel documentation repository .
If you do find an existing issue for what you wanted to report, please include your own
feedback in the discussion. We also highly recommend up-voting (👍 reaction) the
original post, as this helps us prioritize popular issues in our backlog.
Create issue
Submitting feedback
If you have general feedback on Semantic Kernel or ideas on how to make it better,
please share it on our discussions board . Before starting a new discussion, please
search the list of discussions to make sure it does not already exist.
We recommend using the ideas category if you have a specific idea you would like to
share and the Q&A category if you have a question about Semantic Kernel.
You can also start discussions (and share any feedback you've created) in the Discord
community by joining the Semantic Kernel Discord server .
Start a discussion
If you think others would benefit from a feature, we also encourage you to ask others to
up-vote the issue. This helps us prioritize issues that are impacting the most users. You
can ask colleagues, friends, or the community on Discord to up-vote an issue by
sharing the link to the issue or discussion.
2. Create a personal fork of the repository on GitHub (if you don't already have one).
3. In your fork, create a branch off of main ( git checkout -b mybranch ).
8. Wait for feedback or approval of your changes from the code maintainers.
9. When area owners have signed off, and all checks are green, your PR will be
merged.
Do's:
Do follow the standard .NET coding style and Python code style
Do give priority to the current style of the project or file you're changing if it
diverges from the general guidelines.
Do include tests when adding new features. When fixing bugs, start with adding a
test that highlights how the current behavior is broken.
Do keep the discussions focused. When a new or related topic comes up it's often
better to create new issue than to side track the discussion.
Do clearly state on an issue that you are going to take on implementing it.
Do blog and/or tweet about your contributions!
Don'ts:
Don't surprise the team with big pull requests. We want to support contributors, so
we recommend filing an issue and starting a discussion so we can agree on a
direction before you invest a large amount of time.
Don't commit code that you didn't write. If you find code that you think is a good
fit to add to Semantic Kernel, file an issue and start a discussion before
proceeding.
Don't submit PRs that alter licensing related files or headers. If you believe there's
a problem with them, file an issue and we'll be happy to discuss it.
Don't make new APIs without filing an issue and discussing with the team first.
Adding new public surface area to a library is a big deal and we want to make sure
we get it right.
Breaking Changes
Contributions must maintain API signature and behavioral compatibility. If you want to
make a change that will break existing code, please file an issue to discuss your idea or
change if you believe that a breaking change is warranted. Otherwise, contributions that
include breaking changes will be rejected.
If the CI build fails for any reason, the PR issue will be updated with a link that can be
used to determine the cause of the failure so that it can be addressed.
Contributing to documentation
We also accept contributions to the Semantic Kernel documentation repository . To
learn how to make contributions, please start with the Microsoft docs contributor guide.
Using the kernel to orchestrate AI
Article • 06/21/2023
The term "kernel" can have different meanings in different contexts, but in the case of
the Semantic Kernel, the kernel refers to an instance of the processing engine that fulfills
a user's request with a collection of plugins.
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
In this way, the kernel is very similar to the UNIX kernel and its pipes and filters
architecture; only now, instead of chaining together programs, we are chaining together
AI prompts and native functions.
Using the kernel
To start using the kernel, you must first create an instance of it.
C#
C#
using Microsoft.SemanticKernel;
Below is an example of how to instantiate the kernel with a custom logger in both C#
and Python.
Tip
To see these code samples in action, we recommend checking out the Loading the
kernel guide to explore different ways to load the kernel in a C# or Python
notebook.
C#
You can use the KernelBuilder class to create a kernel with custom configuration.
The following code snippet shows how to create a kernel with a logger.
C#
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
ILogger myLogger = NullLogger.Instance;
IKernel kernel_2 = Kernel.Builder
.WithLogger(myLogger)
.Build();
Additionally, you can create a kernel using a configuration object. This is useful if
you want to define a configuration elsewhere in your code and then inject it into
the kernel.
C#
The following code snippets show how to add a model to the kernel in C# and Python.
C#
C#
kernel.Config.AddAzureTextCompletionService(
"my-finetuned-Curie", // Azure OpenAI *Deployment
ID*
"https://contoso.openai.azure.com/", // Azure OpenAI *Endpoint*
"...your Azure OpenAI Key...", // Azure OpenAI *Key*
"Azure_curie" // alias used in the prompt
templates' config.json
);
kernel.Config.AddOpenAITextCompletionService(
"text-davinci-003", // OpenAI Model Name
"...your OpenAI API Key...", // OpenAI API key
"...your OpenAI Org ID...", // *optional* OpenAI
Organization ID
"OpenAI_davinci" // alias used in the prompt
templates' config.json
);
Tip
Many of the code samples below come from the quick start notebooks. To follow
along (and to learn more about how the code works), we recommend checking out
the Running prompts from files and Running semantic functions inline guides.
The following example leverages the sample FunSkill plugin that comes with the
Semantic Kernel repo.
C#
C#
var skillsDirectory =
Path.Combine(System.IO.Directory.GetCurrentDirectory(), "..", "..",
"skills");
var funSkillFunctions =
kernel.ImportSemanticSkillFromDirectory(skillsDirectory, "FunSkill");
var jokeFunction = funSkillFunctions["Joke"];
Alternatively, you can register a semantic function inline. To do so, you'll start by
defining the semantic prompt and its configuration. The following samples show how
you could have registered the same Joke function from the FunSkill plugin inline.
C#
C#
string skPrompt = @"WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE
TOPIC BELOW
{{$input}}
+++++
";
C#
C#
C#
C#
Console.WriteLine(result);
After running the above code examples, you should receive an output like the following.
Output
A time traveler went back to the dinosaur age and was amazed by the size of
the creatures. He asked one of the dinosaurs, "How do you manage to get
around with such short legs?"
C#
C#
""";
C#
Console.WriteLine(myOutput);
Output
2. Gasp and Groan Mocha - A rich and indulgent mocha that will make you gasp
and groan with delight.
Learn what plugins are and what they can do Understand AI plugins
Create more advanced pipelines with Semantic Kernel Chaining functions together
Your goal Next step
Automatically creating pipelines with Planner Auto create plans with planner
Understanding plugins
Using AI plugins in Semantic Kernel
Article • 06/21/2023
With plugins, you can encapsulate AI capabilities into a single unit of functionality.
Plugins are the building blocks of the Semantic Kernel and can interoperate with plugins
in ChatGPT, Bing, and Microsoft 365.
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
What is a plugin?
To drive alignment across the industry, we're in progress of adopting the OpenAI plugin
specification as the standard for plugins. This will help create an ecosystem of
interoperable plugins that can be used across all of the major AI apps and services like
ChatGPT, Bing, and Microsoft 365.
For developers using Semantic Kernel, this means any plugins you build will soon be
usable in ChatGPT, Bing, and Microsoft 365, allowing you to increase the reach of your
AI capabilities without rewriting your code. It also means that plugins built for ChatGPT,
Bing, and Microsoft 365 will be able to integrate with Semantic Kernel.
To see our status on adopting the OpenAI plugin specification, see our roadmap at the
bottom of the page. Each of the integration points have accompanying issues on GitHub
that you can follow to stay up-to-date on our progress. We are also open to feedback
on our unification plan, so feel free to leave a comment on the GitHub issues so that we
can best support your needs.
Just providing functions, however, is not enough to make a plugin. To power automatic
orchestration with a planner, plugins also need to provide details that semantically
describe how they behave. Everything from the function's input, output, and side effects
need to be described in a way that the AI can understand, otherwise, planner will
provide unexpected results.
For example, in the WriterSkill plugin, each function has a semantic description that
describes what the function does. Planner can then use this description to choose the
best function to call based on a user's ask.
In the picture on the right, planner would likely use the ShortPoem and StoryGen
functions to satisfy the users ask thanks to the provided semantic descriptions.
Adding functions to plugins
Now that you know what a plugin is, let's take a look at how to create one. Within a
plugin, you can create two types of functions: semantic functions and native functions.
The following sections describe how to create each type. For further details, please refer
to the Creating semantic functions and Creating native functions articles.
Semantic functions
If plugins represent the "body" of your AI app, then semantic functions would represent
the ears and mouth of your AI. They allow your AI app to listen to users asks and
respond back with a natural language response.
To connect the ears and the mouth to the "brain," Semantic Kernel uses connectors. This
allows you to easily swap out the AI services without rewriting code.
Below is an sample called Summarize that can be found in the samples folder in the
GitHub repository.
Prompt
[SUMMARIZATION RULES]
DONT WASTE WORDS
USE SHORT, CLEAR, COMPLETE SENTENCES.
DO NOT USE BULLET POINTS OR DASHES.
USE ACTIVE VOICE.
MAXIMIZE DETAIL, MEANING
FOCUS ON THE CONTENT
[BANNED PHRASES]
This article
This document
This page
This material
[END LIST]
Summarize:
Hello how are you?
+++++
Hello
Summarize this
{{$input}}
+++++
To semantically describe this function (as well as define the configuration for the AI
service), you must also create a config.json file in the same folder as the prompt. This file
describes the function's input parameters and description. Below is the config.json file
for the Summarize function.
JSON
{
"schema": 1,
"type": "completion",
"description": "Summarize given text or any text document",
"completion": {
"max_tokens": 512,
"temperature": 0.0,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"input": {
"parameters": [
{
"name": "input",
"description": "Text to summarize",
"defaultValue": ""
}
]
}
}
Both description fields are used by planner, so it's important to provide a detailed, yet
concise, description so planner can make the best decision when orchestrating functions
together. We recommend testing multiple descriptions to see which one works best for
the widest range of scenarios.
You can learn more about creating semantic functions in the Creating semantic
functions article. In this article you'll learn the best practices for the following:
Native functions
With native functions, you can have the kernel call C# or Python code directly so that
you can manipulate data or perform other operations. In this way, native functions are
like the hands of your AI app. They can be used to save data, retrieve data, and perform
any other operation that you can do in code that is ill-suited for LLMs (e.g., performing
calculations).
C#
The following code is an excerpt from the DocumentSkill plugin, which can be
found in the document plugin folder in the GitHub repository. It demonstrates
how you can use the SKFunction and SKFunctionInput attributes to describe the
function's input and output to planner.
C#
You can learn more about creating native functions in the Creating native functions
article. In this article you'll learn the best practices for the following:
To support this effort, the Semantic Kernel team is in the progress of updating what was
previously known as "skills" into plugins. After this unification process, we will allow
developers to bring outside AI plugins into Semantic Kernel and deploy Semantic Kernel
plugins so they can be consumed by other apps and services.
The following tables describe the teams progress towards plugin unification. The 🔁
symbol means the feature is currently being planned for.
Use OpenAPI With the OpenAPI plugin, you can take an OpenAPI file from Blog ✅
files in a ChatGPT plugin and bring it into Semantic Kernel post
Semantic
Kernel
Import a ai- This will make it even easier to bring in a ChatGPT plugin. By Coming 🔁
plugin.json providing an ai-plugin.json file, we can pull in the relevant soon
manifest in OpenAPI file and also provide the plugin description planner
Semantic for more effective plan generation.
Kernel
Deploy Today, you can deploy your existing semantic and Documentation ✅
Semantic native functions to Azure. Once they've been
Kernel plugins deployed, you can manually craft the necessary
for ChatGPT OpenAPI specification and ai-plugin.json file so that
your functions can be used by ChatGPT.
Feature Description Link Status
In this article, we'll demonstrate how to actually create a semantic function so you can
easily import them into Semantic Kernel. As an example in this article, we will
demonstrate how to create a semantic function that gathers the intent of the user. This
semantic function will be called GetIntent and will be part of a plugin called
OrchestratorPlugin .
By following this example, you'll learn how to create a semantic function that can use
multiple context variables and functions to elicit an AI response. If you want to see the
final solution, you can check out the following samples in the public documentation
repository.
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
Tip
We recommend using the Semantic Kernel Tools extension for Visual Studio Code
to help you create semantic functions. This extension provides an easy way to
create and test functions directly from within VS Code.
Creating a home for your semantic functions
Before creating the OrchestratorPlugin or the GetIntent function, you must first define
a folder that will hold all of your plugins. This will make it easier to import them into
Semantic Kernel later. We recommend putting this folder at the root of your project and
calling it plugins.
Within your plugins folder, you can then create a folder called OrchestratorPlugin for
your plugin and a nested folder called GetIntent for your function.
directory
Plugins
│
└─── OrchestratorPlugin
|
└─── GetIntent
To see a more complete example of a plugins directory, check out the Semantic Kernel
sample plugins folder in the GitHub repository.
Go ahead and create these two files in the GetIntent folder. In the following sections,
we'll walk through how to configure them.
directory
Plugins
│
└─── OrchestratorPlugin
|
└─── GetIntent
|
└─── config.json
└─── skprompt.txt
In most cases, you'll send your prompt to a text or chat completion service which will
return back a response that attempts to complete the prompt. For example, if you send
the prompt I want to go to the , the AI service might return back beach . This is a very
simple example, but it demonstrates the basic idea of how prompts work.
In the case of the GetIntent function, we want to create a prompt that asks the AI
service what the intent of a user is. The following prompt will do just that:
txt
---------------------------------------------
Notice that we're using a variable called $input in the prompt. This variable is later
defined in the config.json file and is used to pass the user's input to the AI service.
Go ahead and copy the prompt above and save it in the skprompt.txt file.
type – The type of prompt. In this case, we're using the completion type.
description – A description of what the prompt does. This is used by planner to
JSON
{
"schema": 1,
"type": "completion",
"description": "Gets the intent of the user.",
"completion": {
"max_tokens": 500,
"temperature": 0.0,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"input": {
"parameters": [
{
"name": "input",
"description": "The user's request.",
"defaultValue": ""
}
]
}
}
C#
C#
var pluginsDirectory =
Path.Combine(System.IO.Directory.GetCurrentDirectory(), "path", "to",
"your", "plugins", "folder");
// Import the OrchestratorPlugin from the plugins directory.
var orchestratorPlugin = kernel
.ImportSemanticSkillFromDirectory(pluginsDirectory,
"OrchestratorPlugin");
Console.WriteLine(result);
Output
We need to find a way to constrain the output of our function so that we can use the
output in a switch statement.
The prompt template syntax article in the prompt engineering section of the
documentation provides a detailed overview of how to use the templating language. In
this article, we'll show you just enough to get started.
The following prompt uses the {{$options}} variable to provide a list of options for the
LLM to choose from. We've also added a {{$history}} variable to the prompt so that
the previous conversation is included.
By including these variables, we are able to help the LLM choose the correct intent by
allowing it to leverage variables within the Semantic Kernel context object.
txt
{{$history}}
User: {{$input}}
---------------------------------------------
Provide the intent of the user. The intent should be one of the following:
{{$options}}
INTENT:
When you add a new variable to the prompt, you also should update the config.json file
to include the new variable. While these properties aren't used now, it's good to get into
the practice of adding them so that they can be used by the planner later. The following
configuration adds the $options and $history variable to the input section of the
configuration.
JSON
{
"schema": 1,
"type": "completion",
"description": "Gets the intent of the user.",
"completion": {
"max_tokens": 500,
"temperature": 0.0,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"input": {
"parameters": [
{
"name": "input",
"description": "The user's request.",
"defaultValue": ""
},
{
"name": "history",
"description": "The history of the conversation.",
"defaultValue": ""
},
{
"name": "options",
"description": "The options to choose from.",
"defaultValue": ""
}
]
}
}
You can now update your code to provide a list of options to the GetIntent function by
using context.
C#
C#
// Create a new context and set the input, history, and options
variables.
var context = kernel.CreateNewContext();
context["input"] = "Yes";
context["history"] = @"Bot: How can I help you?
User: My team just hit a major milestone and I would like to send them a
message to congratulate them.
Bot:Would you like to send an email?";
context["options"] = "SendEmail, ReadEmail, SendMeeting, RsvpToMeeting,
SendChat";
Now, instead of getting an output like Send congratulatory email. , we'll get an output
like SendEmail . This output could then be used within a switch statement in native code
to run the correct function.
To learn more about calling functions within a semantic function, see the calling
functions within a semantic function section in the prompt engineering section of the
documentation.
The following prompt uses the Summarize function in the SummarizeSkill plugin to
summarize the conversation history before asking for the intent.
txt
{{SummarizeSkill.Summarize $history}}
User: {{$input}}
---------------------------------------------
Provide the intent of the user. The intent should be one of the following:
{{$options}}
INTENT:
You can now update your code to load the SummarizeSkill plugin so the kernel can find
the Summarize function.
C#
C#
var pluginsDirectory =
Path.Combine(System.IO.Directory.GetCurrentDirectory(), "path", "to",
"your", "plugins", "folder");
// Import the OrchestratorPlugin and SummarizeSkill from the plugins
directory.
var orchestrationPlugin =
kernel.ImportSemanticSkillFromDirectory(pluginsDirectory,
"OrchestratorPlugin");
var summarizationPlugin =
kernel.ImportSemanticSkillFromDirectory(pluginsDirectory,
"SummarizeSkill");
// Create a new context and set the input, history, and options
variables.
var context = kernel.CreateNewContext();
context["input"] = "Yes";
context["history"] = @"Bot: How can I help you?
User: My team just hit a major milestone and I would like to send them a
message to congratulate them.
Bot:Would you like to send an email?";
context["options"] = "SendEmail, ReadEmail, SendMeeting, RsvpToMeeting,
SendChat";
Console.WriteLine(result);
In the how to create semantic functions article, we showed how you could create a
semantic function that retrieves a user's intent, but what do you do once you have the
intent? In this article we'll show how to create native functions that can route the intent
and perform a task.
By the end of this article, you'll have a kernel that can correctly answer user questions
like What is the square root of 634? and What is 42 plus 1513? . If you want to see
the final solution, you can check out the following samples in the public documentation
repository.
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
directory
MyPluginsDirectory
│
└─── MySemanticPlugin
| │
| └─── MyFirstSemanticFunction
| │ └─── skprompt.txt
| │ └─── config.json
| └─── MyOtherSemanticFunctions
| | ...
│
└─── MyCSharpPlugin.cs
In our example, we'll create two files one for the native OrchestratorPlugin functions
and another for the MathPlugin . Depending on the language you're using, you'll create
either C# or Python files for each.
C#
directory
Plugins
│
└─── OrchestratorPlugin
| │
| └─── GetIntent
| └─── skprompt.txt
| └─── config.json
|
└─── OrchestratorPlugin.cs
└─── MathPlugin.cs
It's ok if you have a semantic plugin folder and a native plugin file with the same name.
The kernel will load both functions into the same plugin namespace. What's important is
that you don't have two functions with the same name within the same plugin
namespace. If you do, the last function loaded will overwrite the previous function.
We'll begin by creating the MathPlugin functions. Afterwards, we'll call the MathPlugin
functions from within the OrchestratorPlugin . At the end of this example you will have
the following supported functions.
C#
C#
using Microsoft.SemanticKernel.SkillDefinition;
using Microsoft.SemanticKernel.Orchestration;
namespace Plugins;
Notice that the input and and return types are strings. This is because the kernel will
pass the input as a string and expect a string to be returned. You can convert the input
to any type you want within the function.
Also notice how we've added a description to each function with attributes. This
description will be used by the planner to automatically create a plan using these
functions. In our case, we're telling planner that this function Takes the square root of
a number .
Using context parameters to take multiple inputs
Adding numbers together requires multiple numbers as input. Since we cannot pass
multiple numbers into a native function, we'll need to use context parameters instead.
Add the following code to your MathPlugin class to create a function that adds two
numbers together.
C#
C#
Notice that instead of taking a string as input, this function takes an SKContext object as
input. This object contains all of the variables in the Semantic Kernel's context. We can
use this object to retrieve the two numbers we want to add. Also notice how we provide
descriptions for each of the context parameters. These descriptions will be used by the
planner to automatically provide inputs to this function.
The SKContext object only supports strings, so we'll need to convert the strings to
doubles before we add them together.
C#
C#
using Microsoft.SemanticKernel;
using Plugins;
The code should output 8 since it's the square root of 64 and 10 since it's the sum of 3
and 7 .
C#
C#
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.SkillDefinition;
using Newtonsoft.Json.Linq;
namespace Plugins;
From the code above, we can see that the OrchestratorPlugin function does the
following:
1. Saves the kernel to a private variable during initialization so it can be used later to
call the GetIntent function.
2. Sets the list of available functions to the context so it can be passed to the
GetIntent function.
3. Uses a switch statement to call the appropriate function based on the user's
intent.
Unfortunately, we have a challenge. Despite knowing the user's intent, we don't know
which numbers to pass to the MathPlugin functions. We'll need to add another semantic
function to the OrchestratorPlugin to extract the necessary numbers from the user's
input.
Using semantic functions to extract data for native
functions
To pull the numbers from the user's input, we'll create a semantic function called
GetNumbers . Create a new folder under the OrchestratorPlugin folder named
GetNumbers. Then create a skprompt.txt and config.json file within the folder. Add the
following code to the skprompt.txt file.
txt
Extract the numbers from the input and output them in JSON format.
-------------------
INPUT: I have a 2x4 that is 3 feet long. Can you cut it in half?
OUTPUT: {"number1":3, "number2":2}
INPUT: {{$input}}
OUTPUT:
JSON
{
"schema": 1,
"type": "completion",
"description": "Gets the numbers from a user's request.",
"completion": {
"max_tokens": 500,
"temperature": 0.0,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"input": {
"parameters": [
{
"name": "input",
"description": "The user's request.",
"defaultValue": ""
}
]
}
}
C#
C#
return sqrtResults["input"];
case "Add":
// Call the Add function with both numbers
var Add = _kernel.Skills.GetFunction("MathPlugin", "Add");
context["input"] = numbers["number1"]!.ToString();
context["number2"] = numbers["number2"]!.ToString();
SKContext addResults = await Add.InvokeAsync(context);
return addResults["input"];
default:
return "I'm sorry, I don't understand.";
}
Finally, you can invoke the OrchestratorPlugin function from your main file using the
code below.
C#
C#
using Microsoft.SemanticKernel;
using Plugins;
var pluginsDirectory =
Path.Combine(System.IO.Directory.GetCurrentDirectory(), "plugins");
Chaining functions
Chaining functions together
Article • 07/12/2023
In previous articles, we showed how you could invoke a Semantic Kernel function
(whether semantic or native) individually. Oftentimes, however, you may want to string
multiple functions together into a single pipeline to simplify your code.
Later in this article, we'll put this knowledge to use by demonstrating how you could
refactor the code from the native functions to make it more readable and maintainable.
If you want to see the final solution, you can check out the following samples in the
public documentation repository.
For example we can make three inline semantic functions and string their outputs into
the next by adding the $input variable into each prompt.
C#
Create and register the semantic functions.
C#
""";
Run the functions sequentially. Notice how all of the functions share the same
context.
C#
Console.WriteLine(context);
Output
2. Gasp and Groan Mocha - A rich and indulgent mocha that will make you gasp
and groan with delight.
C#
C#
Console.WriteLine(myOutput);
We'll demonstrate this by updating the code written in the native functions article to use
the RunAsync method instead.
C#
C#
[SKFunction("Extracts numbers from JSON")]
public SKContext ExtractNumbersFromJson(SKContext context)
{
JObject numbers = JObject.Parse(context["input"]);
C#
C#
return output["input"];
}
After making these changes, you should be able to run the code again and see the same
results as before. Only now, the RouteRequest is easier to read and you've created a new
native function that can be reused in other pipelines.
It's also useful in persisting the initial $input variable across all functions in the pipeline
without it being overwritten. For example, in our current pipeline, the user's original
request is overwritten by the output of the GetNumbers function. This makes it difficult to
retrieve the original request later in the pipeline to create a natural sounding response.
By storying the original request as another variable, we can retrieve it later in the
pipeline.
C#
C#
JSON
{
"schema": 1,
"type": "completion",
"description": "Creates a response based on the original request and
the output of the pipeline",
"completion": {
"max_tokens": 256,
"temperature": 0.0,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"input": {
"parameters": [
{
"name": "input",
"description": "The user's request.",
"defaultValue": ""
},
{
"name": "original_request",
"description": "The original request from the user.",
"defaultValue": ""
}
]
}
}
txt
User: {{$original_request}}
Bot:
You can now update the RouteRequest function to include the CreateResponse function
in the pipeline. Update the RouteRequest function to the following:
C#
C#
return output["input"];
}
C#
C#
using Microsoft.SemanticKernel;
using Plugins;
var pluginsDirectory =
Path.Combine(System.IO.Directory.GetCurrentDirectory(), "plugins");
You should get a response like the following. Notice how the response is now more
natural sounding.
Output
So far, we have manually orchestrated all of the functions on behalf of the user. This,
however, is not a scalable solution because it would require the app developer to
predict all possible requests that could be made by the user. So instead, we will learn
how to automatically orchestrate functions on the fly using planner. If you want to see
the final solution, you can check out the following samples in the public documentation
repository.
What is planner?
Planner is a function that takes a user's ask and returns back a plan on how to
accomplish the request. It does so by using AI to mix-and-match the plugins registered
in the kernel so that it can recombine them into a series of steps that complete a goal.
This is a powerful concept because it allows you to create atomic functions that can be
used in ways that you as a developer may not have thought of.
For example, if you had task and calendar event plugins, planner could combine them to
create workflows like "remind me to buy milk when I go to the store" or "remind me to
call my mom tomorrow" without you explicitly having to write code for those scenarios.
With great power comes great responsibility, however. Because planner can combine
functions in ways that you may not have thought of, it is important to make sure that
you only expose functions that you want to be used in this way. It's also important to
make sure that you apply responsible AI principles to your functions so that they are
used in a way that is fair, reliable, safe, private, and secure.
Planner is an extensible part of Semantic Kernel. This means we have several planners to
choose from and that you could create a custom planner if you had specific needs.
Below is a table of the out-of-the-box planners provided by Semantic Kernel and their
language support. The ❌ symbol indicates that the feature is not yet available in that
language; if you would like to see a feature implemented in a language, please consider
contributing to the project or opening an issue.
At the end of this section, we'll have built a natural language calculator that can answer
simple word problems for users.
C#
C#
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.SkillDefinition;
namespace Plugins;
Instantiating planner
To instantiate planner, all you need to do is pass it a kernel object. Planner will then
automatically discover all of the plugins registered in the kernel and use them to create
plans. The following code initializes both a kernel and a SequentialPlanner . At the end
of this article we'll review the other types of Planners that are available in Semantic
Kernel.
C#
C#
using Microsoft.SemanticKernel;
using Plugins;
// Create planner
var planner = new SequentialPlanner(kernel);
Creating and running a plan
Now that we have planner, we can use it to create a plan for a user's ask and then
invoke the plan to get a result. The following code asks our planner to solve a math
problem that is difficult for an LLM to solve on its own because it requires multiple steps
and it has numbers with decimal points.
C#
C#
Console.WriteLine("Plan results:");
Console.WriteLine(result.Result);
After running this code, you should get the correct answer of 2615.1829 back, but how?
txt
With these steps, planner is given a set of rules that it can use to generate a plan in
XML. Afterwards, the prompt provides a few examples of valid plans before finally
providing the $available_functions and user's goal.
txt
[AVAILABLE FUNCTIONS]
{{$available_functions}}
<goal>{{$input}}</goal>
txt
[AVAILABLE FUNCTIONS]
MathPlugin.Add:
description: Add two numbers
inputs:
- input: The first number to add
- number2: The second number to add
MathPlugin.Divide:
description: Divide two numbers
inputs:
- input: The first number to divide from
- number2: The second number to divide by
Because of this, it's incredibly important to provide the best descriptions you can for
your functions. If you don't, planner will not be able to generate a plan that uses your
functions correctly.
You can also use the descriptions to provide explicit instructions to the model on how to
use your functions. Below are some techniques you can use to improve the use of your
functions by planner.
Provide help text – It's not always clear when or how to use a function, so giving
advice helps. For example, the description for MathPlugin.Multiply reminds the
bot to add 1 whenever it increases a number by a percentage.
Describe the output. – While there is not an explicit way to tell planner what the
output of a function is, you can describe the output in the description.
State if inputs are required. – If a function requires an input, you can state that in
the input's description so the model knows to provide an input. Conversely, you
can tell the model that an input is optional so it knows it can skip it if necessary.
C#
C#
Console.WriteLine(plan);
Output
{
"state": [
{
"Key": "INPUT",
"Value": ""
}
],
"steps": [
{
"state": [
{
"Key": "INPUT",
"Value": ""
}
],
"steps": [],
"parameters": [
{
"Key": "number2",
"Value": "1.23"
},
{
"Key": "INPUT",
"Value": "2130.23"
}
],
"outputs": [
"INVESTMENT_INCREASE"
],
"next_step_index": 0,
"name": "Multiply",
"skill_name": "MathPlugin",
"description": "Multiply two numbers"
},
{
"state": [
{
"Key": "INPUT",
"Value": ""
}
],
"steps": [],
"parameters": [
{
"Key": "number2",
"Value": "5"
},
{
"Key": "INPUT",
"Value": "$INVESTMENT_INCREASE"
}
],
"outputs": [
"RESULT__FINAL_AMOUNT"
],
"next_step_index": 0,
"name": "Subtract",
"skill_name": "MathPlugin",
"description": "Subtract two numbers"
}
],
"parameters": [
{
"Key": "INPUT",
"Value": ""
}
],
"outputs": [
"RESULT__FINAL_AMOUNT"
],
"next_step_index": 0,
"name": "",
"skill_name": "Microsoft.SemanticKernel.Planning.Plan",
"description": "If my investment of 2130.23 dollars increased by 23%,
how much would I have after I spent $5 on a latte?"
}
Notice how in the example, planner can string together functions and pass parameters
to them. This effectively allows us to deprecate the OrchestratorPlugin we created
previously because we no longer need the RouteRequest native function or the
GetNumbers semantic function. Planner does both.
There are, however, considerations you should make before using a planner. The
following table describes the top considerations you should make along with
mitigations you can take to reduce their impact.
Performance It takes time for a planner to While building UI, it's important to
consume the full list of tokens and provide feedback to the user to let them
to generate a plan for a user, if you know something is happening with
rely on the planner after a user loading experiences. You can also use
provides input, you may LLMs to stall for time by generating an
unintentionally hang the UI while initial response for the user while the
waiting for a plan. planner completes a plan. Lastly, you
can use predefined plans for common
scenarios to avoid waiting for a new
plan.
Considerations Description Mitigation
Cost both the prompt and generated The more atomic your functions are, the
plan consume many tokens. To more tokens you'll require. By authoring
generate a very complex plan, you higher order functions, you can provide
may need to consume all of the planner with fewer functions that use
tokens provided by a model. This fewer tokens. Lastly, you can use
can result in high costs for your predefined plans for common scenarios
service if you're not careful, to avoid spending money on new plans.
especially since planning typically
requires more advanced models like
GPT 3.5 or GPT 4.
Correctness Planner can generate faulty plans. To make planner robust, you should
For example, it may pass variables provide error handling. Some errors, like
incorrectly, return malformed malformed schema or improperly
schema, or perform steps that don't returned schema, can be recovered by
make sense. asking planner to "fix" the plan.
This is similar to the front-end development adage coined by Aaron Swartz: "Bake, don't
fry." By pre-creating, or "baking," your plans, you can avoid generating them on the fly
(i.e., "frying"). You won't be able to get rid of "frying" entirely when creating AI apps, but
you can reduce your reliance on it so you can use healthier alternatives instead.
To achieve this, you can generate plans for common scenarios offline, and store them as
XML in your project. Based on the intent of the user, you can then serve the plan back
up so it can be executed. By "baking" your plans, you also have the opportunity to
create additional optimizations to improve speed or lower costs.
Use the out-of-the-box plugins in the
kernel
Article • 06/21/2023
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
Core plugins
The core plugins are planned to be available in all languages since they are core to
using Semantic Kernel. Below are the core plugins currently available in Semantic Kernel
along with their current support for each language. The ❌ symbol indicates that the
feature is not yet available in that language; if you would like to see a feature
implemented in a language, please consider contributing to the project or opening an
issue.
You can find the full list of core plugins for each language by following the links below:
C# core plugins
Python core plugins
C#
C#
using Microsoft.SemanticKernel.CoreSkills;
Answer to the following questions using JSON syntax, including the data
used.
Is it morning, afternoon, evening, or night
(morning/afternoon/evening/night)?
Is it weekend time (weekend/not weekend)?";
resulting-output
{
"date": "Wednesday, 21 June, 2023",
"time": "12:17:02 AM",
"period": "night",
"weekend": "not weekend"
}
C#
C#
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.CoreSkills;
Console.WriteLine(myOutput);
Note how the input streams through a pipeline of three functions executed serially.
Expressed sequentially as in a chain of functions:
Prompts play a crucial role in communicating and directing the behavior of Large
Language Models (LLMs) AI. They serve as inputs or queries that users can provide to
elicit specific responses from a model.
If you've already experimented with ChatGPT, you can see how the model's behavior
changes dramatically based on the inputs you provide. For example, the following
prompts produce very different outputs:
Prompt
Prompt
The first prompt produces a long report, while the second prompt produces a concise
response. If you were building a UI with limited space, the second prompt would be
more suitable for your needs. Further refined behavior can be achieved by adding even
more details to the prompt, but its possible to go too far and produce irrelevant
outputs. As a prompt engineer, you must find the right balance between specificity and
relevance.
When you work directly with LLM models, you can also use other controls to influence
the model's behavior. For example, you can use the temperature parameter to control
the randomness of the model's output. Other parameters like top-k, top-p, frequency
penalty, and presence penalty also influence the model's behavior.
Prompt engineering: a new career
Because of the amount of control that exists, prompt engineering is a critical skill for
anyone working with LLM AI models. It's also a skill that's in high demand as more
organizations adopt LLM AI models to automate tasks and improve productivity. A good
prompt engineer can help organizations get the most out of their LLM AI models by
designing prompts that produce the desired outputs.
Once you've become familiar with prompt engineering, you can also use Semantic
Kernel to apply your skills to real-world scenarios. By combining your prompts with
native functions and connectors, you can build powerful AI-powered applications.
Lastly, by deeply integrating with Visual Studio Code, Semantic Kernel also makes it easy
for you to integrate prompt engineering into your existing development processes.
Prompt engineering is a dynamic and evolving field, and skilled prompt engineers play a
crucial role in harnessing the capabilities of LLM AI models effectively.
To write an LLM AI prompt that Semantic Kernel is uniquely fit for, all you need is a
concrete goal in mind — something you would like an AI to get done for you. For
example:
I want to make a cake. Give me the best chocolate cake recipe you can think of.
Congratulations! You have imagined a delicious ask for Semantic Kernel to run to
completion. This ask can be given to the Planner to get decomposed into steps.
Although to make the Planner work reliably, you'll need to use the most advanced
model available to you. So let's start from writing basic prompts to begin with.
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
Tip
Want to easily follow along as you write your first prompts? Download the
Semantic Kernel VS Code Extension which allows you to easily create and run
prompts from within VS Code.
Plain-Prompt
Response-From-LLM-AI-Model
Let's try another example where we are eager to play with the summarizing capability of
LLM AIs and want to show off its superpower when applied to text that we explicitly
define:
Plain-Prompt
Response-From-LLM-AI-Model
Both of these simple prompts qualify as "functions" that can be packaged as part of an
Semantic Kernel plugin. The only problem is that they can do only one thing — as
defined by the prompt — and with no flexibility. We set up the first plain prompt in
Semantic Kernel within a directory named SloganMaker into a file named skprompt.txt :
SloganMaker/skprompt.txt
Similarly, we place the second plain prompt into a directory named SummarizeBlurb as a
file named into a file named skprompt.txt .
SummarizeBlurb/skprompt.txt
Each of these directories comprise a Semantic Kernel function. When both of the
directories are placed inside an enclosing directory called TestPlugin the result is a
brand new plugin.
Semantic-Plugins-And-Their-Functions
TestPlugin
│
└─── SloganMaker
| |
│ └─── skprompt.txt
│ └─── [config.json](../howto/configuringfunctions)
│
└─── SummarizeBlurb
|
└─── skprompt.txt
└─── [config.json](../howto/configuringfunctions)
This plugin can do one of two things by calling one of its two functions:
Next, we'll show you how to make a more powerful plugin by introducing Semantic
Kernel prompt templates. But before we do so, you may have noticed the config.json
file. That's a special file for customizing how you want the function to run so that its
performance can be tuned. If you're eager to know what's inside that file you can go
here but no worries — you'll be running in no time. So let's keep going!
SloganMakerFlex/skprompt.txt
Such "templated" prompts include variables and function calls that can dynamically
change the content and the behavior of an otherwise plain prompt. Prompt templates
can help you to generate more diverse, relevant, and effective prompts, and to reuse
and combine them for different tasks and domains.
In a templated prompt, the double {{ curly braces }} signify to Semantic Kernel that
there's something special for it to notice within the LLM AI prompt. To pass an input to a
prompt, we refer to the default input variable $INPUT — and by the same token if we
have other variables to work with, they will start with a dollar sign $ as well.
Our other plain prompt for summarizing text into two sentences can take an input by
simply replacing the existing body of text and replacing it with {{$INPUT}} as follows:
SummarizeBlurbFlex/skprompt.txt
Summarize the following text in two sentences or less.
---Begin Text---
{{$INPUT}}
---End Text---
File-Structure-For-Plugin-Definition-With-Functions
TestPluginFlex
│
└─── SloganMakerFlex
| |
│ └─── skprompt.txt
│ └─── config.json
│
└─── SummarizeBlurbFlex
|
└─── skprompt.txt
└─── config.json
Recall that the difference between our new "flex" plugins and our original "plain" plugins
is that we've gained the added flexibility of being able to pass a single parameter like:
Templated prompts can be further customized beyond a single $INPUT variable to take
on more inputs to gain even greater flexibility. For instance, if we wanted our
SloganMaker plugin to not only take into account the kind of business but also the
business' location and specialty, we would write the function as:
SloganMakerFlex/skprompt.txt
Note that although the use of $INPUT made sense as a generic input for a templated
prompt, you're likely to want to give it a name that makes immediate sense like
$BUSINESS — so let's change the function accordingly:
SloganMakerFlex/skprompt.txt
We can replace our TestPluginFlex plugin with this new definition for SloganMakerFlex
to serve the minimum capabilities of a copywriting agency.
C#
using Microsoft.SemanticKernel;
kernel.Config.AddAzureOpenAITextCompletion(
"Azure_davinci", // LLM AI model alias
"text-davinci-003", // Azure OpenAI *Deployment ID*
"https://contoso.openai.azure.com/", // Azure OpenAI *Endpoint*
"...your Azure OpenAI Key..." // Azure OpenAI *Key*
);
C#
using Microsoft.SemanticKernel;
kernel.Config.AddOpenAITextCompletion(
"OpenAI_davinci", // LLM AI model alias
"text-davinci-003", // OpenAI Model Name
"...your OpenAI API Key...", // OpenAI API key
"...your OpenAI Org ID..." // *optional* OpenAI
Organization ID
);
Your-App-And-Semantic-Plugins
MyAppSource
│
└───MyPluginsDirectory
│
└─── TestPluginFlex
│
└─── SloganMakerFlex
| |
│ └─── skprompt.txt
│ └─── config.json
│
└─── SummarizeBlurbFlex
|
└─── skprompt.txt
└─── config.json
1. Import your desired semantic function by specifying the root plugins directory and
the plugin's name
2. Get ready to pass your semantic function parameters with a ContextVariables
object
3. Set the corresponding context variables with <your context variables>.Set
4. Select the semantic function to run within the plugin by selecting a function
In code, and assuming you've already instantiated and configured your kernel as
myKernel as described above:
C#
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.KernelExtensions;
using Microsoft.SemanticKernel.Orchestration;
var myPlugin =
myKernel.ImportSemanticSkillFromDirectory("MyPluginsDirectory",
"TestPluginFlex");
Console.WriteLine(myResult);
take summarizeBlurbFlex :
summarizeBlurbFlex
and define the function inline in C# — assuming you've already instantiated and
configured your kernel as myKernel as described above:
C#
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.SemanticFunctions;
Console.WriteLine(myOutput);
Note that the configuration was given inline to the kernel with a PromptTemplateConfig
object instead of a config.json file with the maximum number of tokens to use
MaxTokens , the variability of words it will use as TopP , and the amount of randomness to
consider in its response with Temperature . Keep in mind that when using C# these
parameters will be PascalCased (each word is explicitly capitalized in a string) to be
consistent with C# conventions, but in the config.json the parameters are lowercase. To
learn more about these function parameters read how to configure functions.
A more succinct way to make this happen is with default settings across the board:
C#
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.KernelExtensions;
using Microsoft.SemanticKernel.Orchestration;
var mySummarizeFunction =
myKernel.CreateSemanticFunction(summarizeBlurbFlex, maxTokens: 1000);
Console.WriteLine(myOutput);
Tip
The article provides a brief overview of GPT models, including their variants, how
they work, and how they can be fine-tuned. It also mentions similar LLM AI models
and compares models based on their number of parameters.
A model refers to a specific instance or version of an LLM AI, such as GPT-3 or Codex,
that has been trained and fine-tuned on a large corpus of text or code (in the case of
the Codex model), and that can be accessed and used through an API or a platform.
OpenAI and Azure OpenAI offer a variety of models that can be customized and
controlled through parameters or options, and that can be applied and integrated to
various domains and tasks.
Ada is the smallest and simplest model, with 350 million parameters and 40GB of text
data. It can handle basic natural language understanding and generation tasks, such as
classification, sentiment analysis, summarization, and simple conversation.
Babbage is a larger model, with 3 billion parameters and 300GB of text data. It can
handle more complex natural language tasks, such as reasoning, logic, arithmetic, and
word analogy.
Curie is a very large model, with 13 billion parameters and 800GB of text data. It can
handle advanced natural language tasks, such as text-to-speech, speech-to-text,
translation, paraphrasing, and question answering.
Davinci is the largest and most powerful model, with 175 billion parameters and 45TB of
text data. It can handle almost any natural language task, as well as some multimodal
tasks, such as image captioning, style transfer, and visual reasoning. It can also generate
coherent and creative texts on any topic, with a high level of fluency, consistency, and
diversity.
text-davinci-003 175 billion Almost any NLU, NLG, and multimodal task
LLM AI models are generally compared by the number of parameters — where bigger is
usually better. The number of parameters is a measure of the size and the complexity of
the model. The more parameters a model has, the more data it can process, learn from,
and generate. However, having more parameters also means having more
computational and memory resources, and more potential for overfitting or underfitting
the data. Parameters are learned or updated during the training process, by using an
optimization algorithm that tries to minimize the error or the loss between the predicted
and the actual outputs. By adjusting the parameters, the model can improve its
performance and accuracy on the given task or domain.
When creating a prompt, there are many parameters that can be set to control how the
prompt behaves. In Semantic Kernel, these parameters both control how a function is
used by planner and how it is run by an LLM AI model.
Semantic Kernel allows a developer to have complete control over these parameters by
using a config.json file placed in the same directory as the skprompt.txt file.
For example, if you were to create a plugin called TestPlugin with two semantic
functions called SloganMaker and OtherFunction , the file structure would look like this:
File-Structure-For-Semantic-Plugins
TestPlugin
│
└─── SloganMaker
| |
│ └─── skprompt.txt
│ └─── config.json
│
└─── OtherFunction
|
└─── skprompt.txt
└─── config.json
The config.json file for the SloganMaker function would look like this:
config.json-example
{
"schema": 1,
"type": "completion",
"description": "a function that generates marketing slogans",
"completion": {
"max_tokens": 1000,
"temperature": 0.0,
"top_p": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
}
"input": {
"parameters": [
{
"name": "input",
"description": "The product to generate a slogan for",
"defaultValue": ""
}
]
}
}
7 Note
The config.json file is currently optional, but if you wish to exercise precise control
of a function's behavior be sure to include it inside each function directory.
Because these parameters impact the behavior of planner, we recommend running tests
on the values you provide to ensure they are used by planner correctly.
When writing description and input , we recommend using the following guidelines:
The description fields should be short and concise so that it does not consume
too many tokens when used in the planner prompt.
Consider the description s of other functions in the same plugin to ensure that
they are sufficiently unique. If they are not, planner may not be able to distinguish
between them.
If you have trouble getting planner to use a function, try adding recommendations
or examples for when to use the function.
The following table describes the parameters available for use in the completion object
for the OpenAI and Azure OpenAI APIs:
Completion Type Required? Default Description
Parameter
To learn more about the various parameters available for tuning how a function works,
visit the Azure OpenAI reference.
Tip
Key topics:
Tokens are the basic units of text or code that an LLM AI uses to process and generate
language. Tokens can be characters, words, subwords, or other segments of text or
code, depending on the chosen tokenization method or scheme. Tokens are assigned
numerical values or identifiers, and are arranged in sequences or vectors, and are fed
into or outputted from the model. Tokens are the building blocks of language for the
model.
The Semantic Kernel prompt template language is a simple and powerful way to define
and compose AI functions using plain text. You can use it to create natural language
prompts, generate responses, extract information, invoke other prompts or perform any
other task that can be expressed with text.
The language supports three basic features that allow you to (#1) include variables, (#2)
call external functions, and (#3) pass parameters to functions.
You don't need to write any code or import any external libraries, just use the curly
braces {{...}} to embed expressions in your prompts. Semantic Kernel will parse your
template and execute the logic behind it. This way, you can easily integrate AI into your
apps with minimal effort and maximum flexibility.
Variables
To include a variable value in your text, use the {{$variableName}} syntax. For example,
if you have a variable called name that holds the user's name, you can write:
Function calls
To call an external function and embed the result in your text, use the
{{namespace.functionName}} syntax. For example, if you have a function called
weather.getForecast that returns the weather forecast for a given location, you can
write:
This will produce a sentence with the weather forecast for the default location stored in
the input variable. The input variable is set automatically by the kernel when invoking
a function. For instance, the code above is equivalent to:
The weather today is {{weather.getForecast $input}}.
Function parameters
To call an external function and pass a parameter to it, use the {namespace.functionName
$varName} syntax. For example, if you want to pass a different input to the weather
forecast function, you can write:
This will produce two sentences with the weather forecast for two different locations,
using the city stored in the city variable and the region name stored in the region
variable.
Design Principles
The template language uses of the $ symbol on purpose, to clearly distinguish between
variables, which are retrieved from local temporary memory, and functions that retrieve
content executing some code.
Branching features such as "if", "for", and code blocks are not part of SK's template
language. This reflects SK's design principle of using natural language as much as
possible, with a clear separation from conventional programming code.
By using a simple language, the kernel can also avoid complex parsing and external
dependencies, resulting in a fast and memory efficient processing.
skprompt.txt
My name: {{msgraph.GetMyName}}
My email: {{msgraph.GetMyEmailAddress}}
Recipient: {{$recipient}}
Email to reply to:
=========
{{$sourceEmail}}
=========
Generate a response to the email, to say: {{$input}}
Include the original email quoted after the response.
C#
try {
string email = await this._msgraph.GetMyEmailAddress();
} catch {
...
}
try {
// Use AI to generate an email using the 5 given variables
// Take care of retry logic, tracking AI costs, etc.
string response = await ...
return response;
} catch {
...
}
}
What are Memories?
Article • 05/23/2023
Memories are a powerful way to provide broader context for your ask. Historically, we've
always called upon memory as a core component for how computers work: think the
RAM in your laptop. For with just a CPU that can crunch numbers, the computer isn't
that useful unless it knows what numbers you care about. Memories are what make
computation relevant to the task at hand.
We access memories to be fed into Semantic Kernel in one of three ways — with the
third way being the most interesting:
1. Conventional key-value pairs: Just like you would set an environment variable in
your shell, the same can be done when using Semantic Kernel. The lookup is
"conventional" because it's a one-to-one match between a key and your query.
3. Semantic memory search: You can also represent text information as a long vector
of numbers, known as "embeddings." This lets you execute a "semantic" search
that compares meaning-to-meaning with your query.
So basically you take a sentence, paragraph, or entire page of text, and then generate
the corresponding embedding vector. And when a query is performed, the query is
transformed to its embedding representation, and then a search is performed through
all the existing embedding vectors to find the most similar ones. This is similar to when
you make a search query on Bing, and it gives you multiple results that are proximate to
your query. Semantic memory is not likely to give you an exact match — but it will
always give you a set of matches ranked in terms of how similar your query matches
other pieces of text.
It would be nice if we could use an entire 10,000-page operating manual as context for
our prompt, but because of the token limit constraint, that is impossible. Therefore,
embeddings are useful for breaking down that large text into smaller pieces. We can do
this by summarizing each page into a shorter paragraph and then generating an
embedding vector for each summary. An embedding vector is like a compressed
representation of the text that preserves its meaning and context. Then we can compare
the embedding vectors of our summaries with the embedding vector of our prompt and
select the most similar ones. We can then add those summaries to our input text as
context for our prompt. This way, we can use embeddings to help us choose and fit
large texts as context within the token limit of the model.
Tip
Memory: Embeddings
Embeddings are vectors or arrays of numbers that represent the meaning and
the context of tokens processed by the model.
They are used to encode and decode input and output texts, and can vary in
size and dimension. / Embeddings can help the model understand the
relationships between tokens, and generate relevant and coherent texts.
They are used for text classification, summarization, translation, and
generation, as well as image and code generation.
Text classification: Embeddings can help the model to assign labels or categories
to texts, based on their meaning and context. For example, embeddings can help
the model to classify texts as positive or negative, spam or not spam, news or
opinion, etc.
Text summarization: Embeddings can help the model to extract or generate the
most important or relevant information from texts, and to create concise and
coherent summaries. For example, embeddings can help the model to summarize
news articles, product reviews, research papers, etc.
Text translation: Embeddings can help the model to convert texts from one
language to another, while preserving the meaning and the structure of the
original texts. For example, embeddings can help the model to translate texts
between English and Spanish, French and German, Chinese and Japanese, etc.
Text generation: Embeddings can help the model to create new and original texts,
based on the input or the prompt that the user provides. For example, embeddings
can help the model to generate texts such as stories, poems, jokes, slogans,
captions, etc.
Image generation: Embeddings can help the model to create images from texts, or
vice versa, by converting different types of data into a common representation. For
example, embeddings can help the model to generate images such as logos, faces,
animals, landscapes, etc.
Code generation: Embeddings can help the model to create code from texts, or
vice versa, by converting different types of data into a common representation. For
example, embeddings can help the model to generate code such as HTML, CSS,
JavaScript, Python, etc.
The main advantage of a vector database is that it allows for fast and accurate similarity
search and retrieval of data based on their vector distance or similarity. This means that
instead of using traditional methods of querying databases based on exact matches or
predefined criteria, you can use a vector database to find the most similar or relevant
data based on their semantic or contextual meaning.
find images that are similar to a given image based on their visual content and
style
find documents that are similar to a given document based on their topic and
sentiment
find products that are similar to a given product based on their features and
ratings
To perform similarity search and retrieval in a vector database, you need to use a query
vector that represents your desired information or criteria. The query vector can be
either derived from the same type of data as the stored vectors (e.g., using an image as
a query for an image database), or from different types of data (e.g., using text as a
query for an image database). Then, you need to use a similarity measure that calculates
how close or distant two vectors are in the vector space. The similarity measure can be
based on various metrics, such as cosine similarity, euclidean distance, hamming
distance, jaccard index.
The result of the similarity search and retrieval is usually a ranked list of vectors that
have the highest similarity scores with the query vector. You can then access the
corresponding raw data associated with each vector from the original source or index.
One use case for storing information in a vector database is to enable large language
models (LLMs) to generate more relevant and coherent text based on an AI plugin.
However, large language models often face challenges such as generating inaccurate or
irrelevant information; lacking factual consistency or common sense; repeating or
contradicting themselves; being biased or offensive. To overcome these challenges, you
can use a vector database to store information about different
topics,keywords,facts,opinions,sources, related to your desired domain or genre. Then,
you can use a large language model and pass information from the vector database
with your AI plugin to generate more informative and engaging content that matches
your intent and style.
For example, if you want to write a blog post about the latest trends in AI, you can use a
vector database to store the latest information about that topic and pass the
information along with the ask to a LLM in order to generate a blog post that leverages
the latest information.
In this how-to guide we will provide steps to deploy Semantic Kernel to Azure as a web
app service. Deploying Semantic Kernel as web service to Azure provides a great
pathway for developers to take advantage of Azure compute and other services such as
Azure Cognitive Services for responsible AI and vectorized databases.
You can use one of the deployment options to deploy based on your use case and
preference.
Considerations
1. Azure currently limits the number of Azure OpenAI resources per region per
subscription to 3. Azure OpenAI is not available in every region. (Refer to this
availability map ) Bearing this in mind, you might want to use the same Azure
OpenAI instance for multiple deployments of Semantic Kernel to Azure.
2. F1 and D1 App Service SKU's (the Free and Shared ones) are not supported for this
deployment.
4. Using web frontends to access your deployment: make sure to include your
frontend's URL as an allowed origin in your deployment's CORS settings.
Otherwise, web browsers will refuse to let JavaScript make calls to your
deployment.
Use this option to use an existing Azure OpenAI instance and connect the
PowerShell File
Semantic Kernel web API to it.
Bash File
Use Case Deployment
Option
Use this option to deploy Semantic Kernel in a web app service and have it
PowerShell File
use a new instance of Azure OpenAI.
Bash File
Note: access to new Azure OpenAI resources is currently limited due to
high demand.
Use this option to use your OpenAI account and connect the Semantic
PowerShell File
Kernel web API to it.
Bash File
Script Parameters
Below are examples on how to run the PowerShell and bash scripts. Refer to each of the
script files for the complete list of available parameters and usage.
PowerShell
Creating new Azure OpenAI Resources
PowerShell
After entering the command below, you will be prompted to enter your Azure OpenAI
API key. (You can also pass in the API key using the -ApiKey parameter)
PowerShell
After entering the command below, you will be prompted to enter your OpenAI API key.
(You can also pass in the API key using the -ApiKey parameter)
PowerShell
Bash
Creating new Azure OpenAI Resources
Bash
Bash
./DeploySK-Existing-AzureOpenAI.sh -d YOUR_DEPLOYMENT_NAME -s
YOUR_SUBSCRIPTION_ID -e YOUR_AZURE_OPENAI_ENDPOINT -o
YOUR_AZURE_OPENAI_API_KEY
Bash
1. Subscription: decide which Azure subscription you want to use. This will house the
resource group for the Semantic Kernel web application.
2. Resource Group: the resource group in which your deployment will go. Creating a
new resource group helps isolate resources, especially if you are still in active
development.
3. Region: select the geo-region for deployment. Note: Azure OpenAI is not available
in all regions and is currently to three instances per region per subscription.
4. Name: used to identify the app. App Service SKU: select the pricing tier based on
your usage. Click here to learn more about Azure App Service plans.
5. Package URI: there is no need to change this unless you want to deploy a
customized version of Semantic Kernel. (See this page for more information on
publishing your own version of the Semantic Kernel web app service)
6. Completion, Embedding and Planner Models: these are by default using the
appropriate models based on the current use case - that is Azure OpenAI or
OpenAI. You can update these based on your needs.
7. Endpoint: this is only applicable if using Azure OpenAI and is the Azure OpenAI
endpoint to use.
8. API Key: enter the API key for the instance of Azure OpenAI or OpenAI to use.
9. Semantic Kernel API Key: the default value of "[newGuid()]" in this field will create
an API key to protect you Semantic Kernel endpoint. You can change this by
providing your own API key. If you do not want to use API authorization, you can
make this field blank.
10. CosmosDB: whether to deploy a CosmosDB resource to store chats. Otherwise,
volatile memory will be used.
11. Qdrant: whether to deploy a Qdrant database to store embeddings. Otherwise,
volatile memory will be used.
12. Speech Services: whether to deploy an instance of the Azure Speech service to
provide speech-to-text for input.
To get your instance's URL, go to your deployment's resource group (by clicking on the
"Go to resource group" button seen at the conclusion of your deployment if you use the
"Deploy to Azure" button). Then click on the resource whose name ends with "-skweb".
This will bring you to the Overview page on your web service. Your instance's URL is the
value that appears next to the "Default domain" field.
Scrolling down in that same pane to the "Monitoring" section gives you access to a
multitude of ways to monitor your deployment.
In addition to this, the "Diagnose and solve problems" item near the top of the pane can
yield crucial insight into some problems your deployment may be experiencing.
If the service itself is functioning properly but you keep getting errors (perhaps reported
as 400 HTTP errors) when making calls to the Semantic Kernel, check that you have
correctly entered the values for the following settings:
AIService:AzureOpenAI
AIService:Endpoint
AIService:Models:Completion
AIService:Models:Embedding
AIService:Models:Planner
PowerShell
If you have not already done so, please star the GitHub repo and join the Semantic
Kernel community! Star the Semantic Kernel repo
Learn how to make changes to the
Semantic Kernel web app service
Article • 05/26/2023
This guide provides steps to make changes to the skills of a deployed instance of the
Semantic Kernel web app. Currently, changing semantic skills can be done without
redeploying the web app service but changes to native skills do require re-deployments.
This document will guide you through the process of doing both.
Prerequisites
1. An instance of the Semantic Kernel web app service deployed in your Azure
subscription. You can follow the how-to guide here for details.
2. Have your web app's name handy. If you used the deployment templates provided
with the Copilot Chat, you can find the web app's name by going to the Azure
Portal and selecting the resource group created for your Semantic Kernel web
app service. Your web app's name is the one of the resource listed that ends with
"skweb".
3. Locally tested skills or planner ready to be added to your Semantic Kernel web app
service.
Tip: You can find examples skills & planners in the GitHub Semantic Kernel repo.
You can use the standard methods available to deploy an ASP.net web app in order to
do so.
Alternatively, you can follow the steps below to manually build and upload your
customized version of the Semantic Kernel service to Azure.
PowerShell
This will create a directory which contains all the files needed for a deployment:
../semantic-kernel/samples/apps/copilot-chat-
app/webapi/bin/Release/net6.0/win-x64/publish'
Zip the contents of that directory and store the resulting zip file on cloud storage, e.g.
Azure Blob Container. Put its URI in the "Package Uri" field in the web deployment page
you access through the "Deploy to Azure" buttons or use its URI as the value for the
PackageUri parameter of the deployment scripts found on this page.
Your deployment will then use your customized deployment package. That package will
be used to create a new Azure web app, which will be configured to run your
customized version of the Semantic Kernel service.
JSON
"Service": {
"SemanticSkillsDirectory": "/SemanticSkills",
"KeyVaultUri": ""
},
If you have not already done so, please star the GitHub repo and join the Semantic
Kernel community! Star the Semantic Kernel repo
Protect your Azure OpenAI API keys
with Azure API Management
Article • 06/07/2023
With Azure API Management, you can protect your AI API keys and manage access to
your AI APIs. This is helpful if you want to give your users or developers access to Azure
OpenAPI APIs without giving them direct access to your keys or to manage access to
your AI APIs directly from Azure.
By the end of this article, you'll have a working API Management instance along with
sample code that shows you how to use Azure API Management with Semantic Kernel.
Prerequisites
To complete this tutorial, you'll first need access to the following:
To create a new API Management instance, see Create an API Management instance.
You can use the default configuration when creating your instance.
1. Start by downloading the API definition for Azure OpenAI and saving it to your
local machine.
2. Open the file in a text editor and change the servers property so that the url and
endpoint properties point to your API endpoint.
For example, if your API endpoint is https://contoso.openai.azure.com , you would
change the servers property to the following:
JSON
"servers": [
{
"url": "https://contoso.openai.azure.com/openai",
"variables": {
"endpoint": {
"default": "contoso.openai.azure.com"
}
}
}
],
3. You can now import the file from step 2 into Azure API Management. The full
process is described in the import and publish article.
4. Now create a named value for your Azure OpenAI API key.
This will allow you to better protect your Azure OpenAI API key. To create a named
value, see using named values in Azure API Management policies. Take note of the
Display name you give your named value as you'll need it in the next step.
5. Finally, edit the inbound policy so your API adds the api-key header to your
request.
a. Navigate to your API Management instance and select APIs from the left-hand
menu.
b. Select your API from the list of APIs.
c. Select the Design tab.
d. Select Add policy within the Inbound processing section.
e. Select Set headers.
f. In the Set headers page, enter openai-key for the Name field
g. For the Value field, take the display name of your named value in the previous
step and wrap it in double curly braces. For example, if the display name of your
named value was azure-openai-key , you would enter {{azure-openai-key}} .
h. Leave the action as append .
i. Select Save.
You can also use key vault secrets to protect your Auzre OpenAI API key even
more. To learn more, see using named values in Azure API Management policies.
You've now created and initially setup your Azure OpenAI API with Azure API
Management. You can now test your API by selecting the Test tab in Azure API
Management. For more information, see Test an API. Next, we'll configure authentication
for your new API so only authorized users can access it.
2. Configure OAuth 2.0 by folloing the steps in the protect an API in Azure API
Management using OAuth 2.0 authorization with Azure Active Directory article.
Once you're done with these steps you'll have an Azure AD application with the
necessary scopes.
3. Next, configure a JWT validation policy to pre-authorize requests. This will ensure
that only users with the correct permissions can access your API and underlying
Azure OpenAI API.
Congrats, you've now configured authentication for your Azure OpenAI API with Azure
API Management. You can now provide users with access to your API by creating users
in Azure AD and assigning them the correct permissions. For more information, see
Assign a user or group to an enterprise app in Azure Active Directory.
) Important
1. First, create a new class that implements the TokenCredential class. This class will
be used to provide Semantic Kernel with the user authentication token for your
service.
C#
using Azure.Core;
2. Next, within your console application, you'll create an interactive logon to get the
user's token.
C#
3. Finally, you can create a new instance of Kernel and pass in the
BearerTokenCredential class you created in step 1 along with the access token you
retrieved in step 2.
C#
Multiple learning samples are provided in the Semantic Kernel GitHub repository to
help you learn core concepts of Semantic Kernel.
) Important
The local API service must be active for the sample apps to run.
Simple chat Use ready-to-use plugins and get those plugins into your app easily. Be sure that
summary the local API service is running for this sample to work.
Book creator Use planner to deconstruct a complex goal and envision using planner in your
app. Be sure that the local API service is running for this sample to work.
Authentication Use a basic plugin pattern to authenticate and connect to an API and imagine
and APIs integrating external data into your app's LLM AI. Be sure that the local API service
is running for this sample to work.
GitHub Repo Use embeddings to store local data and functions to question the embedded
Q&A Bot data. Be sure that the local API service is running for this sample to work.
Copilot Chat Build your own chatbot based on the Semantic Kernel.
Sample App
Next step
Run the simple chat summary app
Local API service for app samples
Article • 05/23/2023
This service API is written in C# against Azure Function Runtime v4 and exposes some
Semantic Kernel APIs that you can call via HTTP POST requests for the learning samples.
) Important
Each function will call OpenAI which will use tokens that you will be billed for.
Walkthrough video
https://aka.ms/SK-Local-API-Setup
Run func start --csharp from the command line. This will run the service API locally at
http://localhost:7071 .
InvokeFunction: [POST]
http://localhost:7071/api/skills/{skillName}/invoke/{functionName}
The Simple Chat Summary sample allows you to see the power of functions used in a
chat sample app. The sample highlights the Summarize , Topics and Action Items
functions in the Summarize Plugin . Each function calls OpenAI to review the
information in the chat window and produces insights.
) Important
Each function will call OpenAI which will use tokens that you will be billed for.
Walkthrough video
https://aka.ms/SK-Samples-SimChat-Video
1. Follow the Setup instructions if you do not already have a clone of Semantic Kernel
locally.
2. Start the local API service.
3. Open the ReadMe file in the Simple Chat Summary sample folder.
4. Open the Integrated Terminal window.
5. Run yarn install - if this is the first time you are running the sample. Then run
yarn start .
Setup Screen
Start by entering in your OpenAI key or if you are using Azure OpenAI Service the key
and endpoint. Then enter in the model you would like to use in this sample.
Interact Screen
A preloaded chat conversation is avaialble. You can add additional items in the chat or
modify the chat thread before running the sample.
AI Summaries Screen
Three semantic functions are called on this screen
1. Summarize
2. Topics
3. Action Items
Next step
Run the book creator app
Book creator sample app
Article • 05/23/2023
The Book creator sample allows you to enter in a topic then the Planner creates a plan
for the functions to run based on the ask. You can see the plan along with the results.
The Writer Skill functions are chained together based on the asks.
) Important
Each function will call OpenAI which will use tokens that you will be billed for.
Walkthrough video
https://aka.ms/SK-Samples-CreateBook-Video
1. Follow the Setup instructions if you do not already have a clone of Semantic Kernel
locally.
2. Start the local API service.
3. Open the ReadMe file in the Book creator sample folder.
4. Open the Integrated Terminal window.
5. Run yarn install - if this is the first time you are running the sample. Then run
yarn start .
6. A browser will open with the sample app running
Topics Screen
On this screen you can enter in a topic for the children's book that will be created for
you. This will use functions and AI to generate book ideas based on this topic.
Book Screen
By clicking on the asks, multiple steps will be found from the Planner and the process
will run to return results.
Next step
Run the authentication and API app
Authentication and API calls sample app
Article • 05/23/2023
The Authenticated API’s sample allows you to use authentication to connect to the
Microsoft Graph using your personal account. If you don’t have a Microsoft account or
do not want to connect to it, you can review the code to see the patterns needed to call
out to APIs. The sample highlights connecting to Microsoft Graph and calling APIs for
Outlook, OneDrive, and ToDo. Each function will call Microsoft Graph and/or OpenAI to
perform the tasks.
) Important
Each function will call OpenAI which will use tokens that you will be billed for.
Walkthrough video
https://aka.ms/SK-Samples-AuthAPI-Video
1. Follow the Setup instructions if you do not already have a clone of Semantic Kernel
locally.
2. Start the local API service.
3. Open the ReadMe file in the Authentication and API sample folder.
4. You will need to register your application in the Azure Portal. Follow the steps to
register your app here.
Setup Screen
Start by entering in your OpenAI key or if you are using Azure OpenAI Service the key
and endpoint. Then enter in the model you would like to use in this sample.
Interact Screen
When you select each of the 3 actions, native functions will be called to preform actions
through the Microsoft Graph API and connector.
The GitHub Repo Q&A Bot sample allows you to enter in a GitHub repo then those files
are created as embeddings. You can then question the stored files from the embedding
local storage.
) Important
Each function will call OpenAI which will use tokens that you will be billed for.
Walkthrough video
https://aka.ms/SK-GitHub-QA-Bot-Video
1. Follow the Setup instructions if you do not already have a clone of Semantic Kernel
locally.
2. Start the local API service.
3. Open the ReadMe file in the GitHub Repo Q&A Bot sample folder.
4. Open the Integrated Terminal window.
5. Run yarn install - if this is the first time you are running the sample. Then run
yarn start .
Q&A Screen
By default the Markdown files are stored as embeddings. You can ask questions in the
chat and get answers based on the embeddings.
Next step
Run the Copilot Chat sample app!
The Copilot Chat sample allows you to build your own integrated large language model
chatbot. This is an enriched intelligence app, with multiple dynamic components
including command messages, user intent, and memories.
The chat prompt and response will evolve as the conversation between the user and the
application proceeds. This chat experience uses a chat plugin containing multiple
functions that work together to construct the final prompt for each exchange.
) Important
Each function will call OpenAI which will use tokens that you will be billed for.
1. Follow the Setup instructions if you do not already have a clone of Semantic Kernel
locally.
2. Follow the instructions to Register an Azure Application
3. Open the ReadMe file in the Copilot Chat sample folder.
4. Follow the ReadMe instructions to configure, start, and test the Backend API Server
5. Follow the ReadMe instructions to start the front end WebApp
6. A browser should automatically launch and navigate to https://localhost:3000. with
the sample app running
Exploring the app
With the Copilot Chat sample app running, you can start interacting with the chatbot.
The app will start with a default conversation thread where you can ask it questions.
1 Conversation The left portion of the screen shows different conversation threads the
Pane user is holding with the chatbot. To start a new conversation, click the
'+'Bot symbol.
2 Conversation Chatbot responses will appear in the main conversation thread, along
Thread with a history of your prompts. Users can scroll up and down to review
a complete conversation history.
3 Prompt Entry The bottom of the screen contains the prompt entry box, where users
Box can type their prompts, and click the "Send" icon to the right of the box
when ready to send it to the bot.
Next step
If you've tried all the apps and are excited to see more, please star the GitHub repo and
join the Semantic Kernel community!
The Semantic Kernel Tools help developers to write semantic functions for Semantic
Kernel .
7 Note
Skills are currently being renamed to plugins. This article has been updated to
reflect the latest terminology, but some images and code samples may still refer to
skills.
In the following image you can see how a user can easily view all of their semantic
functions, edit them, and run them from within Visual Studio Code using any of the
supported AI endpoints.
Installing the Semantic Kernel Extension
To get started with Semantic Kernel Tools, follow these simple steps:
1. Ensure that you have Visual Studio Code installed on your computer.
2. Open Visual Studio Code and press Shift+Control+X to bring up the Extensions
marketplace .
3. In the Extensions menu, search for "Semantic Kernel Tools ".
4. Select Semantic Kernel Tools from the search results and click the Install button.
5. Wait for the installation to complete, then restart Visual Studio Code.
Open the Command Palette i.e., View -> Command Palette or Ctrl+Shift+P
1. If you have access to an Azure subscription that contains the Azure OpenAI
resource you want to use:
2. Type "Add Azure OpenAI Endpoint" and you will be prompted for the following
information:
3. If you have the details of an Azure OpenAI endpoint that you want to use
Type "Add AI Endpoint" and you will be prompted for the following information:
Endpoint type, select "completion"
Completion label, the default of "Completion" is fine
Completion AI Service, select AzureOpenAI
Completion deployment or model id e.g., text-davinci-003
Completion endpoint URI e.g., https://contoso-openai.azure.com/
Completion endpoint API key (this will be stored in VS Code secure storage)
4. If you have the details of an OpenAI endpoint that you want to use
Type "Add AI Endpoint" and you will be prompted for the following information:
Endpoint type, select "completion"
Completion label, the default of "Completion" is fine
Completion AI Service, select OpenAI
Completion deployment or model id e.g., text-davinci-003
Completion endpoint API key (this will be stored in VS Code secure storage)
2. Click the Semantic Kernel icon to open Semantic Kernel Functions view
3. Click the "Add Semantic Skill" icon in the Semantic Kernel Functions view title bar
4. You will be prompted to select a folder
This will be the location of the plugin which will contain your new Semantic
Function
Create a new folder called MyPlugin1 in this directory <location of your
clone>\semantic-kernel\samples\skills
Select this new folder as your Plugin folder
Troubleshooting
Enabling Trace Level Logs
You can enable trace level logging for the Semantic Kernel using the following
steps:
Below is a list of possible errors you might receive and details on how to address them.
Unable to find any subscriptions. Please log in with a user account that has access
to a subscription where OpenAI resources have been deployed.
The user account you specified to use when logging in to Microsoft does not have
access to any subscriptions. Please try again with a different account.
Unable to find any resource groups. Please log in with a user account that has
access to a subscription where OpenAI resources have been deployed.
The user account you specified to use when logging in to Microsoft does not have
access to any resource groups in the subscription you selected. Please try again
with a different account or a different subscription.
Unable to find any OpenAI resources. Please log in with a user account that has
access to a subscription where OpenAI resources have been deployed.
The user account you specified to use when logging in to Microsoft does not have
access to any Azure OpenAI resources in the resource group you selected. Please
try again with a different account or a different resource group.
Unable to find any OpenAI model deployments. Please log in with a user account
that has access to a subscription where OpenAI model deployments have been
deployed.
The user account you specified to use when logging in to Microsoft does not have
access to any deployment models in the Azure OpenAI resource you selected.
Please try again with a different account or a different Azure OpenAI resource.
Unable to access the Azure OpenAI account. Please log in with a user account that
has access to an Azure OpenAI account.
The user account you specified to use when logging in to Microsoft does not have
access to the Azure OpenAI account in the Azure OpenAI resource you selected.
Please try again with a different account or a different Azure OpenAI resource.
Unable to access the Azure OpenAI account keys. Please log in with a user account
that has access to an Azure OpenAI account.
The user account you specified to use when logging in to Microsoft does not have
access to the Azure OpenAI account keys in the Azure OpenAI resource you
selected. Please try again with a different account or a different Azure OpenAI
resource.
Settings does not contain a valid AI completion endpoint configuration. Please run
the "Add Azure OpenAI Enpoint" or "Add AI Endpoint" command to configure a
valid endpoint.
You have not configured an AI endpoint. Please refer to the first part of the Execute
a Semantic Function section above.
👋 Welcome! There are a variety of ways to get supported in the Semantic Kernel (SK)
world.
Read the docs This learning site is the home of the latest information for developers
Visit the repo Our open-source GitHub repository is availble for perusal and suggestions
Realtime chat Visit our Discord channel to get supported quickly with our CoC actively
enforced
Realtime video We will be hosting regular office hours that will be announced in our Discord
channel
Next step
Run the samples
Semantic Kernel FAQ's
Article • 05/23/2023
Our Pledge
In the interest of fostering an open and welcoming environment, we as owners,
contributors and maintainers pledge to making participation in our project and our
community a harassment-free experience for everyone, regardless of age, body size,
disability, ethnicity, gender identity and expression, level of experience, nationality,
personal appearance, race, religion, or sexual identity and orientation.
Our Standards
Examples of behavior that contributes to creating a positive environment include:
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior
and are expected to take appropriate and fair corrective action in response to any
instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are not
aligned to this Code of Conduct, or to ban temporarily or permanently any contributor
for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
Scope
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community. Examples of representing a
project or community include using an official project e-mail address, posting via an
official social media account, or acting as an appointed representative at an online or
offline event. Representation of a project may be further defined and clarified by project
maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting the project team by using #moderation in the Discord community . The
project team will review and investigate all complaints, and will respond in a way that it
deems appropriate to the circumstances. The project team is obligated to maintain
confidentiality with regard to the reporter of an incident. Further details of specific
enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith
may face temporary or permanent repercussions as determined by other members of
the project's leadership.
Attribution
This Code of Conduct is adapted from the [Contributor Covenant]
[https://www.contributor-covenant.org/], version 1.4, available here .
Schillace Laws of Semantic AI
Article • 05/23/2023
1. Don’t write code if the model can do it; the model will get better, but the code
won't. The overall goal of the system is to build very high leverage programs using
the LLM's capacity to plan and understand intent. It's very easy to slide back into a
more imperative mode of thinking and write code for aspects of a program. Resist
this temptation – to the degree that you can get the model to do something
reliably now, it will be that much better and more robust as the model develops.
2. Trade leverage for precision; use interaction to mitigate. Related to the above,
the right mindset when coding with an LLM is not "let's see what we can get the
dancing bear to do," it's to get as much leverage from the system as possible. For
example, it's possible to build very general patterns, like "build a report from a
database" or "teach a year of a subject" that can be parameterized with plain text
prompts to produce enormously valuable and differentiated results easily.
3. Code is for syntax and process; models are for semantics and intent. There are
lots of different ways to say this, but fundamentally, the models are stronger when
they are being asked to reason about meaning and goals, and weaker when they
are being asked to perform specific calculations and processes. For example, it's
easy for advanced models to write code to solve a sudoku generally, but hard for
them to solve a sudoku themselves. Each kind of code has different strengths and
it's important to use the right kind of code for the right kind of problem. The
boundaries between syntax and semantics are the hard parts of these programs.
4. The system will be as brittle as its most brittle part. This goes for either kind of
code. Because we are striving for flexibility and high leverage, it’s important to not
hard code anything unnecessarily. Put as much reasoning and flexibility into the
prompts and use imperative code minimally to enable the LLM.
5. Ask Smart to Get Smart. Emerging LLM AI models are incredibly capable and "well
educated" but they lacks context and initiative. If you ask them a simple or open-
ended question, you will get a simple or generic answer back. If you want more
detail and refinement, the question has to be more intelligent. This is an echo of
"Garbage in, Garbage out" for the AI age.
7. Text is the universal wire protocol. Since the LLMs are adept at parsing natural
language and intent as well as semantics, text is a natural format for passing
instructions between prompts, modules and LLM based services. Natural language
is less precise for some uses, and it is possible to use structured language like XML
sparingly, but generally speaking, passing natural language between prompts
works very well, and is less fragile than more structured language for most uses.
Over time, as these model-based programs proliferate, this is a natural "future
proofing" that will make disparate prompts able to understand each other, the
same way humans do.
8. Hard for you is hard for the model. One common pattern when giving the model
a challenging task is that it needs to "reason out loud." This is fun to watch and
very interesting, but it's problematic when using a prompt as part of a program,
where all that is needed is the result of the reasoning. However, using a "meta"
prompt that is given the question and the verbose answer and asked to extract just
the answer works quite well. This is a cognitive task that would be easier for a
person (it's easy to imagine being able to give someone the general task of "read
this and pull out whatever the answer is" and have that work across many domains
where the user had no expertise, just because natural language is so powerful). So,
when writing programs, remember that something that would be hard for a person is
likely to be hard for the model, and breaking patterns down into easier steps often
gives a more stable result.
Microsoft’s Transparency Notes are part of a broader effort at Microsoft to put our AI
Principles into practice. To find out more, see the Microsoft AI principles .
Planner The planner breaks it down into steps based upon resources that are available
Plugins Plugins are customizable resources built from LLM AI prompts and native code
Concept Short Description
Connectors Connectors are customizable resources that enable external data access
Intended uses
The general intended uses include:
Chat and conversation interaction: Users can interact with a conversational agent
that responds with responses drawn from trusted documents such as internal
company documentation or tech support documentation; conversations must be
limited to answering scoped questions.
Chat and conversation creation: Users can create a conversational agent that
responds with responses drawn from trusted documents such as internal company
documentation or tech support documentation; conversations must be limited to
answering scoped questions.
Code generation or transformation scenarios: For example, converting one
programming language to another, generating docstrings for functions, converting
natural language to SQL.
Journalistic content: For use to create new journalistic content or to rewrite
journalistic content submitted by the user as a writing aid for pre-defined topics.
Users cannot use the application as a general content creation tool for all topics.
May not be used to generate content for political campaigns.
Question-answering: Users can ask questions and receive answers from trusted
source documents such as internal company documentation. The application does
not generate answers ungrounded in trusted source documentation.
Reason over structured and unstructured data: Users can analyze inputs using
classification, sentiment analysis of text, or entity extraction. Examples include
analyzing product feedback sentiment, analyzing support calls and transcripts, and
refining text-based search with embeddings.
Search: Users can search trusted source documents such as internal company
documentation. The application does not generate results ungrounded in trusted
source documentation.
Summarization: Users can submit content to be summarized for pre-defined topics
built into the application and cannot use the application as an open-ended
summarizer. Examples include summarization of internal company documentation,
call center transcripts, technical reports, and product reviews.
Writing assistance on specific topics: Users can create new content or rewrite
content submitted by the user as a writing aid for business content or pre-defined
topics. Users can only rewrite or create content for specific business purposes or
pre-defined topics and cannot use the application as a general content creation
tool for all topics. Examples of business content include proposals and reports. For
journalistic use, see above Journalistic content use case.
Understand what it can do: Fully assess the capabilities of any AI system you are
using to understand its capabilities and limitations. Understand how it will perform
in your particular scenario and context by thoroughly testing it with real life
conditions and data.
Respect an individual's right to privacy: Only collect data and information from
individuals for lawful and justifiable purposes. Only use data and information that
you have consent to use for this purpose.
Legal review: Obtain appropriate legal advice to review your solution, particularly if
you will use it in sensitive or high-risk applications. Understand what restrictions
you might need to work within and your responsibility to resolve any issues that
might come up in the future. Do not provide any legal advice or guidance.
Security: Ensure your solution is secure and has adequate controls to preserve the
integrity of your content and prevent unauthorized access.
Build trust with affected stakeholders: Communicate the expected benefits and
potential risks to affected stakeholders. Help people understand why the data is
needed and how the use of the data will lead to their benefit. Describe data
handling in an understandable way.
Customer feedback loop: Provide a feedback channel that allows users and
individuals to report issues with the service once it's been deployed. Once you've
deployed an AI-powered product or feature it requires ongoing monitoring and
improvement -- be ready to implement any feedback and suggestions for
improvement. Establish channels to collect questions and concerns from affected
stakeholders (people who may be directly or indirectly impacted by the system,
including employees, visitors, and the general public). Examples of such channels
are: