google_search_with_functions/
google_search_with_functions.rs

1use gemini_rust::{
2    Content, FunctionCall, FunctionCallingMode, FunctionDeclaration, FunctionParameters, Gemini,
3    Message, PropertyDetails, Role, Tool,
4};
5use serde_json::json;
6use std::env;
7
8#[tokio::main]
9async fn main() -> Result<(), Box<dyn std::error::Error>> {
10    // Get API key from environment variable
11    let api_key = env::var("GEMINI_API_KEY").expect("GEMINI_API_KEY environment variable not set");
12
13    // Create client
14    let client = Gemini::new(api_key);
15
16    println!("--- Google Search with Function Calling example ---");
17
18    // Define a calculator function
19    let calculate = FunctionDeclaration::new(
20        "calculate",
21        "Perform a calculation",
22        FunctionParameters::object()
23            .with_property(
24                "operation",
25                PropertyDetails::enum_type(
26                    "The mathematical operation to perform",
27                    ["add", "subtract", "multiply", "divide"],
28                ),
29                true,
30            )
31            .with_property("a", PropertyDetails::number("The first number"), true)
32            .with_property("b", PropertyDetails::number("The second number"), true),
33    );
34
35    // Create function tool
36    let function_tool = Tool::new(calculate);
37
38    // Create a request with both tools
39    let response = client
40        .generate_content()
41        .with_user_message("What is the current Google stock price multiplied by 2?")
42        .with_tool(function_tool.clone())
43        .with_function_calling_mode(FunctionCallingMode::Any)
44        .execute()
45        .await?;
46
47    // Check if there are function calls
48    if let Some(function_call) = response.function_calls().first() {
49        println!(
50            "Function call: {} with args: {}",
51            function_call.name, function_call.args
52        );
53
54        // Handle the calculate function
55        if function_call.name == "calculate" {
56            let operation: String = function_call.get("operation")?;
57            let a: f64 = function_call.get("a")?;
58            let b: f64 = function_call.get("b")?;
59
60            println!("Calculation: {} {} {}", a, operation, b);
61
62            let result = match operation.as_str() {
63                "add" => a + b,
64                "subtract" => a - b,
65                "multiply" => a * b,
66                "divide" => a / b,
67                _ => panic!("Unknown operation"),
68            };
69
70            let function_response = json!({
71                "result": result,
72            })
73            .to_string();
74
75            // Based on the curl example, we need to structure the conversation properly:
76            // 1. A user message with the original query
77            // 2. A model message containing the function call
78            // 3. A user message containing the function response
79
80            // Construct conversation following the exact curl pattern
81            let mut conversation = client.generate_content();
82
83            // 1. Add user message with original query
84            conversation = conversation
85                .with_user_message("What is the current Google stock price multiplied by 2?");
86
87            // 2. Create model message with function call
88            let model_function_call = FunctionCall::new(
89                "calculate",
90                json!({
91                    "operation": operation,
92                    "a": a,
93                    "b": b
94                }),
95            );
96
97            // Create model content with function call
98            let model_content = Content::function_call(model_function_call).with_role(Role::Model);
99
100            // Add as model message
101            let model_message = Message {
102                content: model_content,
103                role: Role::Model,
104            };
105            conversation = conversation.with_message(model_message);
106
107            // 3. Add user message with function response
108            conversation =
109                conversation.with_function_response_str("calculate", function_response)?;
110
111            // Execute the request
112            let final_response = conversation.execute().await?;
113
114            println!("Final response: {}", final_response.text());
115        } else {
116            println!("Unknown function call: {}", function_call.name);
117        }
118    } else {
119        println!("No function calls in the response.");
120        println!("Direct response: {}", response.text());
121    }
122
123    Ok(())
124}