advanced/
advanced.rs

1use gemini_rust::{
2    Content, FunctionCallingMode, FunctionDeclaration, FunctionParameters, Gemini, Part,
3    PropertyDetails,
4};
5use serde_json;
6use std::env;
7
8#[tokio::main]
9async fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let api_key = env::var("GEMINI_API_KEY")?;
11
12    // Create client
13    let client = Gemini::new(api_key);
14
15    // Define a weather function
16    let get_weather = FunctionDeclaration::new(
17        "get_weather",
18        "Get the current weather for a location",
19        FunctionParameters::object()
20            .with_property(
21                "location",
22                PropertyDetails::string("The city and state, e.g., San Francisco, CA"),
23                true,
24            )
25            .with_property(
26                "unit",
27                PropertyDetails::enum_type("The unit of temperature", ["celsius", "fahrenheit"]),
28                false,
29            ),
30    );
31
32    // Create a request with function calling
33    println!("Sending function call request...");
34    let response = client
35        .generate_content()
36        .with_user_message("What's the weather like in Tokyo right now?")
37        .with_function(get_weather)
38        .with_function_calling_mode(FunctionCallingMode::Any)
39        .execute()
40        .await?;
41
42    // Check if there are function calls
43    if let Some(function_call) = response.function_calls().first() {
44        println!(
45            "Function call received: {} with args: {}",
46            function_call.name, function_call.args
47        );
48
49        // Get parameters from the function call
50        let location: String = function_call.get("location")?;
51        let unit = function_call
52            .get::<String>("unit")
53            .unwrap_or_else(|_| String::from("celsius"));
54
55        println!("Location: {}, Unit: {}", location, unit);
56
57        // Simulate function execution (in a real app, this would call a weather API)
58        // Create a JSON response object
59        let weather_response = serde_json::json!({
60            "temperature": 22,
61            "unit": unit,
62            "condition": "sunny",
63            "location": location
64        });
65
66        // Continue the conversation with the function result
67        // We need to replay the entire conversation with the function response
68        println!("Sending function response...");
69
70        // First, need to recreate the original prompt and the model's response
71        let mut final_request = client
72            .generate_content()
73            .with_user_message("What's the weather like in Tokyo right now?");
74
75        // Add the function call from the model's response
76        let mut call_content = Content::default();
77        call_content.parts.push(Part::FunctionCall {
78            function_call: (*function_call).clone(),
79        });
80        final_request.contents.push(call_content);
81
82        // Now add the function response using the JSON value
83        final_request = final_request.with_function_response("get_weather", weather_response);
84
85        // Execute the request
86        let final_response = final_request.execute().await?;
87
88        println!("Final response: {}", final_response.text());
89    } else {
90        println!("No function calls in the response.");
91        println!("Response text: {}", response.text());
92    }
93
94    Ok(())
95}