Skip to content
Draft
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
1 change: 1 addition & 0 deletions dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<PackageVersion Include="FastBertTokenizer" Version="1.0.28" />
<PackageVersion Include="Google.Apis.Auth" Version="1.72.0" />
<PackageVersion Include="Google.Apis.CustomSearchAPI.v1" Version="1.68.0.3520" />
<PackageVersion Include="Google.GenAI" Version="0.6.0" />
<PackageVersion Include="Google.Protobuf" Version="3.32.1" />
<PackageVersion Include="Grpc.AspNetCore" Version="2.71.0" />
<PackageVersion Include="Grpc.AspNetCore.Server" Version="2.70.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
</PackageReference>
<PackageReference Include="System.Numerics.Tensors" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Google.GenAI" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using Google.GenAI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
Expand Down Expand Up @@ -113,4 +114,147 @@ public void GoogleAIEmbeddingGeneratorShouldBeRegisteredInServiceCollection()
Assert.NotNull(embeddingsGenerationService);
Assert.IsType<GoogleAIEmbeddingGenerator>(embeddingsGenerationService);
}

#if NET
[Fact]
public void GoogleGenAIChatClientShouldBeRegisteredInKernelServicesWithApiKey()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act
kernelBuilder.AddGoogleGenAIChatClient("modelId", "apiKey");
var kernel = kernelBuilder.Build();

// Assert
var chatClient = kernel.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}

[Fact]
public void GoogleGenAIChatClientShouldBeRegisteredInServiceCollectionWithApiKey()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddGoogleGenAIChatClient("modelId", "apiKey");
var serviceProvider = services.BuildServiceProvider();

// Assert
var chatClient = serviceProvider.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}

[Fact]
public void GoogleVertexAIChatClientShouldBeRegisteredInKernelServices()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act
kernelBuilder.AddGoogleVertexAIChatClient("modelId", project: "test-project", location: "us-central1");

// Assert - just verify no exception during registration
// Resolution requires real credentials, so skip that in unit tests
var kernel = kernelBuilder.Build();
Assert.NotNull(kernel.Services);
}

[Fact]
public void GoogleVertexAIChatClientShouldBeRegisteredInServiceCollection()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddGoogleVertexAIChatClient("modelId", project: "test-project", location: "us-central1");
var serviceProvider = services.BuildServiceProvider();

// Assert - just verify no exception during registration
// Resolution requires real credentials, so skip that in unit tests
Assert.NotNull(serviceProvider);
}

[Fact]
public void GoogleAIChatClientShouldBeRegisteredInKernelServicesWithClient()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();
using var googleClient = new Client(apiKey: "apiKey");

// Act
kernelBuilder.AddGoogleAIChatClient("modelId", googleClient);
var kernel = kernelBuilder.Build();

// Assert
var chatClient = kernel.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}

[Fact]
public void GoogleAIChatClientShouldBeRegisteredInServiceCollectionWithClient()
{
// Arrange
var services = new ServiceCollection();
using var googleClient = new Client(apiKey: "apiKey");

// Act
services.AddGoogleAIChatClient("modelId", googleClient);
var serviceProvider = services.BuildServiceProvider();

// Assert
var chatClient = serviceProvider.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}

[Fact]
public void GoogleGenAIChatClientShouldBeRegisteredWithServiceId()
{
// Arrange
var services = new ServiceCollection();
const string serviceId = "test-service-id";

// Act
services.AddGoogleGenAIChatClient("modelId", "apiKey", serviceId: serviceId);
var serviceProvider = services.BuildServiceProvider();

// Assert
var chatClient = serviceProvider.GetKeyedService<IChatClient>(serviceId);
Assert.NotNull(chatClient);
}

[Fact]
public void GoogleVertexAIChatClientShouldBeRegisteredWithServiceId()
{
// Arrange
var services = new ServiceCollection();
const string serviceId = "test-service-id";

// Act
services.AddGoogleVertexAIChatClient("modelId", project: "test-project", location: "us-central1", serviceId: serviceId);
var serviceProvider = services.BuildServiceProvider();

// Assert - just verify no exception during registration
// Resolution requires real credentials, so skip that in unit tests
Assert.NotNull(serviceProvider);
}

[Fact]
public void GoogleAIChatClientShouldResolveFromServiceProviderWhenClientNotProvided()
{
// Arrange
var services = new ServiceCollection();
using var googleClient = new Client(apiKey: "apiKey");
services.AddSingleton(googleClient);

// Act
services.AddGoogleAIChatClient("modelId");
var serviceProvider = services.BuildServiceProvider();

// Assert
var chatClient = serviceProvider.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}
#endif
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright (c) Microsoft. All rights reserved.

#if NET

using System;
using Google.GenAI;
using Microsoft.Extensions.AI;
using Microsoft.SemanticKernel;
using Xunit;

namespace SemanticKernel.Connectors.Google.UnitTests.Services;

public sealed class GoogleGeminiChatClientTests
{
[Fact]
public void GenAIChatClientShouldBeCreatedWithApiKey()
{
// Arrange
string modelId = "gemini-1.5-pro";
string apiKey = "test-api-key";

// Act
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddGoogleGenAIChatClient(modelId, apiKey);
var kernel = kernelBuilder.Build();

// Assert
var chatClient = kernel.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}

[Fact]
public void VertexAIChatClientShouldBeCreated()
{
// Arrange
string modelId = "gemini-1.5-pro";

// Act
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddGoogleVertexAIChatClient(modelId, project: "test-project", location: "us-central1");
var kernel = kernelBuilder.Build();

// Assert - just verify no exception during registration
// Resolution requires real credentials, so skip that in unit tests
Assert.NotNull(kernel.Services);
}

[Fact]
public void ChatClientShouldBeCreatedWithGoogleClient()
{
// Arrange
string modelId = "gemini-1.5-pro";
using var googleClient = new Client(apiKey: "test-api-key");

// Act
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddGoogleAIChatClient(modelId, googleClient);
var kernel = kernelBuilder.Build();

// Assert
var chatClient = kernel.GetRequiredService<IChatClient>();
Assert.NotNull(chatClient);
}

[Fact]
public void GenAIChatClientShouldBeCreatedWithServiceId()
{
// Arrange
string modelId = "gemini-1.5-pro";
string apiKey = "test-api-key";
string serviceId = "test-service";

// Act
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddGoogleGenAIChatClient(modelId, apiKey, serviceId: serviceId);
var kernel = kernelBuilder.Build();

// Assert
var chatClient = kernel.GetRequiredService<IChatClient>(serviceId);
Assert.NotNull(chatClient);
}

[Fact]
public void VertexAIChatClientShouldBeCreatedWithServiceId()
{
// Arrange
string modelId = "gemini-1.5-pro";
string serviceId = "test-service";

// Act
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddGoogleVertexAIChatClient(modelId, project: "test-project", location: "us-central1", serviceId: serviceId);
var kernel = kernelBuilder.Build();

// Assert - just verify no exception during registration
// Resolution requires real credentials, so skip that in unit tests
Assert.NotNull(kernel.Services);
}

[Fact]
public void GenAIChatClientThrowsForNullModelId()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act & Assert
Assert.ThrowsAny<ArgumentException>(() => kernelBuilder.AddGoogleGenAIChatClient(null!, "apiKey"));
}

[Fact]
public void GenAIChatClientThrowsForEmptyModelId()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act & Assert
Assert.ThrowsAny<ArgumentException>(() => kernelBuilder.AddGoogleGenAIChatClient("", "apiKey"));
}

[Fact]
public void GenAIChatClientThrowsForNullApiKey()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act & Assert
Assert.ThrowsAny<ArgumentException>(() => kernelBuilder.AddGoogleGenAIChatClient("modelId", null!));
}

[Fact]
public void GenAIChatClientThrowsForEmptyApiKey()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act & Assert
Assert.ThrowsAny<ArgumentException>(() => kernelBuilder.AddGoogleGenAIChatClient("modelId", ""));
}

[Fact]
public void VertexAIChatClientThrowsForNullModelId()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act & Assert
Assert.ThrowsAny<ArgumentException>(() => kernelBuilder.AddGoogleVertexAIChatClient(null!, project: "test-project", location: "us-central1"));
}

[Fact]
public void VertexAIChatClientThrowsForEmptyModelId()
{
// Arrange
var kernelBuilder = Kernel.CreateBuilder();

// Act & Assert
Assert.ThrowsAny<ArgumentException>(() => kernelBuilder.AddGoogleVertexAIChatClient("", project: "test-project", location: "us-central1"));
}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<ProjectReference Include="..\..\SemanticKernel.Core\SemanticKernel.Core.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0' or '$(TargetFramework)' == 'net9.0' or '$(TargetFramework)' == 'net10.0'">
<PackageReference Include="Google.GenAI" />
<PackageReference Include="Google.Apis.Auth" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="SemanticKernel.Connectors.GoogleVertexAI.UnitTests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
Expand Down
Loading