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