Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
<PackageVersion Include="Prompty.Core" Version="0.2.3-beta" />
<PackageVersion Include="PuppeteerSharp" Version="20.0.5" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.6.1" />
<PackageVersion Include="System.IO.Packaging" Version="8.0.1" />
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="10.0.0-preview.5.25277.114" />
<PackageVersion Include="System.Memory.Data" Version="8.0.1" />
Expand Down Expand Up @@ -144,7 +144,7 @@
<PackageVersion Include="DuckDB.NET.Data.Full" Version="1.2.0" />
<PackageVersion Include="DuckDB.NET.Data" Version="1.1.3" />
<PackageVersion Include="MongoDB.Driver" Version="2.30.0" />
<PackageVersion Include="Microsoft.Graph" Version="4.51.0" />
<PackageVersion Include="Microsoft.Graph" Version="5.90.0" />
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
<PackageVersion Include="Microsoft.OpenApi.ApiManifest" Version="0.5.6-preview" />
Expand Down
61 changes: 61 additions & 0 deletions dotnet/samples/Concepts/Plugins/MsGraph_CalendarPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Text.Json;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.MsGraph;
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;

namespace Plugins;

/// <summary>
/// This example shows how to use Microsoft Graph Plugin
/// These examples require a valid Microsoft account and delegated/application access for the Microsoft Graph used resources.
/// </summary>
public class MsGraph_CalendarPlugin(ITestOutputHelper output) : BaseTest(output)
{
private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true };

/// <summary>Shows how to use Microsoft Graph Calendar Plugin with AI Models.</summary>
[Fact]
public async Task UsingWithAIModel()
{
// Setup the Kernel
Kernel kernel = Kernel.CreateBuilder()
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
.Build();

using var graphClient = GetGraphClient();

var calendarConnector = new OutlookCalendarConnector(graphClient);

// Add the plugin to the Kernel
var graphPlugin = kernel.Plugins.AddFromObject(new CalendarPlugin(calendarConnector, jsonSerializerOptions: s_options));

var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };

string Prompt = $"""
1. Show me the next 10 calendar events I have
2. If I don't have any event named "Semantic Kernel", please create a new event named "Semantic Kernel"
starting at {DateTimeOffset.Now.AddHours(1)} with 1 hour of duration.
""";

// Invoke the OneDrive plugin multiple times
var result = await kernel.InvokePromptAsync(Prompt, new(settings));

Console.WriteLine(result);
}

private static GraphServiceClient GetGraphClient()
{
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
ClientId = TestConfiguration.MSGraph.ClientId,
TenantId = TestConfiguration.MSGraph.TenantId,
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
});

return new GraphServiceClient(credential);
}
}
58 changes: 58 additions & 0 deletions dotnet/samples/Concepts/Plugins/MsGraph_EmailPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) Microsoft. All rights reserved.

using Azure.Identity;
using Microsoft.Graph;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;

namespace Plugins;

/// <summary>
/// This example shows how to use Microsoft Graph Plugin
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
/// </summary>
public class MsGraph_EmailPlugin(ITestOutputHelper output) : BaseTest(output)
{
/// <summary>Shows how to use Microsoft Graph Email Plugin with AI Models.</summary>
[Fact]
public async Task EmailPlugin_SendEmailToMyself()
{
// Setup the Kernel
Kernel kernel = Kernel.CreateBuilder()
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
.Build();

using var graphClient = GetGraphClient();

var emailConnector = new OutlookMailConnector(graphClient);

// Add the plugin to the Kernel
var graphPlugin = kernel.Plugins.AddFromObject(new Microsoft.SemanticKernel.Plugins.MsGraph.EmailPlugin(emailConnector));

var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };

const string Prompt = """
Using the tools available, please do the following:
1. Get my email address
2. Send an email to myself with the subject "FYI" and content "This is a very important email"
3. List 10 of my email messages
""";

// Invoke the Graph plugin with a prompt
var result = await kernel.InvokePromptAsync(Prompt, new(settings));

Console.WriteLine(result);
}

private static GraphServiceClient GetGraphClient()
{
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
ClientId = TestConfiguration.MSGraph.ClientId,
TenantId = TestConfiguration.MSGraph.TenantId,
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
});

return new GraphServiceClient(credential);
}
}
59 changes: 59 additions & 0 deletions dotnet/samples/Concepts/Plugins/MsGraph_OneDrivePlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft. All rights reserved.

using Azure.Identity;
using Microsoft.Graph;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.MsGraph;
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;

namespace Plugins;

/// <summary>
/// This example shows how to use Microsoft Graph Plugin
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
/// </summary>
public class MsGraph_OneDrivePlugin(ITestOutputHelper output) : BaseTest(output)
{
/// <summary>Shows how to use Microsoft Graph OneDrive Plugin with AI Models.</summary>
[Fact]
public async Task UsingWithAIModel()
{
// Setup the Kernel
Kernel kernel = Kernel.CreateBuilder()
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
.Build();

using var graphClient = GetGraphClient();
var connector = new OneDriveConnector(graphClient);

// Add the plugin to the Kernel
var graphPlugin = kernel.Plugins.AddFromObject(new CloudDrivePlugin(connector));

var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };

const string Prompt = """
I need you to do the following things with the tools available:
1. Update the current file: "Resources/travelinfo.txt" to my OneDrive into the "Test" folder.
2. Generate a OneDrive Link for sharing the file
3. Summarize for me the contents of the uploaded file
4. Show me the generated shared link.
""";

// Invoke the OneDrive plugin multiple times
var result = await kernel.InvokePromptAsync(Prompt, new(settings));

Console.WriteLine($"Assistant: {result}");
}

private static GraphServiceClient GetGraphClient()
{
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
ClientId = TestConfiguration.MSGraph.ClientId,
TenantId = TestConfiguration.MSGraph.TenantId,
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
});

return new GraphServiceClient(credential);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Text.Json;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.MsGraph;
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;

namespace Plugins;

/// <summary>
/// This example shows how to use Microsoft Graph Plugin
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
/// </summary>
public class MsGraph_OrganizationHierarchyPlugin(ITestOutputHelper output) : BaseTest(output)
{
private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true };

/// <summary>Shows how to use Microsoft Graph Organization Hierarchy Plugin with AI Models.</summary>
[Fact]
public async Task UsingWithAIModel()
{
// Setup the Kernel
Kernel kernel = Kernel.CreateBuilder()
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
.Build();

using var graphClient = GetGraphClient();
var connector = new OrganizationHierarchyConnector(graphClient);

// Add the plugin to the Kernel
var graphPlugin = kernel.Plugins.AddFromObject(new OrganizationHierarchyPlugin(connector, s_options));

var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };

const string Prompt = "I need you to show my manager details as well as my direct reports using the tools available:";

// Invoke the OneDrive plugin multiple times
var result = await kernel.InvokePromptAsync(Prompt, new(settings));

Console.WriteLine($"Assistant: {result}");
}

private static GraphServiceClient GetGraphClient()
{
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
ClientId = TestConfiguration.MSGraph.ClientId,
TenantId = TestConfiguration.MSGraph.TenantId,
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
});

return new GraphServiceClient(credential);
}
}
59 changes: 59 additions & 0 deletions dotnet/samples/Concepts/Plugins/MsGraph_TaskListPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Text.Json;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.MsGraph;
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;

namespace Plugins;

/// <summary>
/// This example shows how to use Microsoft Graph Plugin
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
/// </summary>
public class MsGraph_TaskListPlugin(ITestOutputHelper output) : BaseTest(output)
{
private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true };

/// <summary>Shows how to use Microsoft Graph To-Do Tasks Plugin with AI Models.</summary>
[Fact]
public async Task UsingWithAIModel()
{
// Setup the Kernel
Kernel kernel = Kernel.CreateBuilder()
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
.Build();

using var graphClient = GetGraphClient();
var connector = new MicrosoftToDoConnector(graphClient);

// Add the plugin to the Kernel
var graphPlugin = kernel.Plugins.AddFromObject(new TaskListPlugin(connector, jsonSerializerOptions: s_options));

var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };

const string Prompt = """
1. Show me all the tasks I have
3. If I don't have a task named "Semantic Kernel", please create one
""";

// Invoke the OneDrive plugin multiple times
var result = await kernel.InvokePromptAsync(Prompt, new(settings));

Console.WriteLine($"Assistant: {result}");
}

private static GraphServiceClient GetGraphClient()
{
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
ClientId = TestConfiguration.MSGraph.ClientId,
TenantId = TestConfiguration.MSGraph.TenantId,
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
});

return new GraphServiceClient(credential);
}
}
5 changes: 5 additions & 0 deletions dotnet/samples/Concepts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ dotnet test -l "console;verbosity=detailed" --filter "FullyQualifiedName=ChatCom
- [DescribeAllPluginsAndFunctions](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/DescribeAllPluginsAndFunctions.cs)
- [GroundednessChecks](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/GroundednessChecks.cs)
- [ImportPluginFromGrpc](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/ImportPluginFromGrpc.cs)
- [MsGraph_CalendarPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_CalendarPlugin.cs)
- [MsGraph_EmailPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_EmailPlugin.cs)
- [MsGraph_ContactsPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_ContactsPlugin.cs)
- [MsGraph_DrivePlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_DrivePlugin.cs)
- [MsGraph_TasksPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_TasksPlugin.cs)
- [TransformPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/TransformPlugin.cs)
- [CopilotAgentBasedPlugins](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CopilotAgentBasedPlugins.cs)
- [WebPlugins](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/WebPlugins.cs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<ProjectReference Include="..\..\Extensions\PromptTemplates.Liquid\PromptTemplates.Liquid.csproj" />
<ProjectReference Include="..\..\SemanticKernel.Core\SemanticKernel.Core.csproj" />
<PackageReference Include="Prompty.Core" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" />
</ItemGroup>
</Project>
10 changes: 7 additions & 3 deletions dotnet/src/Plugins/Plugins.MsGraph/CalendarPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public sealed class CalendarPlugin
{
private readonly ICalendarConnector _connector;
private readonly ILogger _logger;
private readonly JsonSerializerOptions? _jsonSerializerOptions;
private static readonly JsonSerializerOptions s_options = new()
{
WriteIndented = false,
Expand All @@ -34,10 +35,13 @@ public sealed class CalendarPlugin
/// </summary>
/// <param name="connector">Calendar connector.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use for logging. If null, no logging will be performed.</param>
public CalendarPlugin(ICalendarConnector connector, ILoggerFactory? loggerFactory = null)
/// <param name="jsonSerializerOptions">The <see cref="JsonSerializerOptions"/> to use for serialization. If null, default options will be used.</param>
public CalendarPlugin(ICalendarConnector connector, ILoggerFactory? loggerFactory = null, JsonSerializerOptions? jsonSerializerOptions = null)
{
Ensure.NotNull(connector, nameof(connector));

this._jsonSerializerOptions = jsonSerializerOptions ?? s_options;

this._connector = connector;
this._logger = loggerFactory?.CreateLogger(typeof(CalendarPlugin)) ?? NullLogger.Instance;
}
Expand Down Expand Up @@ -87,13 +91,13 @@ public async Task<string> GetCalendarEventsAsync(

const string SelectString = "start,subject,organizer,location";

IEnumerable<CalendarEvent> events = await this._connector.GetEventsAsync(
IEnumerable<CalendarEvent>? events = await this._connector.GetEventsAsync(
top: maxResults,
skip: skip,
select: SelectString,
cancellationToken
).ConfigureAwait(false);

return JsonSerializer.Serialize(value: events, options: s_options);
return JsonSerializer.Serialize(value: events, options: this._jsonSerializerOptions);
}
}
10 changes: 8 additions & 2 deletions dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ public CloudDrivePlugin(ICloudDriveConnector connector, ILoggerFactory? loggerFa
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <returns>A string containing the file content.</returns>
[KernelFunction, Description("Get the contents of a file in a cloud drive.")]
public async Task<string> GetFileContentAsync(
public async Task<string?> GetFileContentAsync(
[Description("Path to file")] string filePath,
CancellationToken cancellationToken = default)
{
this._logger.LogDebug("Getting file content for '{0}'", filePath);
Stream fileContentStream = await this._connector.GetFileContentStreamAsync(filePath, cancellationToken).ConfigureAwait(false);
Stream? fileContentStream = await this._connector.GetFileContentStreamAsync(filePath, cancellationToken).ConfigureAwait(false);

if (fileContentStream is null)
{
this._logger.LogDebug("File content stream for '{0}' is null", filePath);
return null;
}

using StreamReader sr = new(fileContentStream);
return await sr.ReadToEndAsync(
Expand Down
Loading
Loading