1
+ package com .google .firebase .example .ailogic .java ;
2
+
3
+ import androidx .lifecycle .ViewModel ;
4
+
5
+ import com .google .common .util .concurrent .FutureCallback ;
6
+ import com .google .common .util .concurrent .Futures ;
7
+ import com .google .common .util .concurrent .ListenableFuture ;
8
+ import com .google .firebase .ai .FirebaseAI ;
9
+ import com .google .firebase .ai .GenerativeModel ;
10
+ import com .google .firebase .ai .java .ChatFutures ;
11
+ import com .google .firebase .ai .java .GenerativeModelFutures ;
12
+ import com .google .firebase .ai .type .Content ;
13
+ import com .google .firebase .ai .type .FunctionCallPart ;
14
+ import com .google .firebase .ai .type .FunctionResponsePart ;
15
+ import com .google .firebase .ai .type .GenerateContentResponse ;
16
+ import com .google .firebase .ai .type .Schema ;
17
+ import com .google .firebase .ai .type .TextPart ;
18
+ import com .google .firebase .ai .type .Tool ;
19
+ import com .google .firebase .ai .type .FunctionDeclaration ;
20
+
21
+ import java .util .Arrays ;
22
+ import java .util .Collections ;
23
+ import java .util .List ;
24
+ import java .util .Map ;
25
+ import java .util .concurrent .Executor ;
26
+ import java .util .concurrent .Executors ;
27
+
28
+ import kotlinx .serialization .json .JsonElement ;
29
+ import kotlinx .serialization .json .JsonElementKt ;
30
+ import kotlinx .serialization .json .JsonObject ;
31
+ import kotlinx .serialization .json .JsonPrimitive ;
32
+
33
+ import org .reactivestreams .Publisher ;
34
+ import org .reactivestreams .Subscriber ;
35
+ import org .reactivestreams .Subscription ;
36
+
37
+ public class CommonSnippets extends ViewModel {
38
+ private Executor executor ;
39
+ private GenerativeModel ai = FirebaseAI .getInstance ().generativeModel ("gemini-2.5-flash" );
40
+ private GenerativeModelFutures model = GenerativeModelFutures .from (ai );
41
+
42
+ public void chat () {
43
+ chatNonStreaming ();
44
+ chatStreaming ();
45
+ }
46
+
47
+ void chatNonStreaming () {
48
+ // [START chat_non_streaming]
49
+ // (optional) Create previous chat history for context
50
+ Content .Builder userContentBuilder = new Content .Builder ();
51
+ userContentBuilder .setRole ("user" );
52
+ userContentBuilder .addText ("Hello, I have 2 dogs in my house." );
53
+ Content userContent = userContentBuilder .build ();
54
+
55
+ Content .Builder modelContentBuilder = new Content .Builder ();
56
+ modelContentBuilder .setRole ("model" );
57
+ modelContentBuilder .addText ("Great to meet you. What would you like to know?" );
58
+ Content modelContent = userContentBuilder .build ();
59
+
60
+ List <Content > history = Arrays .asList (userContent , modelContent );
61
+
62
+ // Initialize the chat
63
+ ChatFutures chat = model .startChat (history );
64
+
65
+ // Create a new user message
66
+ Content .Builder messageBuilder = new Content .Builder ();
67
+ messageBuilder .setRole ("user" );
68
+ messageBuilder .addText ("How many paws are in my house?" );
69
+
70
+ Content message = messageBuilder .build ();
71
+
72
+ // Send the message
73
+ ListenableFuture <GenerateContentResponse > response = chat .sendMessage (message );
74
+ Futures .addCallback (
75
+ response ,
76
+ new FutureCallback <GenerateContentResponse >() {
77
+ @ Override
78
+ public void onSuccess (GenerateContentResponse result ) {
79
+ String resultText = result .getText ();
80
+ System .out .println (resultText );
81
+ }
82
+
83
+ @ Override
84
+ public void onFailure (Throwable t ) {
85
+ t .printStackTrace ();
86
+ }
87
+ },
88
+ executor );
89
+ // [END chat_non_streaming]
90
+ }
91
+
92
+ void chatStreaming () {
93
+ // [START chat_streaming]
94
+ // (optional) Create previous chat history for context
95
+ Content .Builder userContentBuilder = new Content .Builder ();
96
+ userContentBuilder .setRole ("user" );
97
+ userContentBuilder .addText ("Hello, I have 2 dogs in my house." );
98
+ Content userContent = userContentBuilder .build ();
99
+
100
+ Content .Builder modelContentBuilder = new Content .Builder ();
101
+ modelContentBuilder .setRole ("model" );
102
+ modelContentBuilder .addText ("Great to meet you. What would you like to know?" );
103
+ Content modelContent = userContentBuilder .build ();
104
+
105
+ List <Content > history = Arrays .asList (userContent , modelContent );
106
+
107
+ // Initialize the chat
108
+ ChatFutures chat = model .startChat (history );
109
+
110
+ // Create a new user message
111
+ Content .Builder messageBuilder = new Content .Builder ();
112
+ messageBuilder .setRole ("user" );
113
+ messageBuilder .addText ("How many paws are in my house?" );
114
+
115
+ Content message = messageBuilder .build ();
116
+
117
+ // Send the message
118
+ Publisher <GenerateContentResponse > streamingResponse = chat .sendMessageStream (message );
119
+
120
+ final String [] fullResponse = {"" };
121
+
122
+ streamingResponse .subscribe (
123
+ new Subscriber <GenerateContentResponse >() {
124
+
125
+ @ Override
126
+ public void onNext (GenerateContentResponse generateContentResponse ) {
127
+ String chunk = generateContentResponse .getText ();
128
+ fullResponse [0 ] += chunk ;
129
+ }
130
+
131
+ @ Override
132
+ public void onComplete () {
133
+ System .out .println (fullResponse [0 ]);
134
+ }
135
+
136
+ // ... other methods omitted for brevity
137
+
138
+ // [START_EXCLUDE]
139
+ @ Override
140
+ public void onSubscribe (Subscription s ) {
141
+ }
142
+
143
+ @ Override
144
+ public void onError (Throwable t ) {
145
+ }
146
+
147
+ // [END_EXCLUDE]
148
+ });
149
+ // [END chat_streaming]
150
+ }
151
+
152
+ public void functionCalling () {
153
+ // [START function_calling_create_function_declaration]
154
+ FunctionDeclaration fetchWeatherTool =
155
+ new FunctionDeclaration (
156
+ "fetchWeather" ,
157
+ "Get the weather conditions for a specific city on a specific date." ,
158
+ Map .of (
159
+ "location" ,
160
+ Schema .obj (
161
+ Map .of (
162
+ "city" , Schema .str ("The city of the location." ),
163
+ "state" , Schema .str ("The US state of the location." ))),
164
+ "date" ,
165
+ Schema .str (
166
+ "The date for which to get the weather. "
167
+ + "Date must be in the format: YYYY-MM-DD." )),
168
+ Collections .emptyList ());
169
+ // [END function_calling_create_function_declaration]
170
+
171
+ // [START function_calling_generate_function_call]
172
+ String prompt = "What was the weather in Boston on October 17, 2024?" ;
173
+ ChatFutures chatFutures = model .startChat ();
174
+ // Send the user's question (the prompt) to the model using multi-turn chat.
175
+ ListenableFuture <GenerateContentResponse > response =
176
+ chatFutures .sendMessage (new Content ("user" , List .of (new TextPart (prompt ))));
177
+
178
+ ListenableFuture <JsonObject > handleFunctionCallFuture =
179
+ Futures .transform (
180
+ response ,
181
+ result -> {
182
+ for (FunctionCallPart functionCall : result .getFunctionCalls ()) {
183
+ if (functionCall .getName ().equals ("fetchWeather" )) {
184
+ Map <String , JsonElement > args = functionCall .getArgs ();
185
+ JsonObject locationJsonObject = JsonElementKt .getJsonObject (args .get ("location" ));
186
+ String city =
187
+ JsonElementKt .getContentOrNull (
188
+ JsonElementKt .getJsonPrimitive (locationJsonObject .get ("city" )));
189
+ String state =
190
+ JsonElementKt .getContentOrNull (
191
+ JsonElementKt .getJsonPrimitive (locationJsonObject .get ("state" )));
192
+ Location location = new Location (city , state );
193
+
194
+ String date =
195
+ JsonElementKt .getContentOrNull (
196
+ JsonElementKt .getJsonPrimitive (args .get ("date" )));
197
+ return fetchWeather (location , date );
198
+ }
199
+ }
200
+ return null ;
201
+ },
202
+ Executors .newSingleThreadExecutor ());
203
+ // [END function_calling_generate_function_call]
204
+
205
+ // [START function_calling_pass_back_function_response]
206
+ ListenableFuture <GenerateContentResponse > modelResponseFuture =
207
+ Futures .transformAsync (
208
+ handleFunctionCallFuture ,
209
+ // Send the response(s) from the function back to the model
210
+ // so that the model can use it to generate its final response.
211
+ functionCallResult ->
212
+ chatFutures .sendMessage (
213
+ new Content (
214
+ "function" ,
215
+ List .of (new FunctionResponsePart ("fetchWeather" , functionCallResult )))),
216
+ Executors .newSingleThreadExecutor ());
217
+
218
+ Futures .addCallback (
219
+ modelResponseFuture ,
220
+ new FutureCallback <GenerateContentResponse >() {
221
+ @ Override
222
+ public void onSuccess (GenerateContentResponse result ) {
223
+ if (result .getText () != null ) {
224
+ // Log the text response.
225
+ System .out .println (result .getText ());
226
+ }
227
+ }
228
+
229
+ @ Override
230
+ public void onFailure (Throwable t ) {
231
+ // handle error
232
+ }
233
+ },
234
+ Executors .newSingleThreadExecutor ());
235
+ // [END function_calling_pass_back_function_response]
236
+ }
237
+
238
+ // [START function_calling_write_function]
239
+ // This function calls a hypothetical external API that returns
240
+ // a collection of weather information for a given location on a given date.
241
+ // `location` is an object of the form { city: string, state: string }
242
+ public JsonObject fetchWeather (Location location , String date ) {
243
+
244
+ // TODO(developer): Write a standard function that would call to an external weather API.
245
+
246
+ // For demo purposes, this hypothetical response is hardcoded here in the expected format.
247
+ return new JsonObject (
248
+ Map .of (
249
+ "temperature" ,
250
+ JsonElementKt .JsonPrimitive (38 ),
251
+ "chancePrecipitation" ,
252
+ JsonElementKt .JsonPrimitive ("56%" ),
253
+ "cloudConditions" ,
254
+ JsonElementKt .JsonPrimitive ("partlyCloudy" )
255
+ )
256
+ );
257
+ }
258
+ // [END function_calling_write_function]
259
+ }
260
+
261
+ class Location {
262
+ public String city ;
263
+ public String state ;
264
+
265
+ public Location (String city , String state ) {
266
+ this .city = city ;
267
+ this .state = state ;
268
+ }
269
+ }
0 commit comments