Skip to content

Commit

Permalink
Merge branch 'microsoft:main' into update-modelid
Browse files Browse the repository at this point in the history
  • Loading branch information
SandraAhlgrimm committed Jan 17, 2024
2 parents 355eb68 + fe23d41 commit c87e45e
Show file tree
Hide file tree
Showing 149 changed files with 5,194 additions and 1,618 deletions.
54 changes: 54 additions & 0 deletions .github/workflows/check-coverage.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
param (
[string]$JsonReportPath,
[double]$CoverageThreshold
)

$jsonContent = Get-Content $JsonReportPath -Raw | ConvertFrom-Json
$coverageBelowThreshold = $false

function Get-FormattedValue($number) {
$formattedNumber = "{0:N1}" -f $number
$icon = if ($number -ge $CoverageThreshold) { '' } else { '' }

return "$formattedNumber% $icon"
}

$lineCoverage = $jsonContent.summary.linecoverage
$branchCoverage = $jsonContent.summary.branchcoverage

if ($lineCoverage -lt $CoverageThreshold -or $branchCoverage -lt $CoverageThreshold) {
$coverageBelowThreshold = $true
}

$totalTableData = [PSCustomObject]@{
'Metric' = 'Total Coverage'
'Line Coverage' = Get-FormattedValue $lineCoverage
'Branch Coverage' = Get-FormattedValue $branchCoverage
}

$totalTableData | Format-Table -AutoSize

$assemblyTableData = @()

foreach ($assembly in $jsonContent.coverage.assemblies) {
$assemblyName = $assembly.name
$assemblyLineCoverage = $assembly.coverage
$assemblyBranchCoverage = $assembly.branchcoverage

if ($assemblyLineCoverage -lt $CoverageThreshold -or $assemblyBranchCoverage -lt $CoverageThreshold) {
$coverageBelowThreshold = $true
}

$assemblyTableData += [PSCustomObject]@{
'Assembly Name' = $assemblyName
'Line' = Get-FormattedValue $assemblyLineCoverage
'Branch' = Get-FormattedValue $assemblyBranchCoverage
}
}

$assemblyTableData | Format-Table -AutoSize

if ($coverageBelowThreshold) {
Write-Host "Code coverage is lower than defined threshold: $CoverageThreshold. Stopping the task."
exit 1
}
19 changes: 18 additions & 1 deletion .github/workflows/dotnet-build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ on:
merge_group:
branches: ["main"]

env:
COVERAGE_THRESHOLD: 80

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
Expand Down Expand Up @@ -82,7 +85,7 @@ jobs:
run: |
export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | grep -v -E "(Planners.Core.UnitTests.csproj|Experimental.Orchestration.Flow.UnitTests.csproj|Experimental.Assistants.UnitTests.csproj)" | tr '\n' ' ')
for project in $UT_PROJECTS; do
dotnet test -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx
dotnet test -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/"
done
- name: Run Integration Tests
Expand All @@ -109,6 +112,20 @@ jobs:
Bing__ApiKey: ${{ secrets.BING__APIKEY }}
OpenAI__ApiKey: ${{ secrets.OPENAI__APIKEY }}

# Generate test reports and check coverage
- name: Generate test reports
uses: danielpalme/ReportGenerator-GitHub-Action@5.2.0
with:
reports: "./TestResults/Coverage/**/coverage.cobertura.xml"
targetdir: "./TestResults/Reports"
reporttypes: "JsonSummary"
# Report for production packages only
assemblyfilters: "+Microsoft.SemanticKernel.Abstractions;+Microsoft.SemanticKernel.Core;+Microsoft.SemanticKernel.PromptTemplates.Handlebars;+Microsoft.SemanticKernel.Connectors.OpenAI;+Microsoft.SemanticKernel.Yaml;"

- name: Check coverage
shell: pwsh
run: .github/workflows/check-coverage.ps1 -JsonReportPath "TestResults/Reports/Summary.json" -CoverageThreshold $env:COVERAGE_THRESHOLD

# This final job is required to satisfy the merge queue. It must only run (or succeed) if no tests failed
dotnet-build-and-test-check:
if: always()
Expand Down
2 changes: 0 additions & 2 deletions dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
<PackageVersion Include="xretry" Version="1.9.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
<PackageVersion Include="Polly" Version="8.2.0" />
<!-- Plugins -->
<PackageVersion Include="DocumentFormat.OpenXml" Version="3.0.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.0" />
Expand All @@ -66,7 +65,6 @@
<PackageVersion Include="Grpc.Net.Client" Version="2.60.0" />
<PackageVersion Include="protobuf-net" Version="3.2.30" />
<PackageVersion Include="protobuf-net.Reflection" Version="3.2.12" />
<PackageVersion Include="CoreCLR-NCalc" Version="2.2.113" />
<PackageVersion Include="YamlDotNet" Version="13.7.1" />
<!-- Memory stores -->
<PackageVersion Include="Pgvector" Version="0.2.0" />
Expand Down
14 changes: 6 additions & 8 deletions dotnet/SK-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System", "System", "{3CDE10
src\InternalUtilities\src\System\EnvExtensions.cs = src\InternalUtilities\src\System\EnvExtensions.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.Core", "src\Plugins\Plugins.Core\Plugins.Core.csproj", "{0D0C4DAD-E6BC-4504-AE3A-EEA4E35920C1}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Type", "Type", "{E85EA4D0-BB7E-4DFD-882F-A76EB8C0B8FF}"
ProjectSection(SolutionItems) = preProject
src\InternalUtilities\src\Type\TypeExtensions.cs = src\InternalUtilities\src\Type\TypeExtensions.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NCalcPlugins", "samples\NCalcPlugins\NCalcPlugins.csproj", "{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.Core", "src\Plugins\Plugins.Core\Plugins.Core.csproj", "{0D0C4DAD-E6BC-4504-AE3A-EEA4E35920C1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelemetryExample", "samples\TelemetryExample\TelemetryExample.csproj", "{C754950A-E16C-4F96-9CC7-9328E361B5AF}"
EndProject
Expand Down Expand Up @@ -353,11 +356,6 @@ Global
{0D0C4DAD-E6BC-4504-AE3A-EEA4E35920C1}.Publish|Any CPU.Build.0 = Publish|Any CPU
{0D0C4DAD-E6BC-4504-AE3A-EEA4E35920C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D0C4DAD-E6BC-4504-AE3A-EEA4E35920C1}.Release|Any CPU.Build.0 = Release|Any CPU
{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA}.Publish|Any CPU.ActiveCfg = Release|Any CPU
{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA}.Release|Any CPU.Build.0 = Release|Any CPU
{C754950A-E16C-4F96-9CC7-9328E361B5AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C754950A-E16C-4F96-9CC7-9328E361B5AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C754950A-E16C-4F96-9CC7-9328E361B5AF}.Publish|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -500,8 +498,8 @@ Global
{B00AD427-0047-4850-BEF9-BA8237EA9D8B} = {958AD708-F048-4FAF-94ED-D2F2B92748B9}
{1C19D805-3573-4477-BF07-40180FCDE1BD} = {958AD708-F048-4FAF-94ED-D2F2B92748B9}
{3CDE10B2-AE8F-4FC4-8D55-92D4AD32E144} = {958AD708-F048-4FAF-94ED-D2F2B92748B9}
{E85EA4D0-BB7E-4DFD-882F-A76EB8C0B8FF} = {958AD708-F048-4FAF-94ED-D2F2B92748B9}
{0D0C4DAD-E6BC-4504-AE3A-EEA4E35920C1} = {D6D598DF-C17C-46F4-B2B9-CDE82E2DE132}
{E6EDAB8F-3406-4DBF-9AAB-DF40DC2CA0FA} = {FA3720F1-C99A-49B2-9577-A940257098BF}
{C754950A-E16C-4F96-9CC7-9328E361B5AF} = {FA3720F1-C99A-49B2-9577-A940257098BF}
{E07608CC-D710-4655-BB9E-D22CF3CDD193} = {24503383-A8C4-4255-9998-28D70FE8E99A}
{D6D598DF-C17C-46F4-B2B9-CDE82E2DE132} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0}
Expand Down
60 changes: 60 additions & 0 deletions dotnet/code-coverage.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# This script is for local use to analyze code coverage in more detail using HTML report.

Param(
[switch]$ProdPackagesOnly = $false
)

# Generate a timestamp for the current date and time
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"

# Define paths
$scriptPath = Get-Item -Path $PSScriptRoot
$coverageOutputPath = Join-Path $scriptPath "TestResults\Coverage\$timestamp"
$reportOutputPath = Join-Path $scriptPath "TestResults\Reports\$timestamp"

# Create output directories
New-Item -ItemType Directory -Force -Path $coverageOutputPath
New-Item -ItemType Directory -Force -Path $reportOutputPath

# Find tests for projects ending with 'UnitTests.csproj'
$testProjects = Get-ChildItem $scriptPath -Filter "*UnitTests.csproj" -Recurse

foreach ($project in $testProjects) {
$testProjectPath = $project.FullName
Write-Host "Running tests for project: $($testProjectPath)"

# Run tests
dotnet test $testProjectPath `
--collect:"XPlat Code Coverage" `
--results-directory:$coverageOutputPath `

}

# Install required tools
& dotnet tool install -g coverlet.console
& dotnet tool install -g dotnet-reportgenerator-globaltool

# Generate HTML report
if ($ProdPackagesOnly) {
$assemblies = @(
"+Microsoft.SemanticKernel.Abstractions",
"+Microsoft.SemanticKernel.Core",
"+Microsoft.SemanticKernel.PromptTemplates.Handlebars",
"+Microsoft.SemanticKernel.Connectors.OpenAI",
"+Microsoft.SemanticKernel.Yaml"
)

$assemblyFilters = $assemblies -join ";"

# Generate report for production assemblies only
& reportgenerator -reports:"$coverageOutputPath/**/coverage.cobertura.xml" -targetdir:$reportOutputPath -reporttypes:Html -assemblyfilters:$assemblyFilters
}
else {
& reportgenerator -reports:"$coverageOutputPath/**/coverage.cobertura.xml" -targetdir:$reportOutputPath -reporttypes:Html
}

Write-Host "Code coverage report generated at: $reportOutputPath"

# Open report
$reportIndexHtml = Join-Path $reportOutputPath "index.html"
Invoke-Item -Path $reportIndexHtml
3 changes: 2 additions & 1 deletion dotnet/samples/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ resharper_condition_is_always_true_or_false_according_to_nullable_api_contract_h
resharper_inconsistent_naming_highlighting = none # InconsistentNaming
resharper_equal_expression_comparison_highlighting = none # EqualExpressionComparison
resharper_check_namespace_highlighting = none # CheckNamespace
resharper_arrange_object_creation_when_type_not_evident_highlighting = none # Disable "Arrange object creation when type is not evident" highlighting
resharper_arrange_object_creation_when_type_not_evident_highlighting = none # Disable "Arrange object creation when type is not evident" highlighting
resharper_arrange_this_qualifier_highlighting = none # Disable "Arrange 'this.' qualifier" highlighting
47 changes: 47 additions & 0 deletions dotnet/samples/KernelSyntaxExamples/BaseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft. All rights reserved.

using Microsoft.Extensions.Configuration;
using RepoUtils;
using Xunit.Abstractions;

namespace Examples;

public abstract class BaseTest
{
protected ITestOutputHelper Output { get; }

protected BaseTest(ITestOutputHelper output)
{
this.Output = output;
LoadUserSecrets();
}

private static void LoadUserSecrets()
{
IConfigurationRoot configRoot = new ConfigurationBuilder()
.AddJsonFile("appsettings.Development.json", true)
.AddEnvironmentVariables()
.AddUserSecrets<Env>()
.Build();

TestConfiguration.Initialize(configRoot);
}

/// <summary>
/// This method can be substituted by Console.WriteLine when used in Console apps.
/// </summary>
/// <param name="target">Target object to write</param>
protected void WriteLine(object? target = null)
{
this.Output.WriteLine(target ?? string.Empty);
}

/// <summary>
/// Current interface ITestOutputHelper does not have a Write method. This extension method adds it to make it analogous to Console.Write when used in Console apps.
/// </summary>
/// <param name="target">Target object to write</param>
protected void Write(object? target = null)
{
this.Output.WriteLine(target ?? string.Empty);
}
}
18 changes: 13 additions & 5 deletions dotnet/samples/KernelSyntaxExamples/Example01_MethodFunctions.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Threading.Tasks;
using Microsoft.SemanticKernel.Plugins.Core;
using Xunit;
using Xunit.Abstractions;

public static class Example01_MethodFunctions
namespace Examples;

public class Example01_MethodFunctions : BaseTest
{
public static Task RunAsync()
[Fact]
public Task RunAsync()
{
Console.WriteLine("======== Functions ========");
this.WriteLine("======== Functions ========");

// Load native plugin
var text = new TextPlugin();

// Use function without kernel
var result = text.Uppercase("ciao!");

Console.WriteLine(result);
this.WriteLine(result);

return Task.CompletedTask;
}

public Example01_MethodFunctions(ITestOutputHelper output) : base(output)
{
}
}
20 changes: 14 additions & 6 deletions dotnet/samples/KernelSyntaxExamples/Example03_Arguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
using System.Threading.Tasks;
using Microsoft.SemanticKernel;
using Plugins;
using Xunit;
using Xunit.Abstractions;

namespace Examples;
// This example shows how to use kernel arguments when invoking functions.
public static class Example03_Arguments
public class Example03_Arguments : BaseTest
{
public static async Task RunAsync()
[Fact]
public async Task RunAsync()
{
Console.WriteLine("======== Arguments ========");
this.WriteLine("======== Arguments ========");

Kernel kernel = new();
var textPlugin = kernel.ImportPluginFromType<StaticTextPlugin>();
Expand All @@ -26,16 +30,20 @@ public static async Task RunAsync()

// Specify and get the value type as generic parameter
string? resultValue = await kernel.InvokeAsync<string>(textPlugin["AppendDay"], arguments);
Console.WriteLine($"string -> {resultValue}");
this.WriteLine($"string -> {resultValue}");

// If you need to access the result metadata, you can use the non-generic version to get the FunctionResult
FunctionResult functionResult = await kernel.InvokeAsync(textPlugin["AppendDay"], arguments);
var metadata = functionResult.Metadata;

// Specify the type from the FunctionResult
Console.WriteLine($"FunctionResult.GetValue<string>() -> {functionResult.GetValue<string>()}");
this.WriteLine($"FunctionResult.GetValue<string>() -> {functionResult.GetValue<string>()}");

// FunctionResult.ToString() automatically converts the result to string
Console.WriteLine($"FunctionResult.ToString() -> {functionResult}");
this.WriteLine($"FunctionResult.ToString() -> {functionResult}");
}

public Example03_Arguments(ITestOutputHelper output) : base(output)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@
using System.Threading.Tasks;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Xunit;
using Xunit.Abstractions;

public static class Example05_InlineFunctionDefinition
namespace Examples;

public class Example05_InlineFunctionDefinition : BaseTest
{
public static async Task RunAsync()
[Fact]
public async Task RunAsync()
{
Console.WriteLine("======== Inline Function Definition ========");
this.WriteLine("======== Inline Function Definition ========");

string openAIModelId = TestConfiguration.OpenAI.ChatModelId;
string openAIApiKey = TestConfiguration.OpenAI.ApiKey;

if (openAIModelId is null || openAIApiKey is null)
{
Console.WriteLine("OpenAI credentials not found. Skipping example.");
this.WriteLine("OpenAI credentials not found. Skipping example.");
return;
}

Expand Down Expand Up @@ -49,14 +54,18 @@ Be creative and be funny. Let your imagination run wild.
var excuseFunction = kernel.CreateFunctionFromPrompt(promptTemplate, new OpenAIPromptExecutionSettings() { MaxTokens = 100, Temperature = 0.4, TopP = 1 });

var result = await kernel.InvokeAsync(excuseFunction, new() { ["input"] = "I missed the F1 final race" });
Console.WriteLine(result.GetValue<string>());
this.WriteLine(result.GetValue<string>());

result = await kernel.InvokeAsync(excuseFunction, new() { ["input"] = "sorry I forgot your birthday" });
Console.WriteLine(result.GetValue<string>());
this.WriteLine(result.GetValue<string>());

var fixedFunction = kernel.CreateFunctionFromPrompt($"Translate this date {DateTimeOffset.Now:f} to French format", new OpenAIPromptExecutionSettings() { MaxTokens = 100 });

result = await kernel.InvokeAsync(fixedFunction);
Console.WriteLine(result.GetValue<string>());
this.WriteLine(result.GetValue<string>());
}

public Example05_InlineFunctionDefinition(ITestOutputHelper output) : base(output)
{
}
}
Loading

0 comments on commit c87e45e

Please sign in to comment.