Skip to content

Commit 82192cf

Browse files
authored
.Net: Gemini Task -> ValueTask for BearerTokenProvider (microsoft#6708)
### Motivation and Context Resolve microsoft#6679
1 parent b0c9fdf commit 82192cf

18 files changed

+81
-30
lines changed

dotnet/src/Connectors/Connectors.Google.UnitTests/Core/Gemini/Clients/GeminiChatGenerationTests.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,57 @@ public async Task ItCreatesPostRequestWithSemanticKernelVersionHeaderAsync()
416416
Assert.Equal(expectedVersion, header);
417417
}
418418

419+
[Fact]
420+
public async Task ItCanUseValueTasksSequentiallyForBearerTokenAsync()
421+
{
422+
// Arrange
423+
var bearerTokenGenerator = new BearerTokenGenerator()
424+
{
425+
BearerKeys = new List<string> { "key1", "key2", "key3" }
426+
};
427+
428+
var responseContent = File.ReadAllText(ChatTestDataFilePath);
429+
using var content1 = new HttpResponseMessage { Content = new StringContent(responseContent) };
430+
using var content2 = new HttpResponseMessage { Content = new StringContent(responseContent) };
431+
432+
using MultipleHttpMessageHandlerStub multipleMessageHandlerStub = new()
433+
{
434+
ResponsesToReturn = [content1, content2]
435+
};
436+
using var httpClient = new HttpClient(multipleMessageHandlerStub, false);
437+
438+
var client = new GeminiChatCompletionClient(
439+
httpClient: httpClient,
440+
modelId: "fake-model",
441+
apiVersion: VertexAIVersion.V1,
442+
bearerTokenProvider: () => bearerTokenGenerator.GetBearerToken(),
443+
location: "fake-location",
444+
projectId: "fake-project-id");
445+
446+
var chatHistory = CreateSampleChatHistory();
447+
448+
// Act
449+
await client.GenerateChatMessageAsync(chatHistory);
450+
await client.GenerateChatMessageAsync(chatHistory);
451+
var firstRequestHeader = multipleMessageHandlerStub.RequestHeaders[0]?.GetValues("Authorization").SingleOrDefault();
452+
var secondRequestHeader = multipleMessageHandlerStub.RequestHeaders[1]?.GetValues("Authorization").SingleOrDefault();
453+
454+
// Assert
455+
Assert.NotNull(firstRequestHeader);
456+
Assert.NotNull(secondRequestHeader);
457+
Assert.NotEqual(firstRequestHeader, secondRequestHeader);
458+
Assert.Equal("Bearer key1", firstRequestHeader);
459+
Assert.Equal("Bearer key2", secondRequestHeader);
460+
}
461+
462+
private sealed class BearerTokenGenerator()
463+
{
464+
private int _index = 0;
465+
public required List<string> BearerKeys { get; init; }
466+
467+
public ValueTask<string> GetBearerToken() => ValueTask.FromResult(this.BearerKeys[this._index++]);
468+
}
469+
419470
private static ChatHistory CreateSampleChatHistory()
420471
{
421472
var chatHistory = new ChatHistory();
@@ -436,7 +487,7 @@ private GeminiChatCompletionClient CreateChatCompletionClient(
436487
httpClient: httpClient ?? this._httpClient,
437488
modelId: modelId,
438489
apiVersion: VertexAIVersion.V1,
439-
bearerTokenProvider: () => Task.FromResult(bearerKey),
490+
bearerTokenProvider: () => new ValueTask<string>(bearerKey),
440491
location: "fake-location",
441492
projectId: "fake-project-id");
442493
}

dotnet/src/Connectors/Connectors.Google.UnitTests/Core/Gemini/Clients/GeminiChatStreamingTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ private GeminiChatCompletionClient CreateChatCompletionClient(
368368
return new GeminiChatCompletionClient(
369369
httpClient: httpClient ?? this._httpClient,
370370
modelId: modelId,
371-
bearerTokenProvider: () => Task.FromResult(bearerKey),
371+
bearerTokenProvider: () => new ValueTask<string>(bearerKey),
372372
apiVersion: VertexAIVersion.V1,
373373
location: "fake-location",
374374
projectId: "fake-project-id");

dotnet/src/Connectors/Connectors.Google.UnitTests/Core/Gemini/Clients/GeminiCountingTokensTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private GeminiTokenCounterClient CreateTokenCounterClient(
124124
return new GeminiTokenCounterClient(
125125
httpClient: this._httpClient,
126126
modelId: modelId,
127-
bearerTokenProvider: () => Task.FromResult(bearerKey),
127+
bearerTokenProvider: () => ValueTask.FromResult(bearerKey),
128128
apiVersion: VertexAIVersion.V1,
129129
location: "fake-location",
130130
projectId: "fake-project-id");

dotnet/src/Connectors/Connectors.Google.UnitTests/Core/VertexAI/VertexAIClientEmbeddingsGenerationTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private VertexAIEmbeddingClient CreateEmbeddingsClient(
143143
var client = new VertexAIEmbeddingClient(
144144
httpClient: this._httpClient,
145145
modelId: modelId,
146-
bearerTokenProvider: () => Task.FromResult(bearerKey ?? "fake-key"),
146+
bearerTokenProvider: () => ValueTask.FromResult(bearerKey ?? "fake-key"),
147147
apiVersion: VertexAIVersion.V1,
148148
location: "us-central1",
149149
projectId: "fake-project-id");

dotnet/src/Connectors/Connectors.Google.UnitTests/Extensions/VertexAIMemoryBuilderExtensionsTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public void ShouldBuildMemoryWithVertexAIEmbeddingGeneratorBearerAsFunc()
3939

4040
// Act
4141
var memory = builder
42-
.WithVertexAITextEmbeddingGeneration("fake-model", () => Task.FromResult("fake-bearer-key"), "fake-location", "fake-project")
42+
.WithVertexAITextEmbeddingGeneration("fake-model", () => ValueTask.FromResult("fake-bearer-key"), "fake-location", "fake-project")
4343
.WithMemoryStore(this._mockMemoryStore.Object)
4444
.Build();
4545

dotnet/src/Connectors/Connectors.Google.UnitTests/Extensions/VertexAIServiceCollectionExtensionsTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void VertexAIGeminiChatCompletionServiceShouldBeRegisteredInKernelService
3838
var kernelBuilder = Kernel.CreateBuilder();
3939

4040
// Act
41-
kernelBuilder.AddVertexAIGeminiChatCompletion("modelId", () => Task.FromResult("apiKey"), location: "test2", projectId: "projectId");
41+
kernelBuilder.AddVertexAIGeminiChatCompletion("modelId", () => ValueTask.FromResult("apiKey"), location: "test2", projectId: "projectId");
4242
var kernel = kernelBuilder.Build();
4343

4444
// Assert
@@ -70,7 +70,7 @@ public void VertexAIGeminiChatCompletionServiceShouldBeRegisteredInServiceCollec
7070
var services = new ServiceCollection();
7171

7272
// Act
73-
services.AddVertexAIGeminiChatCompletion("modelId", () => Task.FromResult("apiKey"), location: "test2", projectId: "projectId");
73+
services.AddVertexAIGeminiChatCompletion("modelId", () => ValueTask.FromResult("apiKey"), location: "test2", projectId: "projectId");
7474
var serviceProvider = services.BuildServiceProvider();
7575

7676
// Assert
@@ -102,7 +102,7 @@ public void VertexAIEmbeddingGenerationServiceShouldBeRegisteredInKernelServices
102102
var kernelBuilder = Kernel.CreateBuilder();
103103

104104
// Act
105-
kernelBuilder.AddVertexAIEmbeddingGeneration("modelId", () => Task.FromResult("apiKey"), location: "test2", projectId: "projectId");
105+
kernelBuilder.AddVertexAIEmbeddingGeneration("modelId", () => ValueTask.FromResult("apiKey"), location: "test2", projectId: "projectId");
106106
var kernel = kernelBuilder.Build();
107107

108108
// Assert
@@ -134,7 +134,7 @@ public void VertexAIEmbeddingGenerationServiceShouldBeRegisteredInServiceCollect
134134
var services = new ServiceCollection();
135135

136136
// Act
137-
services.AddVertexAIEmbeddingGeneration("modelId", () => Task.FromResult("apiKey"), location: "test2", projectId: "projectId");
137+
services.AddVertexAIEmbeddingGeneration("modelId", () => ValueTask.FromResult("apiKey"), location: "test2", projectId: "projectId");
138138
var serviceProvider = services.BuildServiceProvider();
139139

140140
// Assert

dotnet/src/Connectors/Connectors.Google.UnitTests/Services/VertexAIGeminiChatCompletionServiceTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void AttributesShouldContainModelIdBearerAsFunc()
2525
{
2626
// Arrange & Act
2727
string model = "fake-model";
28-
var service = new VertexAIGeminiChatCompletionService(model, () => Task.FromResult("key"), "location", "project");
28+
var service = new VertexAIGeminiChatCompletionService(model, () => new ValueTask<string>("key"), "location", "project");
2929

3030
// Assert
3131
Assert.Equal(model, service.Attributes[AIServiceExtensions.ModelIdKey]);

dotnet/src/Connectors/Connectors.Google.UnitTests/Services/VertexAITextEmbeddingGenerationServiceTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void AttributesShouldContainModelIdBearerAsFunc()
2525
{
2626
// Arrange & Act
2727
string model = "fake-model";
28-
var service = new VertexAITextEmbeddingGenerationService(model, () => Task.FromResult("key"), "location", "project");
28+
var service = new VertexAITextEmbeddingGenerationService(model, () => ValueTask.FromResult("key"), "location", "project");
2929

3030
// Assert
3131
Assert.Equal(model, service.Attributes[AIServiceExtensions.ModelIdKey]);

dotnet/src/Connectors/Connectors.Google/Connectors.Google.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
</PropertyGroup>
1111

1212
<!-- IMPORT NUGET PACKAGE SHARED PROPERTIES -->
13-
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props"/>
14-
<Import Project="$(RepoRoot)/dotnet/src/InternalUtilities/src/InternalUtilities.props"/>
13+
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
14+
<Import Project="$(RepoRoot)/dotnet/src/InternalUtilities/src/InternalUtilities.props" />
1515

1616
<PropertyGroup>
1717
<!-- NuGet Package Settings -->
@@ -21,12 +21,12 @@
2121

2222
<ItemGroup>
2323
<ProjectReference Include="..\..\SemanticKernel.Abstractions\SemanticKernel.Abstractions.csproj" />
24-
<ProjectReference Include="..\..\SemanticKernel.Core\SemanticKernel.Core.csproj"/>
24+
<ProjectReference Include="..\..\SemanticKernel.Core\SemanticKernel.Core.csproj" />
2525
</ItemGroup>
2626

2727
<ItemGroup>
28-
<InternalsVisibleTo Include="SemanticKernel.Connectors.GoogleVertexAI.UnitTests"/>
29-
<InternalsVisibleTo Include="DynamicProxyGenAssembly2"/>
28+
<InternalsVisibleTo Include="SemanticKernel.Connectors.GoogleVertexAI.UnitTests" />
29+
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
3030
</ItemGroup>
3131

3232
</Project>

dotnet/src/Connectors/Connectors.Google/Core/ClientBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Microsoft.SemanticKernel.Connectors.Google.Core;
1414

1515
internal abstract class ClientBase
1616
{
17-
private readonly Func<Task<string>>? _bearerTokenProvider;
17+
private readonly Func<ValueTask<string>>? _bearerTokenProvider;
1818

1919
protected ILogger Logger { get; }
2020

@@ -23,7 +23,7 @@ internal abstract class ClientBase
2323
protected ClientBase(
2424
HttpClient httpClient,
2525
ILogger? logger,
26-
Func<Task<string>> bearerTokenProvider)
26+
Func<ValueTask<string>> bearerTokenProvider)
2727
: this(httpClient, logger)
2828
{
2929
Verify.NotNull(bearerTokenProvider);

dotnet/src/Connectors/Connectors.Google/Core/Gemini/Clients/GeminiChatCompletionClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public GeminiChatCompletionClient(
125125
public GeminiChatCompletionClient(
126126
HttpClient httpClient,
127127
string modelId,
128-
Func<Task<string>> bearerTokenProvider,
128+
Func<ValueTask<string>> bearerTokenProvider,
129129
string location,
130130
string projectId,
131131
VertexAIVersion apiVersion,

dotnet/src/Connectors/Connectors.Google/Core/Gemini/Clients/GeminiTokenCounterClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public GeminiTokenCounterClient(
5757
public GeminiTokenCounterClient(
5858
HttpClient httpClient,
5959
string modelId,
60-
Func<Task<string>> bearerTokenProvider,
60+
Func<ValueTask<string>> bearerTokenProvider,
6161
string location,
6262
string projectId,
6363
VertexAIVersion apiVersion,

dotnet/src/Connectors/Connectors.Google/Core/VertexAI/VertexAIEmbeddingClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal sealed class VertexAIEmbeddingClient : ClientBase
3131
public VertexAIEmbeddingClient(
3232
HttpClient httpClient,
3333
string modelId,
34-
Func<Task<string>> bearerTokenProvider,
34+
Func<ValueTask<string>> bearerTokenProvider,
3535
string location,
3636
string projectId,
3737
VertexAIVersion apiVersion,

dotnet/src/Connectors/Connectors.Google/Extensions/VertexAIKernelBuilderExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static class VertexAIKernelBuilderExtensions
3737
public static IKernelBuilder AddVertexAIGeminiChatCompletion(
3838
this IKernelBuilder builder,
3939
string modelId,
40-
Func<Task<string>> bearerTokenProvider,
40+
Func<ValueTask<string>> bearerTokenProvider,
4141
string location,
4242
string projectId,
4343
VertexAIVersion apiVersion = VertexAIVersion.V1,
@@ -122,7 +122,7 @@ public static IKernelBuilder AddVertexAIGeminiChatCompletion(
122122
public static IKernelBuilder AddVertexAIEmbeddingGeneration(
123123
this IKernelBuilder builder,
124124
string modelId,
125-
Func<Task<string>> bearerTokenProvider,
125+
Func<ValueTask<string>> bearerTokenProvider,
126126
string location,
127127
string projectId,
128128
VertexAIVersion apiVersion = VertexAIVersion.V1,

dotnet/src/Connectors/Connectors.Google/Extensions/VertexAIMemoryBuilderExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static class VertexAIMemoryBuilderExtensions
3333
public static MemoryBuilder WithVertexAITextEmbeddingGeneration(
3434
this MemoryBuilder builder,
3535
string modelId,
36-
Func<Task<string>> bearerTokenProvider,
36+
Func<ValueTask<string>> bearerTokenProvider,
3737
string location,
3838
string projectId,
3939
VertexAIVersion apiVersion = VertexAIVersion.V1,

dotnet/src/Connectors/Connectors.Google/Extensions/VertexAIServiceCollectionExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static class VertexAIServiceCollectionExtensions
3535
public static IServiceCollection AddVertexAIGeminiChatCompletion(
3636
this IServiceCollection services,
3737
string modelId,
38-
Func<Task<string>> bearerTokenProvider,
38+
Func<ValueTask<string>> bearerTokenProvider,
3939
string location,
4040
string projectId,
4141
VertexAIVersion apiVersion = VertexAIVersion.V1,
@@ -116,7 +116,7 @@ public static IServiceCollection AddVertexAIGeminiChatCompletion(
116116
public static IServiceCollection AddVertexAIEmbeddingGeneration(
117117
this IServiceCollection services,
118118
string modelId,
119-
Func<Task<string>> bearerTokenProvider,
119+
Func<ValueTask<string>> bearerTokenProvider,
120120
string location,
121121
string projectId,
122122
VertexAIVersion apiVersion = VertexAIVersion.V1,

dotnet/src/Connectors/Connectors.Google/Services/VertexAIGeminiChatCompletionService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public VertexAIGeminiChatCompletionService(
3939
VertexAIVersion apiVersion = VertexAIVersion.V1,
4040
HttpClient? httpClient = null,
4141
ILoggerFactory? loggerFactory = null)
42-
: this(modelId, () => Task.FromResult(bearerKey), location, projectId, apiVersion, httpClient, loggerFactory)
42+
: this(modelId, () => new ValueTask<string>(bearerKey), location, projectId, apiVersion, httpClient, loggerFactory)
4343
{
4444
Verify.NotNullOrWhiteSpace(bearerKey);
4545
}
@@ -61,7 +61,7 @@ public VertexAIGeminiChatCompletionService(
6161
/// </remarks>
6262
public VertexAIGeminiChatCompletionService(
6363
string modelId,
64-
Func<Task<string>> bearerTokenProvider,
64+
Func<ValueTask<string>> bearerTokenProvider,
6565
string location,
6666
string projectId,
6767
VertexAIVersion apiVersion = VertexAIVersion.V1,

dotnet/src/Connectors/Connectors.Google/Services/VertexAITextEmbeddingGenerationService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public VertexAITextEmbeddingGenerationService(
3939
VertexAIVersion apiVersion = VertexAIVersion.V1,
4040
HttpClient? httpClient = null,
4141
ILoggerFactory? loggerFactory = null)
42-
: this(modelId, () => Task.FromResult(bearerKey), location, projectId, apiVersion, httpClient, loggerFactory)
42+
: this(modelId, () => new ValueTask<string>(bearerKey), location, projectId, apiVersion, httpClient, loggerFactory)
4343
{
4444
Verify.NotNullOrWhiteSpace(bearerKey);
4545
}
@@ -61,7 +61,7 @@ public VertexAITextEmbeddingGenerationService(
6161
/// </remarks>
6262
public VertexAITextEmbeddingGenerationService(
6363
string modelId,
64-
Func<Task<string>> bearerTokenProvider,
64+
Func<ValueTask<string>> bearerTokenProvider,
6565
string location,
6666
string projectId,
6767
VertexAIVersion apiVersion = VertexAIVersion.V1,

0 commit comments

Comments
 (0)