Skip to content

Commit 506e24c

Browse files
committed
chore: make tool param changes work with other major changes
1 parent c2ba879 commit 506e24c

File tree

2 files changed

+96
-32
lines changed

2 files changed

+96
-32
lines changed

examples/tool_param_types.rs

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ use std::collections::HashMap;
4141
/// This will use the specified model instead of the default "gemini-2.5-flash".
4242
use gemini_client_rs::{
4343
types::{
44-
Content, ContentPart, FunctionDeclaration, FunctionParameters, GenerateContentRequest,
45-
ParameterProperty, ParameterPropertyArray, ParameterPropertyBoolean,
46-
ParameterPropertyInteger, ParameterPropertyString, PartResponse, Role, ToolConfig,
44+
Content, ContentData, ContentPart, FunctionDeclaration, FunctionParameters,
45+
GenerateContentRequest, ParameterProperty, ParameterPropertyArray,
46+
ParameterPropertyBoolean, ParameterPropertyInteger, ParameterPropertyString, Role, Tool,
4747
ToolConfigFunctionDeclaration,
4848
},
4949
GeminiClient,
@@ -75,7 +75,12 @@ struct MeetingResponse {
7575
async fn main() -> Result<(), Box<dyn std::error::Error>> {
7676
dotenv().ok();
7777

78-
// Build the tool schema using Rust types
78+
let current_date = "2025-06-19";
79+
let system_message = format!(
80+
"You are a helpful assistant. Today's date is {}. When scheduling meetings, use appropriate dates relative to today.",
81+
current_date
82+
);
83+
7984
let properties = HashMap::from([
8085
// attendees: array of strings
8186
(
@@ -146,7 +151,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
146151
name: "schedule_meeting".to_string(),
147152
description: "Schedules a meeting with specified attendees at a given time and date."
148153
.to_string(),
149-
parameters: FunctionParameters {
154+
parameters: Some(FunctionParameters {
150155
parameter_type: "object".to_string(),
151156
properties,
152157
required: Some(vec![
@@ -158,37 +163,40 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
158163
"category".to_string(),
159164
"is_public".to_string(),
160165
]),
161-
},
166+
}),
167+
response: None,
162168
};
163169

164-
let tool_config = ToolConfig::FunctionDeclaration(ToolConfigFunctionDeclaration {
165-
function_declarations: vec![function_declaration.clone()],
166-
});
167-
168-
let current_date = "2025-06-19";
169-
let system_message = format!(
170-
"You are a helpful assistant. Today's date is {}. When scheduling meetings, use appropriate dates relative to today.",
171-
current_date
172-
);
173-
174170
let request = GenerateContentRequest {
175171
system_instruction: Some(Content {
176-
parts: vec![ContentPart::Text(system_message)],
172+
parts: vec![ContentPart {
173+
data: ContentData::Text(system_message),
174+
thought: false,
175+
metadata: None,
176+
}],
177177
role: Role::User,
178178
}),
179179
contents: vec![Content {
180-
parts: vec![ContentPart::Text(
181-
"Please schedule a team meeting for tomorrow at 2 PM with John, Sarah, and Mike to discuss the quarterly review. tag it as work, it's a P5, and make it public".to_string(),
182-
)],
180+
parts: vec![ContentPart{
181+
data: ContentData::Text( "Please schedule a team meeting for tomorrow at 2 PM with John, Sarah, and Mike to discuss the quarterly review. tag it as work, it's a P5, and make it public".to_string()),
182+
metadata: None,
183+
thought: false
184+
}],
183185
role: Role::User,
184186
}],
185-
tools: Some(vec![tool_config]),
187+
tools: vec![
188+
Tool::FunctionDeclaration(
189+
ToolConfigFunctionDeclaration{
190+
function_declarations: vec![
191+
function_declaration.clone()
192+
]
193+
}
194+
),
195+
],
196+
tool_config: None,
186197
generation_config: None,
187198
};
188199

189-
// Serialize the function declaration to JSON for verification
190-
let serialized_function = serde_json::to_value(&function_declaration)?;
191-
192200
// Expected JSON schema for comparison
193201
let expected_schema = json!({
194202
"name": "schedule_meeting",
@@ -229,8 +237,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
229237
},
230238
"required": ["attendees", "date", "time", "topic", "priority", "category", "is_public"],
231239
},
240+
"response": null,
232241
});
233242

243+
// Serialize the function declaration to JSON for verification
244+
let serialized_function = serde_json::to_value(&function_declaration)?;
245+
234246
println!("Serialized function declaration:");
235247
println!("{}", serde_json::to_string_pretty(&serialized_function)?);
236248

@@ -310,16 +322,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
310322
.await
311323
{
312324
Ok(response) => {
313-
let candidates = response.candidates.unwrap();
325+
let candidates = response.candidates.iter().collect::<Vec<_>>();
314326
let first_candidate = candidates.first().unwrap();
315327
let first_part = first_candidate.content.parts.first().unwrap();
316328

317329
let result = match first_part {
318-
PartResponse::Text(text) => text,
319-
PartResponse::FunctionCall(_) => "Function call found",
320-
PartResponse::FunctionResponse(_) => "Function response found",
321-
PartResponse::ExecutableCode(_) => "Executable code found",
322-
PartResponse::CodeExecutionResult(_) => "Code execution result found",
330+
ContentPart {
331+
data: ContentData::Text(text),
332+
thought: false,
333+
metadata: None,
334+
} => text.clone(),
335+
ContentPart {
336+
data: ContentData::FunctionResponse(result),
337+
thought: false,
338+
metadata: None,
339+
} => result.response.content.to_string(),
340+
_ => "No valid response found".to_string(),
323341
};
324342

325343
println!("🤖 Model Response:");

src/types.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::HashMap;
2+
13
use serde::{Deserialize, Serialize};
24
use serde_json::Value;
35

@@ -164,8 +166,52 @@ pub struct DynamicRetrievalConfig {
164166
pub struct FunctionDeclaration {
165167
pub name: String,
166168
pub description: String,
167-
pub parameters: Option<serde_json::Value>,
168-
pub response: Option<serde_json::Value>,
169+
pub parameters: Option<FunctionParameters>,
170+
pub response: Option<FunctionParameters>,
171+
}
172+
173+
#[derive(Debug, Serialize, Deserialize, Clone)]
174+
pub struct FunctionParameters {
175+
#[serde(rename = "type")]
176+
pub parameter_type: String,
177+
pub properties: HashMap<String, ParameterProperty>,
178+
pub required: Option<Vec<String>>,
179+
}
180+
181+
#[derive(Debug, Serialize, Deserialize, Clone)]
182+
#[serde(tag = "type", rename_all = "lowercase")]
183+
pub enum ParameterProperty {
184+
String(ParameterPropertyString),
185+
Integer(ParameterPropertyInteger),
186+
Boolean(ParameterPropertyBoolean),
187+
Array(ParameterPropertyArray),
188+
}
189+
190+
#[derive(Debug, Serialize, Deserialize, Clone)]
191+
pub struct ParameterPropertyArray {
192+
#[serde(default, skip_serializing_if = "Option::is_none")]
193+
pub description: Option<String>,
194+
pub items: Box<ParameterProperty>,
195+
}
196+
197+
#[derive(Debug, Serialize, Deserialize, Clone)]
198+
pub struct ParameterPropertyString {
199+
#[serde(default, skip_serializing_if = "Option::is_none")]
200+
pub description: Option<String>,
201+
#[serde(default, skip_serializing_if = "Option::is_none", rename = "enum")]
202+
pub enum_values: Option<Vec<String>>,
203+
}
204+
205+
#[derive(Debug, Serialize, Deserialize, Clone)]
206+
pub struct ParameterPropertyInteger {
207+
#[serde(default, skip_serializing_if = "Option::is_none")]
208+
pub description: Option<String>,
209+
}
210+
211+
#[derive(Debug, Serialize, Deserialize, Clone)]
212+
pub struct ParameterPropertyBoolean {
213+
#[serde(default, skip_serializing_if = "Option::is_none")]
214+
pub description: Option<String>,
169215
}
170216

171217
/// Response from the model supporting multiple candidate responses.

0 commit comments

Comments
 (0)