1414 * limitations under the License.
1515 */
1616
17- package java .com .google .firebase .ai ;
17+ package java .com .google .firebase .vertexai ;
1818
1919import android .graphics .Bitmap ;
2020import com .google .common .util .concurrent .ListenableFuture ;
21+ import com .google .firebase .concurrent .FirebaseExecutors ;
2122import com .google .firebase .ai .FirebaseAI ;
2223import com .google .firebase .ai .GenerativeModel ;
24+ import com .google .firebase .ai .LiveGenerativeModel ;
2325import com .google .firebase .ai .java .ChatFutures ;
2426import com .google .firebase .ai .java .GenerativeModelFutures ;
27+ import com .google .firebase .ai .java .LiveModelFutures ;
28+ import com .google .firebase .ai .java .LiveSessionFutures ;
2529import com .google .firebase .ai .type .BlockReason ;
2630import com .google .firebase .ai .type .Candidate ;
2731import com .google .firebase .ai .type .Citation ;
3236import com .google .firebase .ai .type .FileDataPart ;
3337import com .google .firebase .ai .type .FinishReason ;
3438import com .google .firebase .ai .type .FunctionCallPart ;
39+ import com .google .firebase .ai .type .FunctionResponsePart ;
3540import com .google .firebase .ai .type .GenerateContentResponse ;
41+ import com .google .firebase .ai .type .GenerationConfig ;
3642import com .google .firebase .ai .type .HarmCategory ;
3743import com .google .firebase .ai .type .HarmProbability ;
3844import com .google .firebase .ai .type .HarmSeverity ;
3945import com .google .firebase .ai .type .ImagePart ;
4046import com .google .firebase .ai .type .InlineDataPart ;
47+ import com .google .firebase .ai .type .LiveContentResponse ;
48+ import com .google .firebase .ai .type .LiveGenerationConfig ;
49+ import com .google .firebase .ai .type .MediaData ;
4150import com .google .firebase .ai .type .ModalityTokenCount ;
4251import com .google .firebase .ai .type .Part ;
4352import com .google .firebase .ai .type .PromptFeedback ;
53+ import com .google .firebase .ai .type .ResponseModality ;
4454import com .google .firebase .ai .type .SafetyRating ;
55+ import com .google .firebase .ai .type .SpeechConfig ;
4556import com .google .firebase .ai .type .TextPart ;
4657import com .google .firebase .ai .type .UsageMetadata ;
47- import com .google .firebase .concurrent . FirebaseExecutors ;
58+ import com .google .firebase .ai . type . Voices ;
4859import java .util .Calendar ;
4960import java .util .List ;
5061import java .util .Map ;
5162import java .util .concurrent .Executor ;
5263import kotlinx .serialization .json .JsonElement ;
5364import kotlinx .serialization .json .JsonNull ;
65+ import kotlinx .serialization .json .JsonObject ;
5466import org .junit .Assert ;
5567import org .reactivestreams .Publisher ;
5668import org .reactivestreams .Subscriber ;
@@ -63,9 +75,31 @@ public class JavaCompileTests {
6375
6476 public void initializeJava () throws Exception {
6577 FirebaseAI vertex = FirebaseAI .getInstance ();
66- GenerativeModel model = vertex .generativeModel ("fake-model-name" );
78+ GenerativeModel model = vertex .generativeModel ("fake-model-name" , getConfig ());
79+ LiveGenerativeModel live = vertex .liveModel ("fake-model-name" , getLiveConfig ());
6780 GenerativeModelFutures futures = GenerativeModelFutures .from (model );
81+ LiveModelFutures liveFutures = LiveModelFutures .from (live );
6882 testFutures (futures );
83+ testLiveFutures (liveFutures );
84+ }
85+
86+ private GenerationConfig getConfig () {
87+ return new GenerationConfig .Builder ().build ();
88+ // TODO b/406558430 GenerationConfig.Builder.setParts returns void
89+ }
90+
91+ private LiveGenerationConfig getLiveConfig () {
92+ return new LiveGenerationConfig .Builder ()
93+ .setTopK (10 )
94+ .setTopP (11.0F )
95+ .setTemperature (32.0F )
96+ .setCandidateCount (1 )
97+ .setMaxOutputTokens (0xCAFEBABE )
98+ .setFrequencyPenalty (1.0F )
99+ .setPresencePenalty (2.0F )
100+ .setResponseModality (ResponseModality .AUDIO )
101+ .setSpeechConfig (new SpeechConfig (Voices .AOEDE ))
102+ .build ();
69103 }
70104
71105 private void testFutures (GenerativeModelFutures futures ) throws Exception {
@@ -138,7 +172,7 @@ public void validateGenerateContentResponse(GenerateContentResponse response) {
138172 List <Candidate > candidates = response .getCandidates ();
139173 if (candidates .size () == 1
140174 && candidates .get (0 ).getContent ().getParts ().stream ()
141- .anyMatch (p -> p instanceof TextPart && !((TextPart ) p ).getText ().isEmpty ())) {
175+ .anyMatch (p -> p instanceof TextPart && !((TextPart ) p ).getText ().isEmpty ())) {
142176 String text = response .getText ();
143177 Assert .assertNotNull (text );
144178 Assert .assertFalse (text .isBlank ());
@@ -236,4 +270,62 @@ public void validateUsageMetadata(UsageMetadata metadata) {
236270 }
237271 }
238272 }
273+
274+ private void testLiveFutures (LiveModelFutures futures ) throws Exception {
275+ LiveSessionFutures session = futures .connect ().get ();
276+ session
277+ .receive ()
278+ .subscribe (
279+ new Subscriber <LiveContentResponse >() {
280+ @ Override
281+ public void onSubscribe (Subscription s ) {
282+ s .request (Long .MAX_VALUE );
283+ }
284+
285+ @ Override
286+ public void onNext (LiveContentResponse response ) {
287+ validateLiveContentResponse (response );
288+ }
289+
290+ @ Override
291+ public void onError (Throwable t ) {
292+ // Ignore
293+ }
294+
295+ @ Override
296+ public void onComplete () {
297+ // Also ignore
298+ }
299+ });
300+
301+ session .send ("Fake message" );
302+ session .send (new Content .Builder ().addText ("Fake message" ).build ());
303+
304+ byte [] bytes = new byte [] {(byte ) 0xCA , (byte ) 0xFE , (byte ) 0xBA , (byte ) 0xBE };
305+ session .sendMediaStream (List .of (new MediaData (bytes , "image/jxl" )));
306+
307+ FunctionResponsePart functionResponse =
308+ new FunctionResponsePart ("myFunction" , new JsonObject (Map .of ()));
309+ session .sendFunctionResponse (List .of (functionResponse , functionResponse ));
310+
311+ session .startAudioConversation (part -> functionResponse );
312+ session .startAudioConversation ();
313+ session .stopAudioConversation ();
314+ session .stopReceiving ();
315+ session .close ();
316+ }
317+
318+ private void validateLiveContentResponse (LiveContentResponse response ) {
319+ //int status = response.getStatus();
320+ //Assert.assertEquals(status, LiveContentResponse.Status.Companion.getNORMAL());
321+ //Assert.assertNotEquals(status, LiveContentResponse.Status.Companion.getINTERRUPTED());
322+ //Assert.assertNotEquals(status, LiveContentResponse.Status.Companion.getTURN_COMPLETE());
323+ // TODO b/412743328 LiveContentResponse.Status inaccessible for Java users
324+ Content data = response .getData ();
325+ if (data != null ) {
326+ validateContent (data );
327+ }
328+ String text = response .getText ();
329+ validateFunctionCalls (response .getFunctionCalls ());
330+ }
239331}
0 commit comments