Skip to content

Commit dfb4c1a

Browse files
committed
[Vertex AI] Fix countTokens integration tests
1 parent 135094a commit dfb4c1a

File tree

4 files changed

+46
-28
lines changed

4 files changed

+46
-28
lines changed

FirebaseVertexAI/Tests/TestApp/Tests/Integration/CountTokensIntegrationTests.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,46 @@ struct CountTokensIntegrationTests {
121121
}
122122
)
123123
}
124+
125+
@Test(arguments: [
126+
InstanceConfig.vertexV1,
127+
InstanceConfig.vertexV1Staging,
128+
InstanceConfig.vertexV1Beta,
129+
InstanceConfig.vertexV1BetaStaging,
130+
/* System instructions are not supported on the v1 Developer API. */
131+
InstanceConfig.developerV1Beta,
132+
])
133+
func countTokens_jsonSchema(_ config: InstanceConfig) async throws {
134+
let model = VertexAI.componentInstance(config).generativeModel(
135+
modelName: ModelNames.gemini2Flash,
136+
generationConfig: GenerationConfig(
137+
responseMIMEType: "application/json",
138+
responseSchema: Schema.object(properties: [
139+
"startDate": .string(format: .custom("date-time")),
140+
"yearsSince": .integer(format: .custom("int32")),
141+
"hoursSince": .integer(format: .int32),
142+
"minutesSince": .integer(format: .int64),
143+
])
144+
),
145+
safetySettings: safetySettings
146+
)
147+
let prompt = "It is 2050-01-01, how many years, hours and minutes since 2000-01-01?"
148+
149+
let response = try await model.countTokens(prompt)
150+
151+
switch config.apiConfig.service {
152+
case .vertexAI:
153+
#expect(response.totalTokens == 65)
154+
#expect(response.totalBillableCharacters == 165)
155+
case .developer:
156+
// The Developer API erroneously ignores the `responseSchema` when counting tokens, resulting
157+
// in a lower total count than Vertex AI.
158+
#expect(response.totalTokens == 34)
159+
#expect(response.totalBillableCharacters == nil)
160+
}
161+
#expect(response.promptTokensDetails.count == 1)
162+
let promptTokensDetails = try #require(response.promptTokensDetails.first)
163+
#expect(promptTokensDetails.modality == .text)
164+
#expect(promptTokensDetails.tokenCount == response.totalTokens)
165+
}
124166
}

FirebaseVertexAI/Tests/TestApp/Tests/Integration/GenerateContentIntegrationTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@ struct GenerateContentIntegrationTests {
105105
#expect(text == "Blue")
106106

107107
let usageMetadata = try #require(response.usageMetadata)
108-
#expect(usageMetadata.promptTokenCount == 14)
108+
#expect(usageMetadata.promptTokenCount.isEqual(to: 15, accuracy: tokenCountAccuracy))
109109
#expect(usageMetadata.candidatesTokenCount.isEqual(to: 1, accuracy: tokenCountAccuracy))
110-
#expect(usageMetadata.totalTokenCount.isEqual(to: 15, accuracy: tokenCountAccuracy))
110+
#expect(usageMetadata.totalTokenCount
111+
== usageMetadata.promptTokenCount + usageMetadata.candidatesTokenCount)
111112
#expect(usageMetadata.promptTokensDetails.count == 1)
112113
let promptTokensDetails = try #require(usageMetadata.promptTokensDetails.first)
113114
#expect(promptTokensDetails.modality == .text)

FirebaseVertexAI/Tests/TestApp/Tests/Integration/IntegrationTests.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -203,31 +203,6 @@ final class IntegrationTests: XCTestCase {
203203
XCTAssertEqual(promptTokensDetails.tokenCount, 24)
204204
}
205205

206-
func testCountTokens_jsonSchema() async throws {
207-
model = vertex.generativeModel(
208-
modelName: "gemini-2.0-flash",
209-
generationConfig: GenerationConfig(
210-
responseMIMEType: "application/json",
211-
responseSchema: Schema.object(properties: [
212-
"startDate": .string(format: .custom("date")),
213-
"yearsSince": .integer(format: .custom("int16")),
214-
"hoursSince": .integer(format: .int32),
215-
"minutesSince": .integer(format: .int64),
216-
])
217-
)
218-
)
219-
let prompt = "It is 2050-01-01, how many years, hours and minutes since 2000-01-01?"
220-
221-
let response = try await model.countTokens(prompt)
222-
223-
XCTAssertEqual(response.totalTokens, 58)
224-
XCTAssertEqual(response.totalBillableCharacters, 160)
225-
XCTAssertEqual(response.promptTokensDetails.count, 1)
226-
let promptTokensDetails = try XCTUnwrap(response.promptTokensDetails.first)
227-
XCTAssertEqual(promptTokensDetails.modality, .text)
228-
XCTAssertEqual(promptTokensDetails.tokenCount, 58)
229-
}
230-
231206
func testCountTokens_appCheckNotConfigured_shouldFail() async throws {
232207
let app = try XCTUnwrap(FirebaseApp.app(name: FirebaseAppNames.appCheckNotConfigured))
233208
let vertex = VertexAI.vertexAI(app: app)

FirebaseVertexAI/Tests/TestApp/Tests/Utilities/IntegrationTestUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ enum IntegrationTestUtils {
4040

4141
extension Numeric where Self: Strideable, Self.Stride.Magnitude: Comparable {
4242
func isEqual(to other: Self, accuracy: Self.Stride) -> Bool {
43-
return distance(to: other).magnitude < accuracy.magnitude
43+
return distance(to: other).magnitude <= accuracy.magnitude
4444
}
4545
}

0 commit comments

Comments
 (0)