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
2 changes: 1 addition & 1 deletion dotnet/samples/Demos/CodeInterpreterPlugin/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

var apiKey = configuration["OpenAI:ApiKey"];
var modelId = configuration["OpenAI:ChatModelId"];
var endpoint = configuration["AzureContainerApps:Endpoint"];
var endpoint = configuration["AzureContainerAppSessionPool:Endpoint"];

// Cached token for the Azure Container Apps service
string? cachedToken = null;
Expand Down
12 changes: 10 additions & 2 deletions dotnet/samples/Demos/CodeInterpreterPlugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

This example demonstrates how to do AI Code Interpretetion using a Plugin with Azure Container Apps to execute python code in a container.

## Create and Configure Azure Container App Session Pool

1. Create a new Container App Session Pool using the Azure CLI or Azure Portal.
2. Specify "Python code interpreter" as the pool type.
3. Add the following roles to the user that will be used to access the session pool:
- The `Azure ContainerApps Session Executor` role to be able to create and manage sessions.
- The `Container Apps SessionPools Contributor` role to be able to work with files.

## Configuring Secrets

The example require credentials to access OpenAI and Azure Container Apps (ACA)
Expand All @@ -16,7 +24,7 @@ dotnet user-secrets init
dotnet user-secrets set "OpenAI:ApiKey" "..."
dotnet user-secrets set "OpenAI:ChatModelId" "gpt-3.5-turbo" # or any other function callable model.

dotnet user-secrets set "AzureContainerApps:Endpoint" " .. endpoint .. "
dotnet user-secrets set "AzureContainerAppSessionPool:Endpoint" " .. endpoint .. "
```

### To set your secrets with environment variables
Expand All @@ -29,7 +37,7 @@ OpenAI__ApiKey
OpenAI__ChatModelId

# Azure Container Apps
AzureContainerApps__Endpoint
AzureContainerAppSessionPool__Endpoint
```

### Usage Example
Expand Down
8 changes: 7 additions & 1 deletion dotnet/src/IntegrationTests/IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Testcontainers.Milvus" />
<PackageReference Include="Testcontainers.MongoDB"/>
<PackageReference Include="Testcontainers.MongoDB" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Agents\AzureAI\Agents.AzureAI.csproj" />
Expand Down Expand Up @@ -109,6 +109,12 @@
</ItemGroup>

<ItemGroup>
<None Update="TestData\SessionsPythonPlugin\file_to_upload_2.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestData\SessionsPythonPlugin\file_to_upload_1.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="testsettings.development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Threading.Tasks;
using Xunit;
using Microsoft.SemanticKernel.Plugins.Core.CodeInterpreter;
using Microsoft.Extensions.Configuration;
using SemanticKernel.IntegrationTests.TestSettings;
using System.Net.Http;
using Azure.Identity;
using Azure.Core;
using System.Collections.Generic;

namespace SemanticKernel.IntegrationTests.Plugins.Core;

public sealed class SessionsPythonPluginTests : IDisposable
{
private const string SkipReason = "For manual verification only";

private readonly SessionsPythonSettings _settings;
private readonly HttpClientFactory _httpClientFactory;
private readonly SessionsPythonPlugin _sut;

public SessionsPythonPluginTests()
{
var configurationRoot = new ConfigurationBuilder()
.AddJsonFile(path: "testsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile(path: "testsettings.development.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddUserSecrets<SessionsPythonPluginTests>()
.Build();

var _configuration = configurationRoot
.GetSection("AzureContainerAppSessionPool")
.Get<AzureContainerAppSessionPoolConfiguration>()!;

this._settings = new(sessionId: Guid.NewGuid().ToString(), endpoint: new Uri(_configuration.Endpoint))
{
CodeExecutionType = SessionsPythonSettings.CodeExecutionTypeSetting.Synchronous,
CodeInputType = SessionsPythonSettings.CodeInputTypeSetting.Inline
};

this._httpClientFactory = new HttpClientFactory();

this._sut = new SessionsPythonPlugin(this._settings, this._httpClientFactory, GetAuthTokenAsync);
}

[Fact(Skip = SkipReason)]
public async Task ItShouldUploadFileAsync()
{
// Act
var result = await this._sut.UploadFileAsync("test_file.txt", @"TestData\SessionsPythonPlugin\file_to_upload_1.txt");

// Assert
Assert.Equal("test_file.txt", result.Filename);
Assert.Equal(322, result.Size);
Assert.NotNull(result.LastModifiedTime);
Assert.Equal("/mnt/data/test_file.txt", result.FullPath);
}

[Fact(Skip = SkipReason)]
public async Task ItShouldDownloadFileAsync()
{
// Arrange
await this._sut.UploadFileAsync("test_file.txt", @"TestData\SessionsPythonPlugin\file_to_upload_1.txt");

// Act
var fileContent = await this._sut.DownloadFileAsync("test_file.txt");

// Assert
Assert.Equal(322, fileContent.Length);
}

[Fact(Skip = SkipReason)]
public async Task ItShouldListFilesAsync()
{
// Arrange
await this._sut.UploadFileAsync("test_file_1.txt", @"TestData\SessionsPythonPlugin\file_to_upload_1.txt");
await this._sut.UploadFileAsync("test_file_2.txt", @"TestData\SessionsPythonPlugin\file_to_upload_2.txt");

// Act
var files = await this._sut.ListFilesAsync();

// Assert
Assert.Equal(2, files.Count);

var firstFile = files[0];
Assert.Equal("test_file_1.txt", firstFile.Filename);
Assert.Equal(322, firstFile.Size);
Assert.NotNull(firstFile.LastModifiedTime);
Assert.Equal("/mnt/data/test_file_1.txt", firstFile.FullPath);

var secondFile = files[1];
Assert.Equal("test_file_2.txt", secondFile.Filename);
Assert.Equal(336, secondFile.Size);
Assert.NotNull(secondFile.LastModifiedTime);
Assert.Equal("/mnt/data/test_file_2.txt", secondFile.FullPath);
}

[Fact(Skip = SkipReason)]
public async Task ItShouldExecutePythonCodeAsync()
{
// Arrange
string code = "result = 5 + 3\nprint(result)";

// Act
var result = await this._sut.ExecuteCodeAsync(code);

// Assert
Assert.Contains("8", result);
Assert.Contains("Success", result);
}

/// <summary>
/// Acquires authentication token for the Azure Container App Session pool.
/// </summary>
private static async Task<string> GetAuthTokenAsync()
{
string resource = "https://acasessions.io/.default";

var credential = new AzureCliCredential();

AccessToken token = await credential.GetTokenAsync(new Azure.Core.TokenRequestContext([resource])).ConfigureAwait(false);

return token.Token;
}

public void Dispose()
{
this._httpClientFactory.Dispose();
}

private sealed class HttpClientFactory : IHttpClientFactory, IDisposable
{
private readonly List<HttpClient> _httpClients = [];

public HttpClient CreateClient(string name)
{
var client = new HttpClient();
this._httpClients.Add(client);
return client;
}

public void Dispose()
{
this._httpClients.ForEach(client => client.Dispose());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Semantic Kernel

Semantic Kernel is an SDK that integrates Large Language Models (LLMs) like OpenAI, Azure OpenAI, and Hugging Face with conventional programming languages like C#, Python, and Java. Semantic Kernel achieves this by allowing you to define plugins that can be chained together in just a few lines of code.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Semantic Kernel is a software development kit (SDK) that seamlessly combines Large Language Models (LLMs) such as OpenAI, Azure OpenAI, and Hugging Face with traditional programming languages like C#, Python, and Java. It enables the creation of plugins that can be linked together with minimal code, facilitating efficient integration.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;

namespace SemanticKernel.IntegrationTests.TestSettings;

[SuppressMessage("Performance", "CA1812:Internal class that is apparently never instantiated",
Justification = "Configuration classes are instantiated through IConfiguration.")]
internal sealed class AzureContainerAppSessionPoolConfiguration(string endpoint)
{
public string Endpoint { get; set; } = endpoint;
}
Loading