Skip to content

Commit c804629

Browse files
rodriciruRodrigomarkwallace-microsoftrogerbarreto
authored
.Net: Add Gemini usage metadata CachedContentTokenCount and ThoughtsTokenC… (#13208)
Add missing usage variables in GeminiMetadata class ### Motivation and Context Gemini gives us CachedContentTokenCount and ThoughtsTokenCount to know how much of cost have the request. The total input as Gemini eyes is not only PromptTokenCount, but a sum of these 3 variables. ### Description Added CachedContentTokenCount and ThoughtsTokenCount variables, filled by the response and add test. **As I am beginner in C#, I can build and pass the test, also I can make an .nupkg of the code changed, but I can't test on other projects, so PLEASE check that before submitting changes. Thank you so much** ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X ] The code builds clean without any errors or warnings - [X ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [X ] All unit tests pass, and I have added new tests where possible - [ X] I didn't break anyone 😄 --------- Co-authored-by: Rodrigo <[email protected]> Co-authored-by: Mark Wallace <[email protected]> Co-authored-by: Roger Barreto <[email protected]>
1 parent d595e48 commit c804629

File tree

6 files changed

+50
-4
lines changed

6 files changed

+50
-4
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ public async Task ShouldReturnValidGeminiMetadataAsync()
164164
}
165165

166166
Assert.Equal(testDataResponse.UsageMetadata!.PromptTokenCount, metadata.PromptTokenCount);
167+
Assert.Equal(testDataResponse.UsageMetadata!.CachedContentTokenCount, metadata.CachedContentTokenCount);
168+
Assert.Equal(testDataResponse.UsageMetadata!.ThoughtsTokenCount, metadata.ThoughtsTokenCount);
167169
Assert.Equal(testDataCandidate.TokenCount, metadata.CurrentCandidateTokenCount);
168170
Assert.Equal(testDataResponse.UsageMetadata.CandidatesTokenCount, metadata.CandidatesTokenCount);
169171
Assert.Equal(testDataResponse.UsageMetadata.TotalTokenCount, metadata.TotalTokenCount);
@@ -207,6 +209,8 @@ public async Task ShouldReturnValidDictionaryMetadataAsync()
207209
}
208210

209211
Assert.Equal(testDataResponse.UsageMetadata!.PromptTokenCount, metadata[nameof(GeminiMetadata.PromptTokenCount)]);
212+
Assert.Equal(testDataResponse.UsageMetadata!.CachedContentTokenCount, metadata[nameof(GeminiMetadata.CachedContentTokenCount)]);
213+
Assert.Equal(testDataResponse.UsageMetadata!.ThoughtsTokenCount, metadata[nameof(GeminiMetadata.ThoughtsTokenCount)]);
210214
Assert.Equal(testDataCandidate.TokenCount, metadata[nameof(GeminiMetadata.CurrentCandidateTokenCount)]);
211215
Assert.Equal(testDataResponse.UsageMetadata.CandidatesTokenCount, metadata[nameof(GeminiMetadata.CandidatesTokenCount)]);
212216
Assert.Equal(testDataResponse.UsageMetadata.TotalTokenCount, metadata[nameof(GeminiMetadata.TotalTokenCount)]);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ public async Task ShouldReturnValidGeminiMetadataAsync()
174174
}
175175

176176
Assert.Equal(testDataResponse.UsageMetadata!.PromptTokenCount, metadata.PromptTokenCount);
177+
Assert.Equal(testDataResponse.UsageMetadata!.CachedContentTokenCount, metadata.CachedContentTokenCount);
178+
Assert.Equal(testDataResponse.UsageMetadata!.ThoughtsTokenCount, metadata.ThoughtsTokenCount);
177179
Assert.Equal(testDataCandidate.TokenCount, metadata.CurrentCandidateTokenCount);
178180
Assert.Equal(testDataResponse.UsageMetadata.CandidatesTokenCount, metadata.CandidatesTokenCount);
179181
Assert.Equal(testDataResponse.UsageMetadata.TotalTokenCount, metadata.TotalTokenCount);
@@ -218,6 +220,8 @@ public async Task ShouldReturnValidDictionaryMetadataAsync()
218220
}
219221

220222
Assert.Equal(testDataResponse.UsageMetadata!.PromptTokenCount, metadata[nameof(GeminiMetadata.PromptTokenCount)]);
223+
Assert.Equal(testDataResponse.UsageMetadata!.CachedContentTokenCount, metadata[nameof(GeminiMetadata.CachedContentTokenCount)]);
224+
Assert.Equal(testDataResponse.UsageMetadata!.ThoughtsTokenCount, metadata[nameof(GeminiMetadata.ThoughtsTokenCount)]);
221225
Assert.Equal(testDataCandidate.TokenCount, metadata[nameof(GeminiMetadata.CurrentCandidateTokenCount)]);
222226
Assert.Equal(testDataResponse.UsageMetadata.CandidatesTokenCount, metadata[nameof(GeminiMetadata.CandidatesTokenCount)]);
223227
Assert.Equal(testDataResponse.UsageMetadata.TotalTokenCount, metadata[nameof(GeminiMetadata.TotalTokenCount)]);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,8 @@ private static GeminiMetadata GetResponseMetadata(
791791
FinishReason = candidate.FinishReason,
792792
Index = candidate.Index,
793793
PromptTokenCount = geminiResponse.UsageMetadata?.PromptTokenCount ?? 0,
794+
CachedContentTokenCount = geminiResponse.UsageMetadata?.CachedContentTokenCount ?? 0,
795+
ThoughtsTokenCount = geminiResponse.UsageMetadata?.ThoughtsTokenCount ?? 0,
794796
CurrentCandidateTokenCount = candidate.TokenCount,
795797
CandidatesTokenCount = geminiResponse.UsageMetadata?.CandidatesTokenCount ?? 0,
796798
TotalTokenCount = geminiResponse.UsageMetadata?.TotalTokenCount ?? 0,

dotnet/src/Connectors/Connectors.Google/Core/Gemini/Models/GeminiResponse.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ internal sealed class UsageMetadataElement
3939
[JsonPropertyName("promptTokenCount")]
4040
public int PromptTokenCount { get; set; }
4141

42+
/// <summary>
43+
/// Gets the number of cached content tokens used.
44+
/// </summary>
45+
[JsonPropertyName("cachedContentTokenCount")]
46+
public int CachedContentTokenCount { get; set; }
47+
48+
/// <summary>
49+
/// Gets the number of thoughts tokens used.
50+
/// </summary>
51+
[JsonPropertyName("thoughtsTokenCount")]
52+
public int ThoughtsTokenCount { get; set; }
53+
4254
/// <summary>
4355
/// Gets the count of used tokens for all candidates.
4456
/// </summary>

dotnet/src/Connectors/Connectors.Google/Models/Gemini/GeminiMetadata.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,21 @@ public int PromptTokenCount
4444
}
4545

4646
/// <summary>
47-
/// The count of token in the current candidate.
47+
/// The count of cached content tokens.
4848
/// </summary>
49-
public int CurrentCandidateTokenCount
49+
public int CachedContentTokenCount
5050
{
51-
get => (this.GetValueFromDictionary(nameof(this.CurrentCandidateTokenCount)) as int?) ?? 0;
52-
internal init => this.SetValueInDictionary(value, nameof(this.CurrentCandidateTokenCount));
51+
get => (this.GetValueFromDictionary(nameof(this.CachedContentTokenCount)) as int?) ?? 0;
52+
internal init => this.SetValueInDictionary(value, nameof(this.CachedContentTokenCount));
53+
}
54+
55+
/// <summary>
56+
/// The count of thoughts tokens.
57+
/// </summary>
58+
public int ThoughtsTokenCount
59+
{
60+
get => (this.GetValueFromDictionary(nameof(this.ThoughtsTokenCount)) as int?) ?? 0;
61+
internal init => this.SetValueInDictionary(value, nameof(this.ThoughtsTokenCount));
5362
}
5463

5564
/// <summary>
@@ -61,6 +70,15 @@ public int CandidatesTokenCount
6170
internal init => this.SetValueInDictionary(value, nameof(this.CandidatesTokenCount));
6271
}
6372

73+
/// <summary>
74+
/// The count of token in the current candidate.
75+
/// </summary>
76+
public int CurrentCandidateTokenCount
77+
{
78+
get => (this.GetValueFromDictionary(nameof(this.CurrentCandidateTokenCount)) as int?) ?? 0;
79+
internal init => this.SetValueInDictionary(value, nameof(this.CurrentCandidateTokenCount));
80+
}
81+
6482
/// <summary>
6583
/// The total count of tokens (prompt + total candidates token count).
6684
/// </summary>

dotnet/src/IntegrationTests/Connectors/Google/Gemini/GeminiChatCompletionTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ public async Task ChatGenerationReturnsUsedTokensAsync(ServiceType serviceType)
435435
Assert.True(geminiMetadata.CandidatesTokenCount > 0);
436436
Assert.True(geminiMetadata.PromptTokenCount > 0);
437437
Assert.True(geminiMetadata.CurrentCandidateTokenCount > 0);
438+
Assert.True(geminiMetadata.CachedContentTokenCount > 0);
439+
Assert.True(geminiMetadata.ThoughtsTokenCount > 0);
438440
}
439441

440442
[RetryTheory]
@@ -459,10 +461,14 @@ public async Task ChatStreamingReturnsUsedTokensAsync(ServiceType serviceType)
459461
this.Output.WriteLine($"TotalTokenCount: {geminiMetadata.TotalTokenCount}");
460462
this.Output.WriteLine($"CandidatesTokenCount: {geminiMetadata.CandidatesTokenCount}");
461463
this.Output.WriteLine($"PromptTokenCount: {geminiMetadata.PromptTokenCount}");
464+
this.Output.WriteLine($"CachedContentTokenCount: {geminiMetadata.CachedContentTokenCount}");
465+
this.Output.WriteLine($"ThoughtsTokenCount: {geminiMetadata.ThoughtsTokenCount}");
462466
this.Output.WriteLine($"CurrentCandidateTokenCount: {geminiMetadata.CurrentCandidateTokenCount}");
463467
Assert.True(geminiMetadata.TotalTokenCount > 0);
464468
Assert.True(geminiMetadata.CandidatesTokenCount > 0);
465469
Assert.True(geminiMetadata.PromptTokenCount > 0);
470+
Assert.True(geminiMetadata.CachedContentTokenCount > 0);
471+
Assert.True(geminiMetadata.ThoughtsTokenCount > 0);
466472
Assert.True(geminiMetadata.CurrentCandidateTokenCount > 0);
467473
}
468474

0 commit comments

Comments
 (0)