Skip to content

Commit

Permalink
Open API GitHub Plugin Skill + Frontend Auth (MSAL + Basic / PAT) (mi…
Browse files Browse the repository at this point in the history
…crosoft#641)

### Motivation and Context
This PR adds:

- Swagger files detailing List and Get Pull Request(s) functions. 
- Example 22 c on how to leverage imported OpenAPI GitHub Skill
- Basic (+ User PAT) and Msal Authentication flows in Copilot chat for
connector plug-ins, sending auth data if user enables plug-in
- Parsing headers in SemanticKernelController to import respective
OpenAPI Skill if auth information is provided

### Description
![image](https://user-images.githubusercontent.com/125500434/234473631-cb01eac2-12b7-4f78-a939-bc99f70d2184.png)

![image](https://user-images.githubusercontent.com/125500434/234473648-976fa0a5-f857-4693-b72b-b2f85a4d1eee.png)

![image](https://user-images.githubusercontent.com/125500434/234473826-9d0264a8-1e4c-464e-a59f-84affa1ae99a.png)

![image](https://user-images.githubusercontent.com/125500434/234473842-1efcbf7d-4bd4-4015-b903-c13bdd173191.png)

![image](https://user-images.githubusercontent.com/125500434/235235863-1353180f-f679-4445-afaf-4b4c2154d922.png)
  • Loading branch information
teresaqhoang committed May 1, 2023
1 parent 4a42d02 commit 7d5c59d
Show file tree
Hide file tree
Showing 26 changed files with 6,779 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
using Microsoft.SemanticKernel.AI;
using Microsoft.SemanticKernel.Orchestration;
using Microsoft.SemanticKernel.SkillDefinition;
using Microsoft.SemanticKernel.Skills.OpenAPI.Authentication;
using SemanticKernel.Service.Config;
using SemanticKernel.Service.Model;
using SemanticKernel.Service.Skills;
using SemanticKernel.Service.Skills.OpenAPI.Authentication;
using SemanticKernel.Service.Storage;

namespace SemanticKernel.Service.Controllers;
Expand Down Expand Up @@ -47,6 +49,7 @@ public class SemanticKernelController : ControllerBase
/// <param name="planner">Planner to use to create function sequences.</param>
/// <param name="plannerOptions">Options for the planner.</param>
/// <param name="ask">Prompt along with its parameters</param>
/// <param name="openApiSkillsAuthHeaders">Authentication headers to connect to OpenAPI Skills</param>
/// <param name="skillName">Skill in which function to invoke resides</param>
/// <param name="functionName">Name of function to invoke</param>
/// <returns>Results consisting of text generated by invoked function along with the variable in the SK that generated it</returns>
Expand All @@ -64,6 +67,7 @@ public class SemanticKernelController : ControllerBase
[FromServices] CopilotChatPlanner planner,
[FromServices] IOptions<PlannerOptions> plannerOptions,
[FromBody] Ask ask,
[FromHeader] OpenApiSkillsAuthHeaders openApiSkillsAuthHeaders,
string skillName, string functionName)
{
this._logger.LogDebug("Received call to invoke {SkillName}/{FunctionName}", skillName, functionName);
Expand All @@ -82,7 +86,7 @@ public class SemanticKernelController : ControllerBase
// Register skills with the planner if enabled.
if (plannerOptions.Value.Enabled)
{
await this.RegisterPlannerSkillsAsync(planner, plannerOptions.Value);
await this.RegisterPlannerSkillsAsync(planner, plannerOptions.Value, openApiSkillsAuthHeaders);
}

// Register native skills with the chat's kernel
Expand Down Expand Up @@ -131,10 +135,22 @@ public class SemanticKernelController : ControllerBase
/// <summary>
/// Register skills with the planner's kernel.
/// </summary>
private async Task RegisterPlannerSkillsAsync(CopilotChatPlanner planner, PlannerOptions options)
private async Task RegisterPlannerSkillsAsync(CopilotChatPlanner planner, PlannerOptions options, OpenApiSkillsAuthHeaders openApiSkillsAuthHeaders)
{
await planner.Kernel.ImportChatGptPluginSkillFromUrlAsync("KlarnaShopping", new Uri("https://www.klarna.com/.well-known/ai-plugin.json"));

// Register authenticated OpenAPI skills with the planner's kernel
// if the request includes an auth header for an OpenAPI skill.
// Else, don't register the skill as it'll fail on auth.
if (openApiSkillsAuthHeaders.GithubAuthentication != null)
{
var authenticationProvider = new BearerAuthenticationProvider(() => { return Task.FromResult(openApiSkillsAuthHeaders.GithubAuthentication); });
this._logger.LogInformation("Registering GitHub Skill");

var filePath = Path.Combine(Directory.GetCurrentDirectory(), @"Skills/OpenApiSkills/GitHubSkill/openapi.json");
var skill = await planner.Kernel.ImportOpenApiSkillFromFileAsync("GitHubSkill", filePath, authenticationProvider.AuthenticateRequestAsync);
}

planner.Kernel.ImportSkill(new Microsoft.SemanticKernel.CoreSkills.TextSkill(), "text");
planner.Kernel.ImportSkill(new Microsoft.SemanticKernel.CoreSkills.TimeSkill(), "time");
planner.Kernel.ImportSkill(new Microsoft.SemanticKernel.CoreSkills.MathSkill(), "math");
Expand Down
1 change: 1 addition & 0 deletions samples/apps/copilot-chat-app/webapi/CopilotChatApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

<ItemGroup>
<ProjectReference Include="..\..\..\..\dotnet\src\Connectors\Connectors.AI.OpenAI\Connectors.AI.OpenAI.csproj" />
<ProjectReference Include="..\..\..\..\dotnet\src\Skills\Skills.OpenAPI\Skills.OpenAPI.csproj" />
<ProjectReference Include="..\..\..\..\dotnet\src\Connectors\Connectors.Memory.Qdrant\Connectors.Memory.Qdrant.csproj" />
<ProjectReference Include="..\..\..\..\dotnet\src\Extensions\Planning.SequentialPlanner\Planning.SequentialPlanner.csproj" />
<ProjectReference Include="..\..\..\..\dotnet\src\SemanticKernel\SemanticKernel.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc;

namespace SemanticKernel.Service.Skills.OpenAPI.Authentication;

/// /// <summary>
/// Represents the authentication headers for imported OpenAPI Plugin Skills.
/// </summary>
public class OpenApiSkillsAuthHeaders
{
/// <summary>
/// Gets or sets the MS Graph authentication header value.
/// </summary>
[FromHeader(Name = "x-sk-copilot-graph-auth")]
public string? GraphAuthentication { get; set; }

/// <summary>
/// Gets or sets the Jira authentication header value.
/// </summary>
[FromHeader(Name = "x-sk-copilot-jira-auth")]
public string? JiraAuthentication { get; set; }

/// <summary>
/// Gets or sets the GitHub authentication header value.
/// </summary>
[FromHeader(Name = "x-sk-copilot-github-auth")]
public string? GithubAuthentication { get; set; }
}

0 comments on commit 7d5c59d

Please sign in to comment.