1
1
package com .google .firebase .example .ailogic .java ;
2
2
3
3
import androidx .lifecycle .ViewModel ;
4
+
4
5
import com .google .common .util .concurrent .FutureCallback ;
5
6
import com .google .common .util .concurrent .Futures ;
6
7
import com .google .common .util .concurrent .ListenableFuture ;
9
10
import com .google .firebase .ai .java .ChatFutures ;
10
11
import com .google .firebase .ai .java .GenerativeModelFutures ;
11
12
import com .google .firebase .ai .type .Content ;
13
+ import com .google .firebase .ai .type .FunctionCallPart ;
14
+ import com .google .firebase .ai .type .FunctionResponsePart ;
12
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
+
13
21
import java .util .Arrays ;
22
+ import java .util .Collections ;
14
23
import java .util .List ;
24
+ import java .util .Map ;
15
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
+
16
33
import org .reactivestreams .Publisher ;
17
34
import org .reactivestreams .Subscriber ;
18
35
import org .reactivestreams .Subscription ;
19
36
20
37
public class CommonSnippets extends ViewModel {
21
38
private Executor executor ;
22
- private GenerativeModel ai = FirebaseAI .getInstance ()
23
- .generativeModel ("gemini-2.5-flash" );
39
+ private GenerativeModel ai = FirebaseAI .getInstance ().generativeModel ("gemini-2.5-flash" );
24
40
private GenerativeModelFutures model = GenerativeModelFutures .from (ai );
25
41
26
42
public void chat () {
@@ -55,18 +71,21 @@ void chatNonStreaming() {
55
71
56
72
// Send the message
57
73
ListenableFuture <GenerateContentResponse > response = chat .sendMessage (message );
58
- Futures .addCallback (response , new FutureCallback <GenerateContentResponse >() {
59
- @ Override
60
- public void onSuccess (GenerateContentResponse result ) {
61
- String resultText = result .getText ();
62
- System .out .println (resultText );
63
- }
64
-
65
- @ Override
66
- public void onFailure (Throwable t ) {
67
- t .printStackTrace ();
68
- }
69
- }, executor );
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 );
70
89
// [END chat_non_streaming]
71
90
}
72
91
@@ -96,39 +115,155 @@ void chatStreaming() {
96
115
Content message = messageBuilder .build ();
97
116
98
117
// Send the message
99
- Publisher <GenerateContentResponse > streamingResponse =
100
- chat .sendMessageStream (message );
118
+ Publisher <GenerateContentResponse > streamingResponse = chat .sendMessageStream (message );
101
119
102
120
final String [] fullResponse = {"" };
103
121
104
- streamingResponse .subscribe (new Subscriber <GenerateContentResponse >() {
122
+ streamingResponse .subscribe (
123
+ new Subscriber <GenerateContentResponse >() {
105
124
106
- @ Override
107
- public void onNext (GenerateContentResponse generateContentResponse ) {
108
- String chunk = generateContentResponse .getText ();
109
- fullResponse [0 ] += chunk ;
110
- }
125
+ @ Override
126
+ public void onNext (GenerateContentResponse generateContentResponse ) {
127
+ String chunk = generateContentResponse .getText ();
128
+ fullResponse [0 ] += chunk ;
129
+ }
111
130
131
+ @ Override
132
+ public void onComplete () {
133
+ System .out .println (fullResponse [0 ]);
134
+ }
112
135
113
- @ Override
114
- public void onComplete () {
115
- System .out .println (fullResponse [0 ]);
116
- }
136
+ // ... other methods omitted for brevity
117
137
118
- // ... other methods omitted for brevity
138
+ // [START_EXCLUDE]
139
+ @ Override
140
+ public void onSubscribe (Subscription s ) {
141
+ }
119
142
120
- // [START_EXCLUDE]
121
- @ Override
122
- public void onSubscribe ( Subscription s ) {
143
+ @ Override
144
+ public void onError ( Throwable t ) {
145
+ }
123
146
124
- }
147
+ // [END_EXCLUDE]
148
+ });
149
+ // [END chat_streaming]
150
+ }
125
151
126
- @ Override
127
- public void onError (Throwable t ) {
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]
128
170
129
- }
130
- // [END_EXCLUDE]
131
- });
132
- // [END chat_streaming]
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 ;
133
268
}
134
269
}
0 commit comments