Skip to content

Commit

Permalink
Merge branch 'main' into agents-nameonly-strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
crickman authored Dec 17, 2024
2 parents 64ff61d + 4a21254 commit 9d3bad9
Show file tree
Hide file tree
Showing 76 changed files with 6,407 additions and 184 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/python-test-coverage-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ on:
types:
- completed

permissions:
contents: read
pull-requests: write

jobs:
python-test-coverage-report:
runs-on: ubuntu-latest
Expand All @@ -25,10 +29,20 @@ jobs:
merge-multiple: true
- name: Display structure of downloaded files
run: ls
- name: Read and set PR number
# Need to read the PR number from the file saved in the previous workflow
# because the workflow_run event does not have access to the PR number
# The PR number is needed to post the comment on the PR
run: |
PR_NUMBER=$(cat pr_number)
echo "PR number: $PR_NUMBER"
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
- name: Pytest coverage comment
id: coverageComment
uses: MishaKav/pytest-coverage-comment@main
with:
github-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
issue-number: ${{ env.PR_NUMBER }}
pytest-coverage-path: python/python-coverage.txt
title: "Python Test Coverage Report"
badge-title: "Python Test Coverage"
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/python-test-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ jobs:
UV_PYTHON: "3.10"
steps:
- uses: actions/checkout@v4
# Save the PR number to a file since the workflow_run event
# in the coverage report workflow does not have access to it
- name: Save PR number
run: |
echo ${{ github.event.number }} > ./pr_number
- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
Expand All @@ -37,6 +42,7 @@ jobs:
path: |
python/python-coverage.txt
python/pytest.xml
python/pr_number
overwrite: true
retention-days: 1
if-no-files-found: error
2 changes: 1 addition & 1 deletion dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
<PackageVersion Include="Docker.DotNet" Version="3.125.15" />
<!-- Plugins -->
<PackageVersion Include="DocumentFormat.OpenXml" Version="3.1.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.10" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageVersion Include="DuckDB.NET.Data.Full" Version="1.1.2.1" />
<PackageVersion Include="DuckDB.NET.Data" Version="1.1.2.1" />
<PackageVersion Include="MongoDB.Driver" Version="2.30.0" />
Expand Down
9 changes: 9 additions & 0 deletions dotnet/SK-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AotCompatibility", "samples
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SemanticKernel.AotTests", "src\SemanticKernel.AotTests\SemanticKernel.AotTests.csproj", "{39EAB599-742F-417D-AF80-95F90376BB18}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Connectors.Postgres.UnitTests", "src\Connectors\Connectors.Postgres.UnitTests\Connectors.Postgres.UnitTests.csproj", "{232E1153-6366-4175-A982-D66B30AAD610}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Process.Utilities.UnitTests", "src\Experimental\Process.Utilities.UnitTests\Process.Utilities.UnitTests.csproj", "{DAC54048-A39A-4739-8307-EA5A291F2EA0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GettingStartedWithVectorStores", "samples\GettingStartedWithVectorStores\GettingStartedWithVectorStores.csproj", "{8C3DE41C-E2C8-42B9-8638-574F8946EB0E}"
Expand Down Expand Up @@ -1074,6 +1076,12 @@ Global
{6F591D05-5F7F-4211-9042-42D8BCE60415}.Publish|Any CPU.Build.0 = Debug|Any CPU
{6F591D05-5F7F-4211-9042-42D8BCE60415}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F591D05-5F7F-4211-9042-42D8BCE60415}.Release|Any CPU.Build.0 = Release|Any CPU
{232E1153-6366-4175-A982-D66B30AAD610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{232E1153-6366-4175-A982-D66B30AAD610}.Debug|Any CPU.Build.0 = Debug|Any CPU
{232E1153-6366-4175-A982-D66B30AAD610}.Publish|Any CPU.ActiveCfg = Debug|Any CPU
{232E1153-6366-4175-A982-D66B30AAD610}.Publish|Any CPU.Build.0 = Debug|Any CPU
{232E1153-6366-4175-A982-D66B30AAD610}.Release|Any CPU.ActiveCfg = Release|Any CPU
{232E1153-6366-4175-A982-D66B30AAD610}.Release|Any CPU.Build.0 = Release|Any CPU
{E82B640C-1704-430D-8D71-FD8ED3695468}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E82B640C-1704-430D-8D71-FD8ED3695468}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E82B640C-1704-430D-8D71-FD8ED3695468}.Publish|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -1311,6 +1319,7 @@ Global
{E82B640C-1704-430D-8D71-FD8ED3695468} = {5A7028A7-4DDF-4E4F-84A9-37CE8F8D7E89}
{6ECFDF04-2237-4A85-B114-DAA34923E9E6} = {5D4C0700-BBB5-418F-A7B2-F392B9A18263}
{39EAB599-742F-417D-AF80-95F90376BB18} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0}
{232E1153-6366-4175-A982-D66B30AAD610} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C}
{DAC54048-A39A-4739-8307-EA5A291F2EA0} = {0D8C6358-5DAA-4EA6-A924-C268A9A21BC9}
{8C3DE41C-E2C8-42B9-8638-574F8946EB0E} = {FA3720F1-C99A-49B2-9577-A940257098BF}
{DB58FDD0-308E-472F-BFF5-508BC64C727E} = {0D8C6358-5DAA-4EA6-A924-C268A9A21BC9}
Expand Down
3 changes: 3 additions & 0 deletions dotnet/samples/Concepts/Concepts.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Resources\Plugins\ApiManifestPlugins\**\apimanifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
34 changes: 34 additions & 0 deletions dotnet/samples/Concepts/Memory/OpenAI_EmbeddingGeneration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft. All rights reserved.

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Embeddings;
using xRetry;

#pragma warning disable format // Format item can be simplified
#pragma warning disable CA1861 // Avoid constant arrays as arguments

namespace Memory;

// The following example shows how to use Semantic Kernel with OpenAI.
public class OpenAI_EmbeddingGeneration(ITestOutputHelper output) : BaseTest(output)
{
[RetryFact(typeof(HttpOperationException))]
public async Task RunEmbeddingAsync()
{
Assert.NotNull(TestConfiguration.OpenAI.EmbeddingModelId);
Assert.NotNull(TestConfiguration.OpenAI.ApiKey);

IKernelBuilder kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddOpenAITextEmbeddingGeneration(
modelId: TestConfiguration.OpenAI.EmbeddingModelId!,
apiKey: TestConfiguration.OpenAI.ApiKey!);
Kernel kernel = kernelBuilder.Build();

var embeddingGenerator = kernel.GetRequiredService<ITextEmbeddingGenerationService>();

// Generate embeddings for the specified text.
var embeddings = await embeddingGenerator.GenerateEmbeddingsAsync(["Semantic Kernel is a lightweight, open-source development kit that lets you easily build AI agents and integrate the latest AI models into your C#, Python, or Java codebase."]);

Console.WriteLine($"Generated {embeddings.Count} embeddings for the provided text");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,51 @@ namespace Memory.VectorStoreFixtures;
/// </summary>
internal static class VectorStoreInfra
{
/// <summary>
/// Setup the postgres pgvector container by pulling the image and running it.
/// </summary>
/// <param name="client">The docker client to create the container with.</param>
/// <returns>The id of the container.</returns>
public static async Task<string> SetupPostgresContainerAsync(DockerClient client)
{
await client.Images.CreateImageAsync(
new ImagesCreateParameters
{
FromImage = "pgvector/pgvector",
Tag = "pg16",
},
null,
new Progress<JSONMessage>());

var container = await client.Containers.CreateContainerAsync(new CreateContainerParameters()
{
Image = "pgvector/pgvector:pg16",
HostConfig = new HostConfig()
{
PortBindings = new Dictionary<string, IList<PortBinding>>
{
{"5432", new List<PortBinding> {new() {HostPort = "5432" } }},
},
PublishAllPorts = true
},
ExposedPorts = new Dictionary<string, EmptyStruct>
{
{ "5432", default },
},
Env = new List<string>
{
"POSTGRES_USER=postgres",
"POSTGRES_PASSWORD=example",
},
});

await client.Containers.StartContainerAsync(
container.ID,
new ContainerStartParameters());

return container.ID;
}

/// <summary>
/// Setup the qdrant container by pulling the image and running it.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft. All rights reserved.

using Docker.DotNet;
using Npgsql;

namespace Memory.VectorStoreFixtures;

/// <summary>
/// Fixture to use for creating a Postgres container before tests and delete it after tests.
/// </summary>
public class VectorStorePostgresContainerFixture : IAsyncLifetime
{
private DockerClient? _dockerClient;
private string? _postgresContainerId;

public async Task InitializeAsync()
{
}

public async Task ManualInitializeAsync()
{
if (this._postgresContainerId == null)
{
// Connect to docker and start the docker container.
using var dockerClientConfiguration = new DockerClientConfiguration();
this._dockerClient = dockerClientConfiguration.CreateClient();
this._postgresContainerId = await VectorStoreInfra.SetupPostgresContainerAsync(this._dockerClient);

// Delay until the Postgres server is ready.
var connectionString = TestConfiguration.Postgres.ConnectionString;
var succeeded = false;
var attemptCount = 0;
while (!succeeded && attemptCount++ < 10)
{
try
{
NpgsqlDataSourceBuilder dataSourceBuilder = new(connectionString);
dataSourceBuilder.UseVector();
using var dataSource = dataSourceBuilder.Build();
NpgsqlConnection connection = await dataSource.OpenConnectionAsync().ConfigureAwait(false);

await using (connection)
{
// Create extension vector if it doesn't exist
await using (NpgsqlCommand command = new("CREATE EXTENSION IF NOT EXISTS vector", connection))
{
await command.ExecuteNonQueryAsync();
}
}
}
catch (Exception)
{
await Task.Delay(1000);
}
}
}
}

public async Task DisposeAsync()
{
if (this._dockerClient != null && this._postgresContainerId != null)
{
// Delete docker container.
await VectorStoreInfra.DeleteContainerAsync(this._dockerClient, this._postgresContainerId);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) Microsoft. All rights reserved.

using Azure.Identity;
using Memory.VectorStoreFixtures;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.AzureOpenAI;
using Microsoft.SemanticKernel.Connectors.Postgres;
using Npgsql;

namespace Memory;

/// <summary>
/// An example showing how to use common code, that can work with any vector database, with a Postgres database.
/// The common code is in the <see cref="VectorStore_VectorSearch_MultiStore_Common"/> class.
/// The common code ingests data into the vector store and then searches over that data.
/// This example is part of a set of examples each showing a different vector database.
///
/// For other databases, see the following classes:
/// <para><see cref="VectorStore_VectorSearch_MultiStore_AzureAISearch"/></para>
/// <para><see cref="VectorStore_VectorSearch_MultiStore_Redis"/></para>
/// <para><see cref="VectorStore_VectorSearch_MultiStore_InMemory"/></para>
///
/// To run this sample, you need a local instance of Docker running, since the associated fixture will try and start a Postgres container in the local docker instance.
/// </summary>
public class VectorStore_VectorSearch_MultiStore_Postgres(ITestOutputHelper output, VectorStorePostgresContainerFixture PostgresFixture) : BaseTest(output), IClassFixture<VectorStorePostgresContainerFixture>
{
[Fact]
public async Task ExampleWithDIAsync()
{
// Use the kernel for DI purposes.
var kernelBuilder = Kernel
.CreateBuilder();

// Register an embedding generation service with the DI container.
kernelBuilder.AddAzureOpenAITextEmbeddingGeneration(
deploymentName: TestConfiguration.AzureOpenAIEmbeddings.DeploymentName,
endpoint: TestConfiguration.AzureOpenAIEmbeddings.Endpoint,
credential: new AzureCliCredential());

// Initialize the Postgres docker container via the fixtures and register the Postgres VectorStore.
await PostgresFixture.ManualInitializeAsync();
kernelBuilder.Services.AddPostgresVectorStore(TestConfiguration.Postgres.ConnectionString);

// Register the test output helper common processor with the DI container.
kernelBuilder.Services.AddSingleton<ITestOutputHelper>(this.Output);
kernelBuilder.Services.AddTransient<VectorStore_VectorSearch_MultiStore_Common>();

// Build the kernel.
var kernel = kernelBuilder.Build();

// Build a common processor object using the DI container.
var processor = kernel.GetRequiredService<VectorStore_VectorSearch_MultiStore_Common>();

// Run the process and pass a key generator function to it, to generate unique record keys.
// The key generator function is required, since different vector stores may require different key types.
// E.g. Postgres supports Guid and ulong keys, but others may support strings only.
await processor.IngestDataAndSearchAsync("skglossaryWithDI", () => Guid.NewGuid());
}

[Fact]
public async Task ExampleWithoutDIAsync()
{
// Create an embedding generation service.
var textEmbeddingGenerationService = new AzureOpenAITextEmbeddingGenerationService(
TestConfiguration.AzureOpenAIEmbeddings.DeploymentName,
TestConfiguration.AzureOpenAIEmbeddings.Endpoint,
new AzureCliCredential());

// Initialize the Postgres docker container via the fixtures and construct the Postgres VectorStore.
await PostgresFixture.ManualInitializeAsync();
var dataSourceBuilder = new NpgsqlDataSourceBuilder(TestConfiguration.Postgres.ConnectionString);
dataSourceBuilder.UseVector();
await using var dataSource = dataSourceBuilder.Build();
var vectorStore = new PostgresVectorStore(dataSource);

// Create the common processor that works for any vector store.
var processor = new VectorStore_VectorSearch_MultiStore_Common(vectorStore, textEmbeddingGenerationService, this.Output);

// Run the process and pass a key generator function to it, to generate unique record keys.
// The key generator function is required, since different vector stores may require different key types.
// E.g. Postgres supports Guid and ulong keys, but others may support strings only.
await processor.IngestDataAndSearchAsync("skglossaryWithoutDI", () => Guid.NewGuid());
}
}
Loading

0 comments on commit 9d3bad9

Please sign in to comment.