advanced/
advanced.rs

1use gemini_rust::{
2    FunctionDeclaration, Gemini, PropertyDetails, FunctionParameters,
3    FunctionCallingMode, Content, Part, Role
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(
28                    "The unit of temperature", 
29                    ["celsius", "fahrenheit"]
30                ),
31                false,
32            ),
33    );
34
35    // Create a request with function calling
36    println!("Sending function call request...");
37    let response = client
38        .generate_content()
39        .with_user_message("What's the weather like in Tokyo right now?")
40        .with_function(get_weather)
41        .with_function_calling_mode(FunctionCallingMode::Any)
42        .execute()
43        .await?;
44
45    // Check if there are function calls
46    if let Some(function_call) = response.function_calls().first() {
47        println!(
48            "Function call received: {} with args: {}",
49            function_call.name,
50            function_call.args
51        );
52
53        // Get parameters from the function call
54        let location: String = function_call.get("location")?;
55        let unit = function_call.get::<String>("unit").unwrap_or_else(|_| String::from("celsius"));
56        
57        println!("Location: {}, Unit: {}", location, unit);
58        
59        // Simulate function execution (in a real app, this would call a weather API)
60        // Create a JSON response object
61        let weather_response = serde_json::json!({
62            "temperature": 22,
63            "unit": unit,
64            "condition": "sunny",
65            "location": location
66        });
67
68        // Continue the conversation with the function result
69        // We need to replay the entire conversation with the function response
70        println!("Sending function response...");
71        
72        // First, need to recreate the original prompt and the model's response
73        let mut final_request = client.generate_content()
74            .with_user_message("What's the weather like in Tokyo right now?");
75        
76        // Add the function call from the model's response
77        let mut call_content = Content::default();
78        call_content.parts.push(Part::FunctionCall { 
79            function_call: (*function_call).clone()
80        });
81        let call_content = call_content.with_role(Role::Model);
82        final_request.contents.push(call_content);
83        
84        // Now add the function response using the JSON value
85        final_request = final_request.with_function_response("get_weather", weather_response);
86        
87        // Execute the request
88        let final_response = final_request.execute().await?;
89
90        println!("Final response: {}", final_response.text());
91    } else {
92        println!("No function calls in the response.");
93        println!("Response text: {}", response.text());
94    }
95
96    Ok(())
97}