Chapter 02 · Firebase AI Logic Basics
Subchapter 2.2
references/ios_setup.mdMarkdown5 KBView on GitHub
Ensure you have installed the FirebaseAILogic SDK via Swift Package Manager.
import FirebaseAILogic
// Initialize the Firebase AI service and the generative model.
let ai = FirebaseAI.firebaseAI()
// [AGENT] Replace "<latest_supported_model>" with the latest model from https://firebase.google.com/docs/ai-logic/models.md.txt
let model = ai.generativeModel(modelName: "<latest_supported_model>")Use the @Observable pattern to manage AI state and provide a smooth UX with
loading indicators and error handling.
⛔️ CRITICAL WARNING: Do NOT initialize the model inline as a class property if there’s any chance the view model is instantiated before
FirebaseApp.configure()executes in the app root. To be safe, initialize the model lazily or pass it in from a point in the hierarchy where Firebase is guaranteed to be configured.
import SwiftUI
import FirebaseAILogic
@MainActor
@Observable
final class AIViewModel {
// [AGENT] Replace with the latest model from https://firebase.google.com/docs/ai-logic/models.md.txt
private lazy var model = FirebaseAI.firebaseAI().generativeModel(modelName: "<latest_supported_model>")
var responseText: String = ""
var isFetching: Bool = false
var errorMessage: String?
func generate(prompt: String) async {
isFetching = true
errorMessage = nil
defer { isFetching = false }
do {
let response = try await model.generateContent(prompt)
self.responseText = response.text ?? "No response"
} catch {
self.errorMessage = error.localizedDescription
}
}
}
struct AIView: View {
@State private var viewModel = AIViewModel()
@State private var prompt = "Write a story about a magic backpack."
var body: some View {
VStack {
TextField("Enter prompt", text: $prompt)
Button("Generate") {
Task { await viewModel.generate(prompt: prompt) }
}
.disabled(viewModel.isFetching)
if viewModel.isFetching {
ProgressView()
} else if let error = viewModel.errorMessage {
Text(error).foregroundStyle(.red)
} else {
ScrollView {
Text(viewModel.responseText)
}
}
}
.padding()
}
}You can configure safety thresholds to prevent the model from generating harmful content.
let safetySettings = [
SafetySetting(category: .harassment, threshold: .blockLowAndAbove),
SafetySetting(category: .hateSpeech, threshold: .blockMediumAndAbove)
]
let model = FirebaseAI.firebaseAI().generativeModel(
modelName: "<latest_supported_model>", // [AGENT] Replace with the latest model from https://firebase.google.com/docs/ai-logic/models.md.txt
safetySettings: safetySettings
)Chat sessions persist state across multiple interactions, which is essential for ongoing conversations or when using tools like function calling.
let chat = model.startChat()
Task {
do {
let response1 = try await chat.sendMessage("Hello! I have two dogs in my house.")
print(response1.text ?? "")
let response2 = try await chat.sendMessage("How many paws are in my house?")
print(response2.text ?? "")
} catch {
print("Error in chat: \(error)")
}
}Define functions that the model can request to execute to interact with external systems. Note: Advanced workflows like function calling generally require a multi-turn Chat Session to handle the back-and-forth execution.
let getStockPriceTool = Tool(functionDeclarations: [
FunctionDeclaration(
name: "getStockPrice",
description: "Get the current stock price for a given symbol.",
parameters: [
"symbol": Schema(
type: .string,
description: "The stock symbol, e.g. AAPL"
)
]
)
])
let model = FirebaseAI.firebaseAI().generativeModel(
modelName: "<latest_supported_model>", // [AGENT] Replace with the latest model from https://firebase.google.com/docs/ai-logic/models.md.txt
tools: [getStockPriceTool]
)
// In your task (using a chat session):
let chat = model.startChat()
let response = try await chat.sendMessage("What is the stock price of Apple?")
if let functionCall = response.functionCalls.first {
// Handle the function call (e.g. call a local API and send the result back)
print("Model requested function: \(functionCall.name) with args: \(functionCall.args)")
}