Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions firebaseai/ChatSample/Screens/ConversationScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ import GenerativeAIUIComponents
import SwiftUI

struct ConversationScreen: View {
@EnvironmentObject
var viewModel: ConversationViewModel
let firebaseService: FirebaseAI
@StateObject var viewModel: ConversationViewModel

@State
private var userPrompt = ""

init(firebaseService: FirebaseAI) {
self.firebaseService = firebaseService
_viewModel =
StateObject(wrappedValue: ConversationViewModel(firebaseService: firebaseService))
}

enum FocusedField: Hashable {
case message
}
Expand Down Expand Up @@ -110,11 +116,12 @@ struct ConversationScreen: View {

struct ConversationScreen_Previews: PreviewProvider {
struct ContainerView: View {
@StateObject var viewModel = ConversationViewModel()
@StateObject var viewModel = ConversationViewModel(firebaseService: FirebaseAI
.firebaseAI()) // Example service init

var body: some View {
ConversationScreen()
.environmentObject(viewModel)
ConversationScreen(firebaseService: FirebaseAI.firebaseAI()) // Example service init
// Removed .environmentObject
.onAppear {
viewModel.messages = ChatMessage.samples
}
Expand All @@ -123,7 +130,7 @@ struct ConversationScreen_Previews: PreviewProvider {

static var previews: some View {
NavigationStack {
ConversationScreen()
ConversationScreen(firebaseService: FirebaseAI.firebaseAI()) // Example service init
}
}
}
10 changes: 5 additions & 5 deletions firebaseai/ChatSample/ViewModels/ConversationViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ class ConversationViewModel: ObservableObject {

private var chatTask: Task<Void, Never>?

init() {
// model = FirebaseAI.firebaseAI(backend: .vertexAI()).generativeModel(modelName: "gemini-2.0-flash-001")
model = FirebaseAI.firebaseAI(backend: .googleAI())
.generativeModel(modelName: "gemini-2.0-flash-001")
chat = model.startChat()
// Modified initializer
init(firebaseService: FirebaseAI) { // Accept FirebaseAI instance
// Use the passed service instance directly
model = firebaseService.generativeModel(modelName: "gemini-2.0-flash-001")
chat = model.startChat() // Initialize chat with the model from the service
}

func sendMessage(_ text: String, streaming: Bool = true) async {
Expand Down
93 changes: 64 additions & 29 deletions firebaseai/FirebaseAISample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,80 @@
// limitations under the License.

import SwiftUI
import FirebaseAI

struct ContentView: View {
@StateObject
var viewModel = ConversationViewModel()
// BackendOption enum definition
enum BackendOption: String, CaseIterable, Identifiable {
case googleAI = "Google AI"
case vertexAI = "Vertex AI"
var id: String { rawValue }

var backendValue: FirebaseAI {
switch self {
case .googleAI:
return FirebaseAI.firebaseAI(backend: .googleAI())
case .vertexAI:
return FirebaseAI.firebaseAI(backend: .vertexAI())
}
}
}

@StateObject
var functionCallingViewModel = FunctionCallingViewModel()
struct ContentView: View {
@State private var selectedBackend: BackendOption = .googleAI
@State private var firebaseService: FirebaseAI = FirebaseAI.firebaseAI(backend: .googleAI())

var body: some View {
NavigationStack {
List {
NavigationLink {
SummarizeScreen()
} label: {
Label("Text", systemImage: "doc.text")
// Add this Section for the Picker
Section("Configuration") {
Picker("Backend", selection: $selectedBackend) {
ForEach(BackendOption.allCases) { option in
Text(option.rawValue).tag(option)
}
}
}
NavigationLink {
PhotoReasoningScreen()
} label: {
Label("Multi-modal", systemImage: "doc.richtext")
}
NavigationLink {
ConversationScreen()
.environmentObject(viewModel)
} label: {
Label("Chat", systemImage: "ellipsis.message.fill")
}
NavigationLink {
FunctionCallingScreen().environmentObject(functionCallingViewModel)
} label: {
Label("Function Calling", systemImage: "function")
}
NavigationLink {
ImagenScreen()
} label: {
Label("Imagen", systemImage: "camera.circle")

Section("Samples") {
NavigationLink {
// Pass the service instance
SummarizeScreen(firebaseService: firebaseService)
} label: {
Label("Text", systemImage: "doc.text")
}
NavigationLink {
// Pass the service instance
PhotoReasoningScreen(firebaseService: firebaseService)
} label: {
Label("Multi-modal", systemImage: "doc.richtext")
}
NavigationLink {
// Pass the service instance
ConversationScreen(firebaseService: firebaseService)
} label: {
Label("Chat", systemImage: "ellipsis.message.fill")
}
NavigationLink {
// Pass the service instance
FunctionCallingScreen(firebaseService: firebaseService)
} label: {
Label("Function Calling", systemImage: "function")
}
NavigationLink {
// Pass the service instance
ImagenScreen(firebaseService: firebaseService)
} label: {
Label("Imagen", systemImage: "camera.circle")
}
}
}
.navigationTitle("Generative AI Samples")
.onChange(of: selectedBackend) { newBackend in
// Update service when selection changes
firebaseService = newBackend.backendValue
// Note: This might cause views that hold the old service instance to misbehave
// unless they are also correctly updated or recreated.
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ import GenerativeAIUIComponents
import SwiftUI

struct FunctionCallingScreen: View {
@EnvironmentObject
var viewModel: FunctionCallingViewModel
let firebaseService: FirebaseAI
@StateObject var viewModel: FunctionCallingViewModel

@State
private var userPrompt = "What is 100 Euros in U.S. Dollars?"

init(firebaseService: FirebaseAI) {
self.firebaseService = firebaseService
_viewModel =
StateObject(wrappedValue: FunctionCallingViewModel(firebaseService: firebaseService))
}

enum FocusedField: Hashable {
case message
}
Expand Down Expand Up @@ -112,11 +118,10 @@ struct FunctionCallingScreen: View {

struct FunctionCallingScreen_Previews: PreviewProvider {
struct ContainerView: View {
@EnvironmentObject
var viewModel: FunctionCallingViewModel
@StateObject var viewModel = FunctionCallingViewModel(firebaseService: FirebaseAI.firebaseAI())

var body: some View {
FunctionCallingScreen()
FunctionCallingScreen(firebaseService: FirebaseAI.firebaseAI())
.onAppear {
viewModel.messages = ChatMessage.samples
}
Expand All @@ -125,7 +130,7 @@ struct FunctionCallingScreen_Previews: PreviewProvider {

static var previews: some View {
NavigationStack {
FunctionCallingScreen().environmentObject(FunctionCallingViewModel())
FunctionCallingScreen(firebaseService: FirebaseAI.firebaseAI()) // Example service init
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ class FunctionCallingViewModel: ObservableObject {

private var chatTask: Task<Void, Never>?

init() {
// model = FirebaseAI.firebaseAI(backend: .vertexAI()).generativeModel(
model = FirebaseAI.firebaseAI(backend: .googleAI()).generativeModel(
modelName: "gemini-2.0-flash-001",
tools: [.functionDeclarations([
FunctionDeclaration(
init(firebaseService: FirebaseAI) { // Accept FirebaseAI instance
model = firebaseService.generativeModel(
modelName: "gemini-2.0-flash-001",
tools: [.functionDeclarations([
FunctionDeclaration(
name: "get_exchange_rate",
description: "Get the exchange rate for currencies between countries",
parameters: [
Expand All @@ -57,8 +56,8 @@ class FunctionCallingViewModel: ObservableObject {
]
),
])]
)
chat = model.startChat()
)
chat = model.startChat() // Initialize chat with the model from the service
}

func sendMessage(_ text: String, streaming: Bool = true) async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ import GenerativeAIUIComponents
import MarkdownUI
import PhotosUI
import SwiftUI
import FirebaseAI

struct PhotoReasoningScreen: View {
@StateObject var viewModel = PhotoReasoningViewModel()
let firebaseService: FirebaseAI
@StateObject var viewModel: PhotoReasoningViewModel

init(firebaseService: FirebaseAI) {
self.firebaseService = firebaseService
_viewModel =
StateObject(wrappedValue: PhotoReasoningViewModel(firebaseService: firebaseService))
}

enum FocusedField: Hashable {
case message
Expand Down Expand Up @@ -73,6 +81,6 @@ struct PhotoReasoningScreen: View {

#Preview {
NavigationStack {
PhotoReasoningScreen()
PhotoReasoningScreen(firebaseService: FirebaseAI.firebaseAI())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ class PhotoReasoningViewModel: ObservableObject {

private var model: GenerativeModel?

init() {
// model = FirebaseAI.firebaseAI(backend: .vertexAI()).generativeModel(modelName: "gemini-2.0-flash-001")
model = FirebaseAI.firebaseAI(backend: .googleAI())
.generativeModel(modelName: "gemini-2.0-flash-001")
// Modified initializer
init(firebaseService: FirebaseAI) {
model = firebaseService.generativeModel(modelName: "gemini-2.0-flash-001")
}

func reason() async {
Expand Down
13 changes: 10 additions & 3 deletions firebaseai/GenerativeAITextSample/Screens/SummarizeScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@

import MarkdownUI
import SwiftUI
import FirebaseAI

struct SummarizeScreen: View {
@StateObject var viewModel = SummarizeViewModel()
@State var userInput = ""
let firebaseService: FirebaseAI
@StateObject var viewModel: SummarizeViewModel
@State var userInput = "" // Kept userInput state

init(firebaseService: FirebaseAI) {
self.firebaseService = firebaseService
_viewModel = StateObject(wrappedValue: SummarizeViewModel(firebaseService: firebaseService))
}

enum FocusedField: Hashable {
case message
Expand Down Expand Up @@ -75,6 +82,6 @@ struct SummarizeScreen: View {

#Preview {
NavigationStack {
SummarizeScreen()
SummarizeScreen(firebaseService: FirebaseAI.firebaseAI())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ class SummarizeViewModel: ObservableObject {

private var model: GenerativeModel?

init() {
// model = FirebaseAI.firebaseAI(backend: .vertexAI()).generativeModel(modelName: "gemini-2.0-flash-001")
model = FirebaseAI.firebaseAI(backend: .googleAI())
.generativeModel(modelName: "gemini-2.0-flash-001")
init(firebaseService: FirebaseAI) {
model = firebaseService.generativeModel(modelName: "gemini-2.0-flash-001")
}

func summarize(inputText: String) async {
Expand Down
12 changes: 10 additions & 2 deletions firebaseai/ImagenScreen/ImagenScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,16 @@

import SwiftUI
import GenerativeAIUIComponents
import FirebaseAI

struct ImagenScreen: View {
@StateObject var viewModel = ImagenViewModel()
let firebaseService: FirebaseAI
@StateObject var viewModel: ImagenViewModel

init(firebaseService: FirebaseAI) {
self.firebaseService = firebaseService
_viewModel = StateObject(wrappedValue: ImagenViewModel(firebaseService: firebaseService))
}

enum FocusedField: Hashable {
case message
Expand Down Expand Up @@ -103,5 +110,6 @@ struct ProgressOverlay: View {
}

#Preview {
ImagenScreen()
// Preview needs a FirebaseAI service instance
ImagenScreen(firebaseService: FirebaseAI.firebaseAI()) // Example service init
}
9 changes: 2 additions & 7 deletions firebaseai/ImagenScreen/ImagenViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ class ImagenViewModel: ObservableObject {

private var generateImagesTask: Task<Void, Never>?

// 1. Initialize the Gemini service
// private let service = FirebaseAI.firebaseAI(backend: .vertexAI())
private let service = FirebaseAI.firebaseAI(backend: .googleAI())
init() {
// 2. Configure Imagen settings
init(firebaseService: FirebaseAI) {
let modelName = "imagen-3.0-generate-002"
let safetySettings = ImagenSafetySettings(
safetyFilterLevel: .blockLowAndAbove
Expand All @@ -50,8 +46,7 @@ class ImagenViewModel: ObservableObject {
generationConfig.numberOfImages = 4
generationConfig.aspectRatio = .landscape4x3

// 3. Initialize the Imagen model
model = service.imagenModel(
model = firebaseService.imagenModel(
modelName: modelName,
generationConfig: generationConfig,
safetySettings: safetySettings
Expand Down