This ASP.Net web application provides a web service hosting the Semantic Kernel, enabling secure and modular access to its features for the Copilot Chat application without embedding kernel code and settings, while allowing user interfaces to be developed using frontend frameworks such as React and Angular.
Before you get started, make sure you have the following requirements in place:
-
.NET 6.0 for building and deploying .NET 6 projects.
-
(Optional) Visual Studio Code or Visual Studio.
-
Update the properties in
./appsettings.json
to configure your Azure OpenAI resource or OpenAI account. -
Generate and trust a localhost developer certificate.
- For Windows and Mac run
dotnet dev-certs https --trust
Select
Yes
when asked if you want to install this certificate. - For Linux run
dotnet dev-certs https
To verify the certificate has been installed and trusted, run
dotnet run dev-certs https --check
To clean your system of the developer certificate, run
dotnet run dev-certs https --clean
- For Windows and Mac run
-
(Optional) To enable support for uploading image file formats such as png, jpg and tiff, there are two options within the
OcrSupport
section of./appsettings.json
, the Tesseract open source library and Azure Form Recognizer.- Tesseract we have included the Tesseract nuget package.
- You will need to obtain one or more tessdata language data files such as
eng.traineddata
and add them to your./data
directory or the location specified in theOcrSupport:Tesseract:FilePath
location in./appsettings.json
. - Set the
Copy to Output Directory
value toCopy if newer
.
- You will need to obtain one or more tessdata language data files such as
- Azure Form Recognizer we have included the Azure.AI.FormRecognizer nuget package.
- You will need to obtain an Azure Form Recognizer resource and add the
OcrSupport:AzureFormRecognizer:Endpoint
andOcrSupport:AzureFormRecognizer:Key
values to the./appsettings.json
file.
- You will need to obtain an Azure Form Recognizer resource and add the
- Tesseract we have included the Tesseract nuget package.
You can start the WebApi service using the command-line, Visual Studio Code, or Visual Studio.
- Open a terminal
- Change directory to the Copilot Chat webapi project directory.
cd webapi/
- (Optional) Build the service and verify there are no errors.
dotnet build
- Run the service
dotnet run
- Early in the startup, the service will provide a probe endpoint you can use in a web browser to verify
the service is running.
info: Microsoft.SemanticKernel.Kernel[0] Health probe: https://localhost:40443/healthz
- build (CopilotChatWebApi)
- run (CopilotChatWebApi)
- [optional] watch (CopilotChatWebApi)
- Open the solution file in Visual Studio 2022 or newer (
CopilotChat.sln
). - In Solution Explorer, right-click on
CopilotChatWebApi
and selectSet as Startup Project
. - Start debugging by pressing
F5
or selecting the menu itemDebug
->Start Debugging
.
If you want to use SequentialPlanner (multi-step) instead ActionPlanner (single-step), we recommend using gpt-4
or gpt-3.5-turbo
as the planner model. SequentialPlanner works best with gpt-4
. Using gpt-3.5-turbo
will require using a relevancy filter.
To enable sequential planner,
- In ./webapi/appsettings.json, set
"Type": "Sequential"
under thePlanner
section. - Then, set your preferred Planner model (
gpt-4
orgpt-3.5-turbo
) under theAIService
configuration section.- If using
gpt-4
, no other changes are required. - If using
gpt-3.5-turbo
: change CopilotChatPlanner.cs to initialize SequentialPlanner with a RelevancyThreshold*.- Add
using
statement to top of file:using Microsoft.SemanticKernel.Planning.Sequential;
- The
CreatePlanAsync
method should return the following line ifthis._plannerOptions?.Type == "Sequential"
is true:* Thereturn new SequentialPlanner(this.Kernel, new SequentialPlannerConfig { RelevancyThreshold = 0.75 }).CreatePlanAsync(goal);
RelevancyThreshold
is a number from 0 to 1 that represents how similar a goal is to a function's name/description/inputs. You want to tune that value when using SequentialPlanner to help keep things scoped while not missing on on things that are relevant or including too many things that really aren't.0.75
is an arbitrary threshold and we recommend developers play around with this number to see what best fits their scenarios.
- Add
- If using
- Restart the
webapi
- Copilot Chat should be now running locally with SequentialPlanner.
By default, the service uses an in-memory volatile memory store that, when the service stops or restarts, forgets all memories. Qdrant is a persistent scalable vector search engine that can be deployed locally in a container or at-scale in the cloud.
To enable the Qdrant memory store, you must first deploy Qdrant locally and then configure the Copilot Chat API service to use it.
Before you get started, make sure you have the following additional requirements in place:
- Docker Desktop for hosting the Qdrant vector search engine.
-
Open a terminal and use Docker to pull down the container image.
docker pull qdrant/qdrant
-
Change directory to this repo and create a
./data/qdrant
directory to use as persistent storage. Then start the Qdrant container on port6333
using the./data/qdrant
folder as the persistent storage location.mkdir ./data/qdrant docker run --name copilotchat -p 6333:6333 -v "$(pwd)/data/qdrant:/qdrant/storage" qdrant/qdrant
To stop the container, in another terminal window run
docker container stop copilotchat; docker container rm copilotchat;
.
Azure Cognitive Search can be used as a persistent memory store for Copilot Chat. The service uses its vector search capabilities.
Enabling telemetry on CopilotChatApi allows you to capture data about requests to and from the API, allowing you to monitor the deployment and monitor how the application is being used.
To use Application Insights, first create an instance in your Azure subscription that you can use for this purpose.
On the resource overview page, in the top right use the copy button to copy the Connection String and paste this into the APPLICATIONINSIGHTS_CONNECTION_STRING
setting as either a appsettings value, or add it as a secret.
In addition to this there are some custom events that can inform you how users are using the service such as SkillFunction
.
To access these custom events the suggested method is to use Azure Data Explorer (ADX). To access data from Application Insights in ADX, create a new dashboard and add a new Data Source (use the ellipsis dropdown in the top right).
In the Cluster URI use the following link: https://ade.applicationinsights.io/subscriptions/<Your subscription Id>
. The subscription id is shown on the resource page for your Applications Insights instance. You can then select the Database for the Application Insights resource.
For more info see Query data in Azure Monitor using Azure Data Explorer.
CopilotChat specific events are in a table called customEvents
.
For example to see the most recent 100 skill function invocations:
customEvents
| where timestamp between (_startTime .. _endTime)
| where name == "SkillFunction"
| extend skill = tostring(customDimensions.skillName)
| extend function = tostring(customDimensions.functionName)
| extend success = tobool(customDimensions.success)
| extend userId = tostring(customDimensions.userId)
| extend environment = tostring(customDimensions.AspNetCoreEnvironment)
| extend skillFunction = strcat(skill, '/', function)
| project timestamp, skillFunction, success, userId, environment
| order by timestamp desc
| limit 100
Or to report the success rate of skill functions against environments, you can first add a parameter to the dashboard to filter the environment.
You can use this query to show the environments available by adding the Source
as this Query
:
customEvents
| where timestamp between (['_startTime'] .. ['_endTime']) // Time range filtering
| extend environment = tostring(customDimensions.AspNetCoreEnvironment)
| distinct environment
Name the variable _environment
, select Multiple Selection
and tick Add empty "Select all" value
. Finally Select all
as the Default value
.
You can then query the success rate with this query:
customEvents
| where timestamp between (_startTime .. _endTime)
| where name == "SkillFunction"
| extend skill = tostring(customDimensions.skillName)
| extend function = tostring(customDimensions.functionName)
| extend success = tobool(customDimensions.success)
| extend environment = tostring(customDimensions.AspNetCoreEnvironment)
| extend skillFunction = strcat(skill, '/', function)
| summarize Total=count(), Success=countif(success) by skillFunction, environment
| project skillFunction, SuccessPercentage = 100.0 * Success/Total, environment
| order by SuccessPercentage asc
You may wish to use the Visual tab to turn on conditional formatting to highlight low success rates or render it as a chart.
Finally you could render this data over time with a query like this:
customEvents
| where timestamp between (_startTime .. _endTime)
| where name == "SkillFunction"
| extend skill = tostring(customDimensions.skillName)
| extend function = tostring(customDimensions.functionName)
| extend success = tobool(customDimensions.success)
| extend environment = tostring(customDimensions.AspNetCoreEnvironment)
| extend skillFunction = strcat(skill, '/', function)
| summarize Total=count(), Success=countif(success) by skillFunction, environment, bin(timestamp,1m)
| project skillFunction, SuccessPercentage = 100.0 * Success/Total, environment, timestamp
| order by timestamp asc
Then use a Time chart on the Visual tab.