Files
firebase-ios-sdk/FirebaseAI/Tests/Unit/APITests.swift
T

187 lines
7.3 KiB
Swift

// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import FirebaseAI
import FirebaseCore
import XCTest
#if canImport(AppKit)
import AppKit // For NSImage extensions.
#elseif canImport(UIKit)
import UIKit // For UIImage extensions.
#endif
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
final class APITests: XCTestCase {
func codeSamples() async throws {
let app = FirebaseApp.app()
let config = GenerationConfig(temperature: 0.2,
topP: 0.1,
topK: 16,
candidateCount: 4,
maxOutputTokens: 256,
stopSequences: ["..."],
responseMIMEType: "text/plain")
let filters = [SafetySetting(harmCategory: .dangerousContent, threshold: .blockOnlyHigh)]
let systemInstruction = ModelContent(
role: "system",
parts: TextPart("Talk like a pirate.")
)
let requestOptions = RequestOptions()
let _ = RequestOptions(timeout: 30.0)
// Instantiate Firebase AI SDK - Default App
let firebaseAI = FirebaseAI.firebaseAI()
let _ = FirebaseAI.firebaseAI(backend: .googleAI())
let _ = FirebaseAI.firebaseAI(backend: .vertexAI())
let _ = FirebaseAI.firebaseAI(backend: .vertexAI(location: "my-location"))
// Instantiate Firebase AI SDK - Custom App
let _ = FirebaseAI.firebaseAI(app: app!)
let _ = FirebaseAI.firebaseAI(app: app!, backend: .googleAI())
let _ = FirebaseAI.firebaseAI(app: app!, backend: .vertexAI())
let _ = FirebaseAI.firebaseAI(app: app!, backend: .vertexAI(location: "my-location"))
// Permutations without optional arguments.
let _ = firebaseAI.generativeModel(modelName: "gemini-2.0-flash")
let _ = firebaseAI.generativeModel(
modelName: "gemini-2.0-flash",
safetySettings: filters
)
let _ = firebaseAI.generativeModel(
modelName: "gemini-2.0-flash",
generationConfig: config
)
let _ = firebaseAI.generativeModel(
modelName: "gemini-2.0-flash",
systemInstruction: systemInstruction
)
// All arguments passed.
let model = firebaseAI.generativeModel(
modelName: "gemini-2.0-flash",
generationConfig: config, // Optional
safetySettings: filters, // Optional
systemInstruction: systemInstruction, // Optional
requestOptions: requestOptions // Optional
)
// Full Typed Usage
let pngData = Data() // ....
let contents = [ModelContent(
role: "user",
parts: [
TextPart("Is it a cat?"),
InlineDataPart(data: pngData, mimeType: "image/png"),
]
)]
do {
let response = try await model.generateContent(contents)
print(response.text ?? "Couldn't get text... check status")
} catch {
print("Error generating content: \(error)")
}
// Content input combinations.
let _ = try await model.generateContent("Constant String")
let str = "String Variable"
let _ = try await model.generateContent(str)
let _ = try await model.generateContent([str])
let _ = try await model.generateContent(str, "abc", "def")
let _ = try await model.generateContent(
str,
FileDataPart(uri: "gs://test-bucket/image.jpg", mimeType: "image/jpeg")
)
#if canImport(UIKit)
_ = try await model.generateContent(UIImage())
_ = try await model.generateContent([UIImage()])
_ = try await model.generateContent([str, UIImage(), TextPart(str)])
_ = try await model.generateContent(str, UIImage(), "def", UIImage())
_ = try await model.generateContent([str, UIImage(), "def", UIImage()])
_ = try await model.generateContent([ModelContent(parts: "def", UIImage()),
ModelContent(parts: "def", UIImage())])
#elseif canImport(AppKit)
_ = try await model.generateContent(NSImage())
_ = try await model.generateContent([NSImage()])
_ = try await model.generateContent(str, NSImage(), "def", NSImage())
_ = try await model.generateContent([str, NSImage(), "def", NSImage()])
#endif
// PartsRepresentable combinations.
let _ = ModelContent(parts: [TextPart(str)])
let _ = ModelContent(role: "model", parts: [TextPart(str)])
let _ = ModelContent(parts: "Constant String")
let _ = ModelContent(parts: str)
let _ = ModelContent(parts: [str])
let _ = ModelContent(parts: [str, InlineDataPart(data: Data(), mimeType: "foo")])
#if canImport(UIKit)
_ = ModelContent(role: "user", parts: UIImage())
_ = ModelContent(role: "user", parts: [UIImage()])
_ = ModelContent(parts: [str, UIImage()])
// Note: without explicitly specifying`: [any PartsRepresentable]` this will fail to compile
// below with "Cannot convert value of type `[Any]` to expected type `[any Part]`.
let representable2: [any PartsRepresentable] = [str, UIImage()]
_ = ModelContent(parts: representable2)
_ = ModelContent(parts: [str, UIImage(), TextPart(str)])
#elseif canImport(AppKit)
_ = ModelContent(role: "user", parts: NSImage())
_ = ModelContent(role: "user", parts: [NSImage()])
_ = ModelContent(parts: [str, NSImage()])
// Note: without explicitly specifying`: [any PartsRepresentable]` this will fail to compile
// below with "Cannot convert value of type `[Any]` to expected type `[any Part]`.
let representable2: [any PartsRepresentable] = [str, NSImage()]
_ = ModelContent(parts: representable2)
_ = ModelContent(parts: [str, NSImage(), TextPart(str)])
#endif
// countTokens API
let _: CountTokensResponse = try await model.countTokens("What color is the Sky?")
#if canImport(UIKit)
let _: CountTokensResponse = try await model.countTokens("What color is the Sky?",
UIImage())
let _: CountTokensResponse = try await model.countTokens([
ModelContent(parts: "What color is the Sky?", UIImage()),
ModelContent(parts: UIImage(), "What color is the Sky?", UIImage()),
])
#endif
// Chat
_ = model.startChat()
_ = model.startChat(history: [ModelContent(parts: "abc")])
}
// Public API tests for GenerateContentResponse.
func generateContentResponseAPI() {
let response = GenerateContentResponse(candidates: [])
let _: [Candidate] = response.candidates
let _: PromptFeedback? = response.promptFeedback
// Usage Metadata
guard let usageMetadata = response.usageMetadata else { fatalError() }
let _: Int = usageMetadata.promptTokenCount
let _: Int = usageMetadata.candidatesTokenCount
let _: Int = usageMetadata.totalTokenCount
// Computed Properties
let _: String? = response.text
let _: [FunctionCallPart] = response.functionCalls
}
}