@@ -48,10 +48,7 @@ struct LiveSessionTests {
4848 ) ,
4949 ] ) ,
5050 ]
51- private let textConfig = LiveGenerationConfig (
52- responseModalities: [ . text]
53- )
54- private let audioConfig = LiveGenerationConfig (
51+ private let generationConfig = LiveGenerationConfig (
5552 responseModalities: [ . audio] ,
5653 outputAudioTranscription: AudioTranscriptionConfig ( )
5754 )
@@ -76,8 +73,8 @@ struct LiveSessionTests {
7673 role: " system " ,
7774 parts: """
7875 When you receive a message, if the message is a single word, assume it's the first name of a \
79- person, and call the getLastName tool to get the last name of said person. Only respond with \
80- the last name .
76+ person, and call the getLastName tool to get the last name of said person. Once you get the \
77+ response, say the response .
8178 """ . trimmingCharacters ( in: . whitespacesAndNewlines)
8279 )
8380
@@ -95,7 +92,7 @@ struct LiveSessionTests {
9592 modelName: String ) async throws {
9693 let model = FirebaseAI . componentInstance ( config) . liveModel (
9794 modelName: modelName,
98- generationConfig: audioConfig ,
95+ generationConfig: generationConfig ,
9996 systemInstruction: SystemInstructions . helloGoodbye
10097 )
10198
@@ -119,15 +116,12 @@ struct LiveSessionTests {
119116 #expect( modelResponse == " goodbye " )
120117 }
121118
122- @Test (
123- . disabled( " Temporarily disabled " ) ,
124- . bug( " https://github.com/firebase/firebase-ios-sdk/issues/15640 " ) ,
125- arguments: arguments
126- )
127- func sendVideoRealtime_receiveText( _ config: InstanceConfig , modelName: String ) async throws {
119+ @Test ( arguments: arguments)
120+ func sendVideoRealtime_receiveAudioOutputTranscripts( _ config: InstanceConfig ,
121+ modelName: String ) async throws {
128122 let model = FirebaseAI . componentInstance ( config) . liveModel (
129123 modelName: modelName,
130- generationConfig: textConfig ,
124+ generationConfig: generationConfig ,
131125 systemInstruction: SystemInstructions . animalInVideo
132126 )
133127
@@ -152,7 +146,7 @@ struct LiveSessionTests {
152146 await session. sendAudioRealtime ( audioFile. data)
153147 await session. sendAudioRealtime ( Data ( repeating: 0 , count: audioFile. data. count) )
154148
155- let text = try await session. collectNextTextResponse ( )
149+ let text = try await session. collectNextAudioOutputTranscript ( )
156150
157151 await session. close ( )
158152 let modelResponse = text
@@ -164,15 +158,11 @@ struct LiveSessionTests {
164158 #expect( [ " kitten " , " cat " , " kitty " ] . contains ( modelResponse) )
165159 }
166160
167- @Test (
168- . disabled( " Temporarily disabled " ) ,
169- . bug( " https://github.com/firebase/firebase-ios-sdk/issues/15640 " ) ,
170- arguments: arguments
171- )
161+ @Test ( arguments: arguments)
172162 func realtime_functionCalling( _ config: InstanceConfig , modelName: String ) async throws {
173163 let model = FirebaseAI . componentInstance ( config) . liveModel (
174164 modelName: modelName,
175- generationConfig: textConfig ,
165+ generationConfig: generationConfig ,
176166 tools: tools,
177167 systemInstruction: SystemInstructions . lastNames
178168 )
@@ -200,11 +190,9 @@ struct LiveSessionTests {
200190 functionId: functionCall. functionId
201191 ) ,
202192 ] )
203-
204- var text = try await session. collectNextTextResponse ( )
193+ var text = try await session. collectNextAudioOutputTranscript ( )
205194 if text. isEmpty {
206- // The model sometimes sends an empty text response first
207- text = try await session. collectNextTextResponse ( )
195+ text = try await session. collectNextAudioOutputTranscript ( )
208196 }
209197
210198 await session. close ( )
@@ -217,8 +205,6 @@ struct LiveSessionTests {
217205 }
218206
219207 @Test (
220- . disabled( " Temporarily disabled " ) ,
221- . bug( " https://github.com/firebase/firebase-ios-sdk/issues/15640 " ) ,
222208 arguments: arguments. filter {
223209 // TODO: (b/450982184) Remove when Vertex AI adds support for Function IDs and Cancellation
224210 switch $0. 0 . apiConfig. service {
@@ -233,7 +219,7 @@ struct LiveSessionTests {
233219 modelName: String ) async throws {
234220 let model = FirebaseAI . componentInstance ( config) . liveModel (
235221 modelName: modelName,
236- generationConfig: textConfig ,
222+ generationConfig: generationConfig ,
237223 tools: tools,
238224 systemInstruction: SystemInstructions . lastNames
239225 )
@@ -266,7 +252,7 @@ struct LiveSessionTests {
266252 func realtime_interruption( _ config: InstanceConfig , modelName: String ) async throws {
267253 let model = FirebaseAI . componentInstance ( config) . liveModel (
268254 modelName: modelName,
269- generationConfig: audioConfig
255+ generationConfig: generationConfig
270256 )
271257
272258 let audioFile = try #require(
@@ -295,23 +281,23 @@ struct LiveSessionTests {
295281 }
296282 }
297283
298- @Test (
299- . disabled( " Temporarily disabled " ) ,
300- . bug( " https://github.com/firebase/firebase-ios-sdk/issues/15640 " ) ,
301- arguments: arguments
302- )
284+ @Test ( arguments: arguments)
303285 func incremental_works( _ config: InstanceConfig , modelName: String ) async throws {
304286 let model = FirebaseAI . componentInstance ( config) . liveModel (
305287 modelName: modelName,
306- generationConfig: textConfig ,
288+ generationConfig: generationConfig ,
307289 systemInstruction: SystemInstructions . yesOrNo
308290 )
309291
310292 let session = try await model. connect ( )
311293 await session. sendContent ( " Does five plus " )
312294 await session. sendContent ( " five equal ten? " , turnComplete: true )
313295
314- let text = try await session. collectNextTextResponse ( )
296+ var text = try await session. collectNextAudioOutputTranscript ( )
297+ if text. isEmpty {
298+ // The model sometimes sends an empty text response first
299+ text = try await session. collectNextAudioOutputTranscript ( )
300+ }
315301
316302 await session. close ( )
317303 let modelResponse = text
@@ -339,26 +325,6 @@ struct LiveSessionTests {
339325}
340326
341327private extension LiveSession {
342- /// Collects the text that the model sends for the next turn.
343- ///
344- /// Will listen for `LiveServerContent` messages from the model,
345- /// incrementally keeping track of any `TextPart`s it sends. Once
346- /// the model signals that its turn is complete, the function will return
347- /// a string concatenated of all the `TextPart`s.
348- func collectNextTextResponse( ) async throws -> String {
349- var text = " "
350-
351- for try await content in responsesOf ( LiveServerContent . self) {
352- text += content. modelTurn? . allText ( ) ?? " "
353-
354- if content. isTurnComplete {
355- break
356- }
357- }
358-
359- return text
360- }
361-
362328 /// Collects the audio output transcripts that the model sends for the next turn.
363329 ///
364330 /// Will listen for `LiveServerContent` messages from the model,
@@ -395,11 +361,7 @@ private extension LiveSession {
395361 case let . toolCall( toolCall) :
396362 return toolCall
397363 case let . content( content) :
398- if let text = content. modelTurn? . allText ( ) {
399- error += text
400- } else {
401- error += content. outputAudioText ( )
402- }
364+ error += content. outputAudioText ( )
403365
404366 if content. isTurnComplete {
405367 Issue . record ( " The model didn't send a tool call. Text received: \( error) " )
@@ -464,16 +426,6 @@ private struct NoInterruptionError: Error,
464426 var description : String { " The model never sent an interrupted message. " }
465427}
466428
467- private extension ModelContent {
468- /// A collection of text from all parts.
469- ///
470- /// If this doesn't contain any `TextPart`, then an empty
471- /// string will be returned instead.
472- func allText( ) -> String {
473- parts. compactMap { ( $0 as? TextPart ) ? . text } . joined ( )
474- }
475- }
476-
477429extension LiveServerContent {
478430 /// Text of the output `LiveAudioTranscript`, or an empty string if it's missing.
479431 func outputAudioText( ) -> String {
0 commit comments