Skip to content

Commit 8c2e48b

Browse files
committed
Handle totalBillableCharacters optional decoding in Vertex AI (#12715)
1 parent 279e438 commit 8c2e48b

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

FirebaseVertexAI/Sources/CountTokensRequest.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,30 @@ extension CountTokensRequest: GenerativeAIRequest {
3939

4040
/// The model's response to a count tokens request.
4141
@available(iOS 15.0, macOS 11.0, macCatalyst 15.0, *)
42-
public struct CountTokensResponse: Decodable {
42+
public struct CountTokensResponse {
4343
/// The total number of tokens in the input given to the model as a prompt.
4444
public let totalTokens: Int
4545

46-
/// The total number of billable characters in the input given to the model as a prompt.
46+
/// The total number of billable characters in the text input given to the model as a prompt.
47+
///
48+
/// > Important: This does not include billable image, video or other non-text input. See
49+
/// [Vertex AI pricing](https://cloud.google.com/vertex-ai/generative-ai/pricing) for details.
4750
public let totalBillableCharacters: Int
4851
}
52+
53+
@available(iOS 15.0, macOS 11.0, macCatalyst 15.0, *)
54+
extension CountTokensResponse: Decodable {
55+
enum CodingKeys: CodingKey {
56+
case totalTokens
57+
case totalBillableCharacters
58+
}
59+
60+
public init(from decoder: any Decoder) throws {
61+
let container = try decoder.container(keyedBy: CodingKeys.self)
62+
totalTokens = try container.decode(Int.self, forKey: .totalTokens)
63+
totalBillableCharacters = try container.decodeIfPresent(
64+
Int.self,
65+
forKey: .totalBillableCharacters
66+
) ?? 0
67+
}
68+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"totalTokens": 258
3+
}

FirebaseVertexAI/Tests/Unit/GenerativeModelTests.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,21 @@ final class GenerativeModelTests: XCTestCase {
946946
XCTAssertEqual(response.totalBillableCharacters, 16)
947947
}
948948

949+
func testCountTokens_succeeds_noBillableCharacters() async throws {
950+
MockURLProtocol.requestHandler = try httpRequestHandler(
951+
forResource: "success-no-billable-characters",
952+
withExtension: "json"
953+
)
954+
955+
let response = try await model.countTokens(ModelContent.Part.data(
956+
mimetype: "image/jpeg",
957+
Data()
958+
))
959+
960+
XCTAssertEqual(response.totalTokens, 258)
961+
XCTAssertEqual(response.totalBillableCharacters, 0)
962+
}
963+
949964
func testCountTokens_modelNotFound() async throws {
950965
MockURLProtocol.requestHandler = try httpRequestHandler(
951966
forResource: "failure-model-not-found", withExtension: "json",

0 commit comments

Comments
 (0)