फ़ंक्शन टूल
कस्टम Rust फ़ंक्शंस के साथ एजेंट की क्षमताओं का विस्तार करें।
फ़ंक्शन टूल क्या हैं?
फ़ंक्शन टूल आपको एजेंट को बातचीत से परे क्षमताएँ देने देते हैं - APIs को कॉल करना, गणनाएँ करना, डेटाबेस तक पहुँचना या कोई भी कस्टम लॉजिक निष्पादित करना। उपयोगकर्ता के अनुरोध के आधार पर LLM यह तय करता है कि टूल का उपयोग कब करना है।
मुख्य विशेषताएँ:
- 🚀
#[tool]मैक्रो - बिना अतिरिक्त बॉयलरप्लेट के टूल पंजीकरण (अनुशंसित)- 🔧
FunctionTool::new()- किसी भी async फ़ंक्शन को मैन्युअल रूप से रैप करें- 📝 JSON पैरामीटर - लचीला इनपुट/आउटपुट
- 🎯 टाइप-सुरक्षित स्कीमा - schemars के माध्यम से प्रकारों से स्वचालित JSON Schema
- 🔗 कॉन्टेक्स्ट एक्सेस - सेशन स्थिति, आर्टिफ़ैक्ट, मेमोरी
टूल निष्पादन पाइपलाइन
अनुशंसित: #[tool] मैक्रो
टूल बनाने का सबसे तेज़ तरीका। मैक्रो आपके doc comment को विवरण के रूप में पढ़ता है और आपके args type से JSON स्कीमा प्राप्त करता है:
use adk_tool::tool;
use adk_core::AdkError;
use schemars::JsonSchema;
use serde::Deserialize;
use serde_json::{json, Value};
#[derive(Deserialize, JsonSchema)]
struct WeatherArgs {
/// The city to look up
city: String,
/// Temperature unit (celsius or fahrenheit)
unit: Option<String>,
}
/// Get the current weather for a city.
#[tool]
async fn get_weather(args: WeatherArgs) -> Result<Value, AdkError> {
Ok(json!({ "temp": 22, "city": args.city }))
}
// Generated: pub struct GetWeather; — implements adk_core::Tool
// Use it: agent_builder.tool(Arc::new(GetWeather))
यदि आपके टूल को सेशन कॉन्टेक्स्ट की आवश्यकता है, तो पहले पैरामीटर के रूप में Arc<dyn ToolContext> जोड़ें:
use adk_core::ToolContext;
use std::sync::Arc;
/// Search the user's saved documents.
#[tool]
async fn search_docs(
ctx: Arc<dyn ToolContext>,
args: SearchArgs,
) -> Result<Value, AdkError> {
let user_id = ctx.user_id();
// ... use context for scoped access
}
टूल मेटाडेटा एट्रिब्यूट
मैक्रो में सीधे टूल को केवल-पठन, समवर्तीता-सुरक्षित या लंबे समय तक चलने वाला चिह्नित करें:
/// Look up cached data — no side effects, safe for parallel dispatch.
#[tool(read_only, concurrency_safe)]
async fn cache_lookup(args: LookupArgs) -> Result<Value, AdkError> {
Ok(json!({"result": "cached"}))
}
/// Start a long-running background report.
#[tool(long_running)]
async fn generate_report(args: ReportArgs) -> Result<Value, AdkError> {
Ok(json!({"task_id": "abc123", "status": "processing"}))
}
उपलब्ध एट्रिब्यूट (सभी वैकल्पिक हैं, स्वतंत्र रूप से संयोजित किए जा सकते हैं):
| विशेषता | प्रभाव |
|---|---|
read_only | is_read_only() → true — समवर्ती Auto प्रेषण के लिए आवश्यक दो संकेतों में से एक |
concurrency_safe | is_concurrency_safe() → true — समवर्ती Auto प्रेषण के लिए आवश्यक दो संकेतों में से एक |
long_running | is_long_running() → true — LLM को लंबित टूल को फिर से कॉल करने से रोकता है |
बिना attributes वाला #[tool] डिफ़ॉल्ट रखता है (सभी false), इसलिए मौजूदा code अप्रभावित रहता है।
विकल्प: FunctionTool::new()
डायनेमिक tools के लिए या जब आप स्पष्ट registration पसंद करते हैं:
FunctionTool::new() के साथ एक tool बनाएँ और हमेशा एक schema जोड़ें, ताकि LLM को पता हो कि कौन से parameters पास करने हैं:
use adk_rust::prelude::*;
use adk_rust::Launcher;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::sync::Arc;
#[derive(JsonSchema, Serialize, Deserialize)]
struct WeatherParams {
/// The city or location to get weather for
location: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let api_key = std::env::var("GOOGLE_API_KEY")?;
let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;
// Weather tool with proper schema
let weather_tool = FunctionTool::new(
"get_weather",
"Get current weather for a location",
|_ctx, args| async move {
let location = args.get("location")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
Ok(json!({
"location": location,
"temperature": "22°C",
"conditions": "sunny"
}))
},
)
.with_parameters_schema::<WeatherParams>(); // Required for LLM to call correctly!
let agent = LlmAgentBuilder::new("weather_agent")
.instruction("You help users check the weather. Always use the get_weather tool.")
.model(Arc::new(model))
.tool(Arc::new(weather_tool))
.build()?;
Launcher::new(Arc::new(agent)).run().await?;
Ok(())
}
⚠️ महत्वपूर्ण: हमेशा
.with_parameters_schema<T>()का उपयोग करें - इसके बिना, LLM को पता नहीं होगा कि कौन से parameters पास करने हैं और वह tool को call नहीं कर सकता।
यह कैसे काम करता है:
- User पूछता है: "टोक्यो में मौसम कैसा है?"
- LLM
get_weatherको{"location": "Tokyo"}के साथ call करने का निर्णय लेता है - Tool
{"location": "Tokyo", "temperature": "22°C", "conditions": "sunny"}लौटाता है - LLM response को format करता है: "टोक्यो में मौसम 22°C पर धूप वाला है।"
चरण 2: Parameter Handling
JSON args से parameters निकालें:
let order_tool = FunctionTool::new(
"process_order",
"Process an order. Parameters: product_id (required), quantity (required), priority (optional)",
|_ctx, args| async move {
// Required parameters - return error if missing
let product_id = args.get("product_id")
.and_then(|v| v.as_str())
.ok_or_else(|| adk_core::AdkError::tool("product_id is required"))?;
let quantity = args.get("quantity")
.and_then(|v| v.as_i64())
.ok_or_else(|| adk_core::AdkError::tool("quantity is required"))?;
// Optional parameter with default
let priority = args.get("priority")
.and_then(|v| v.as_str())
.unwrap_or("normal");
Ok(json!({
"order_id": "ORD-12345",
"product_id": product_id,
"quantity": quantity,
"priority": priority,
"status": "confirmed"
}))
},
);
चरण 3: Schema के साथ Typed Parameters
जटिल tools के लिए, JSON Schema के साथ typed structs का उपयोग करें:
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(JsonSchema, Serialize, Deserialize)]
struct CalculatorParams {
/// The arithmetic operation to perform
operation: Operation,
/// First operand
a: f64,
/// Second operand
b: f64,
}
#[derive(JsonSchema, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
enum Operation {
Add,
Subtract,
Multiply,
Divide,
}
let calculator = FunctionTool::new(
"calculator",
"Perform arithmetic operations",
|_ctx, args| async move {
let params: CalculatorParams = serde_json::from_value(args)?;
let result = match params.operation {
Operation::Add => params.a + params.b,
Operation::Subtract => params.a - params.b,
Operation::Multiply => params.a * params.b,
Operation::Divide if params.b != 0.0 => params.a / params.b,
Operation::Divide => return Err(adk_core::AdkError::tool("Cannot divide by zero")),
};
Ok(json!({ "result": result }))
},
)
.with_parameters_schema::<CalculatorParams>();
Schema, schemars का उपयोग करके Rust types से अपने-आप generate होता है।
चरण 4: Multi-Tool Agent
एक agent में कई tools जोड़ें:
let agent = LlmAgentBuilder::new("assistant")
.instruction("Help with calculations, conversions, and weather.")
.model(Arc::new(model))
.tool(Arc::new(calc_tool))
.tool(Arc::new(convert_tool))
.tool(Arc::new(weather_tool))
.build()?;
LLM user के request के आधार पर अपने-आप सही tool चुनता है।
Error Handling
Tool-विशिष्ट failures के लिए Tool component के साथ errors लौटाएँ:
use adk_core::{AdkError, ErrorComponent, ErrorCategory};
let divide_tool = FunctionTool::new(
"divide",
"Divide two numbers",
|_ctx, args| async move {
let a = args.get("a").and_then(|v| v.as_f64())
.ok_or_else(|| AdkError::new(
ErrorComponent::Tool,
ErrorCategory::InvalidInput,
"tool.divide.missing_param",
"Parameter 'a' is required",
))?;
let b = args.get("b").and_then(|v| v.as_f64())
.ok_or_else(|| AdkError::new(
ErrorComponent::Tool,
ErrorCategory::InvalidInput,
"tool.divide.missing_param",
"Parameter 'b' is required",
))?;
if b == 0.0 {
return Err(AdkError::new(
ErrorComponent::Tool,
ErrorCategory::InvalidInput,
"tool.divide.division_by_zero",
"Cannot divide by zero",
));
}
Ok(json!({ "result": a / b }))
},
);
त्वरित migration के लिए, backward-compatible shorthand भी काम करता है:
Err(AdkError::tool("Parameter 'a' is required"))
Error messages LLM को पास किए जाते हैं, जो retry कर सकता है या अलग input माँग सकता है।
Tool Context
ToolContext के माध्यम से session info तक पहुँचें:
#[derive(JsonSchema, Serialize, Deserialize)]
struct GreetParams {
#[serde(default)]
message: Option<String>,
}
let greet_tool = FunctionTool::new(
"greet",
"Greet the user with session info",
|ctx, _args| async move {
let user_id = ctx.user_id();
let session_id = ctx.session_id();
let agent_name = ctx.agent_name();
Ok(json!({
"greeting": format!("Hello, user {}!", user_id),
"session": session_id,
"served_by": agent_name
}))
},
)
.with_parameters_schema::<GreetParams>();
उपलब्ध context:
ctx.user_id()- वर्तमान user IDctx.session_id()- वर्तमान session IDctx.agent_name()- agent का नामctx.artifacts()- artifact storage तक पहुँचctx.search_memory(query)- memory service में search
लंबे समय तक चलने वाले Tools
महत्वपूर्ण समय लेने वाले ऑपरेशनों (डेटा प्रोसेसिंग, बाहरी APIs) के लिए, गैर-ब्लॉकिंग पैटर्न का उपयोग करें:
- टूल शुरू करें तुरंत task_id के साथ लौटता है
- पृष्ठभूमि का कार्य एसिंक्रोनस रूप से चलता है
- स्थिति टूल उपयोगकर्ताओं को प्रगति जाँचने देता है
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(JsonSchema, Serialize, Deserialize)]
struct ReportParams {
topic: String,
}
#[derive(JsonSchema, Serialize, Deserialize)]
struct StatusParams {
task_id: String,
}
// Shared task store
let tasks: Arc<RwLock<HashMap<String, TaskState>>> = Arc::new(RwLock::new(HashMap::new()));
let tasks1 = tasks.clone();
let tasks2 = tasks.clone();
// Tool 1: Start (returns immediately)
let start_tool = FunctionTool::new(
"generate_report",
"Start generating a report. Returns task_id immediately.",
move |_ctx, args| {
let tasks = tasks1.clone();
async move {
let topic = args.get("topic").and_then(|v| v.as_str()).unwrap_or("general").to_string();
let task_id = format!("task_{}", rand::random::<u32>());
// Store initial state
tasks.write().await.insert(task_id.clone(), TaskState {
status: "processing".to_string(),
progress: 0,
result: None,
});
// Spawn background work (non-blocking!)
let tasks_bg = tasks.clone();
let tid = task_id.clone();
tokio::spawn(async move {
// Simulate work...
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
if let Some(t) = tasks_bg.write().await.get_mut(&tid) {
t.status = "completed".to_string();
t.result = Some("Report complete".to_string());
}
});
// Return immediately with task_id
Ok(json!({"task_id": task_id, "status": "processing"}))
}
},
)
.with_parameters_schema::<ReportParams>()
.with_long_running(true); // Mark as long-running
// Tool 2: Check status
let status_tool = FunctionTool::new(
"check_report_status",
"Check report generation status",
move |_ctx, args| {
let tasks = tasks2.clone();
async move {
let task_id = args.get("task_id").and_then(|v| v.as_str()).unwrap_or("");
if let Some(t) = tasks.read().await.get(task_id) {
Ok(json!({"status": t.status, "result": t.result}))
} else {
Ok(json!({"error": "Task not found"}))
}
}
},
)
.with_parameters_schema::<StatusParams>();
मुख्य बिंदु:
.with_long_running(true)एजेंट को बताता है कि यह टूल लंबित स्थिति लौटाता है- टूल
tokio::spawn()के साथ कार्य शुरू करता है और तुरंत लौटता है - एक स्थिति-जाँच टूल प्रदान करें ताकि उपयोगकर्ता प्रगति के लिए बार-बार जाँच कर सकें
यह LLM को टूल बार-बार कॉल करने से रोकने के लिए एक नोट जोड़ता है।
टूल से स्ट्रीमिंग प्रगति
लंबे समय तक चलने वाले टूल निष्पादन के दौरान भी UI पर मध्यवर्ती आउटपुट भेज सकते हैं, ताकि उपयोगकर्ता अंतिम परिणाम की प्रतीक्षा करने के बजाय शेल कमांड का stdout, बिल्ड के लॉग या डाउनलोड के बाइट्स को लाइव देख सके। आउटपुट आते ही ToolContext::emit_progress को कॉल करें:
use adk_core::{Result, Tool, ToolContext};
use std::sync::Arc;
#[async_trait::async_trait]
impl Tool for BuildTool {
// ... name(), description(), parameters_schema() ...
async fn execute(&self, ctx: Arc<dyn ToolContext>, args: serde_json::Value) -> Result<serde_json::Value> {
// Emit chunks as they arrive — each becomes a partial Event on the
// agent's EventStream, the SAME stream the model's reply travels on.
ctx.emit_progress("stdout", "Compiling project...\n").await;
ctx.emit_progress("stdout", "Build finished in 4.2s\n").await;
ctx.emit_progress("stderr", "warning: unused variable `x`\n").await;
// The final return value is still the complete result the model consumes.
Ok(serde_json::json!({ "status": "ok", "warnings": 1 }))
}
}
हस्ताक्षर:
async fn emit_progress(&self, stream: &str, chunk: &str)
stream— chunk के लिए एक लेबल:"stdout","stderr", या कोई कस्टम चैनल।chunk— उत्सर्जित किया जाने वाला टेक्स्ट (टर्मिनल-शैली के आउटपुट के लिए प्रत्येक पंक्ति पर उत्सर्जित करें)।
यह UI तक कैसे पहुँचता है। फ्रेमवर्क प्रत्येक chunk को एजेंट के EventStream पर एक आंशिक Event के रूप में अग्रेषित करता है। कोई उपभोक्ता इसे event.tool_progress_stream() से पहचानता है और इसे लाइव रेंडर करता है। कोई दूसरा चैनल नहीं है और न ही लॉग स्क्रैपिंग — प्रगति, मॉडल टेक्स्ट और अंतिम टूल परिणाम सभी एक ही क्रमबद्ध स्ट्रीम पर आते हैं।
पिछड़े संस्करणों के साथ संगत। डिफ़ॉल्ट emit_progress नो-ऑप है, इसलिए स्ट्रीम न करने वाले मौजूदा टूल और रनर अप्रभावित रहते हैं। केवल वे टूल जो इसे सक्षम करते हैं, प्रगति उत्सर्जित करते हैं, और केवल वे उपभोक्ता जो tool_progress_stream() की जाँच करते हैं, इसे देखते हैं।
प्रगति सीमित और हानिपूर्ण होती है। कोई टूल क्लाइंट द्वारा उसे ग्रहण करने की गति से अधिक तेज़ी से आउटपुट उत्पन्न कर सकता है — जैसे कंपाइलर लॉग, शेल कमांड, या नियंत्रण से बाहर लूप — इसलिए फ़्रेमवर्क असीमित रूप से बढ़ने देने के बजाय, अपने पास रखने और आगे भेजने वाली सामग्री की अधिकतम सीमा तय करता है:
| सीमा | मान | इसके पार होने पर |
|---|---|---|
| प्रति टूल बैच कतार की गहराई | 256 घटनाएँ | टूल स्थान के लिए अधिकतम 100 मिलीसेकंड तक प्रतीक्षा करता है, फिर चंक छोड़ दिया जाता है |
| प्रति चंक बाइट्स | 8 KiB | चंक को वर्ण सीमा पर छोटा कर दिया जाता है |
| प्रति टूल कॉल बाइट्स | 1 MiB | शेष प्रगति अग्रेषित नहीं की जाती |
इनमें से किसी भी कारण से आउटपुट हटाए जाने पर, उस कॉल के लिए [adk: tool progress truncated] पाठ वाला ठीक एक प्रगति इवेंट उत्सर्जित किया जाता है, इसलिए अंतर हमेशा दिखाई देता है, मौन नहीं रहता। इस प्रकार धीमा उपभोक्ता टूल को थोड़ी देर के लिए धीमा कर सकता है, लेकिन उसे कभी भी अनिश्चितकाल तक रोक नहीं सकता या मेमोरी समाप्त नहीं कर सकता।
ये सीमाएँ केवल प्रगति पर लागू होती हैं। टूल का अंतिम परिणाम प्रभावित नहीं होता, इसलिए यदि यह आपके लिए महत्वपूर्ण है तो बड़े परिणामों को टूल के अंदर ही छोटा करें।
एक पूर्ण वेब UI के लिए
streaming_bashउदाहरण देखें, जो लाइवbashआउटपुट और एकल-प्रयोग वाले टूल परिणाम (read_file,grep,glob) को एक ही इवेंट फ़ीड से रेंडर करता है। स्ट्रीमिंगbashटूल स्वयंadk-devtoolsमें मौजूद है।
उदाहरण चलाएँ
cargo adk new tool_agent --template tools
cd tool_agent
cargo run
सर्वोत्तम प्रथाएँ
- स्पष्ट विवरण - LLM को यह समझने में सहायता करें कि टूल का उपयोग कब करना है
- इनपुट मान्य करें - अनुपलब्ध पैरामीटर के लिए उपयोगी त्रुटि संदेश लौटाएँ
- संरचित JSON लौटाएँ - स्पष्ट फ़ील्ड नामों का उपयोग करें
- टूल को केंद्रित रखें - प्रत्येक टूल को एक काम अच्छी तरह करना चाहिए
- स्कीमा का उपयोग करें - जटिल टूल के लिए पैरामीटर स्कीमा परिभाषित करें
- सुरक्षित केवल-पठन टूल को चिह्नित करें -
.with_read_only(true)और.with_concurrency_safe(true)दोनों सेट करें, ताकिAutoडिस्पैच उन्हें अपने समवर्ती उपसमुच्चय में शामिल कर सके
टूल मेटाडेटा: केवल-पठन और समवर्तीता
अधिक बुद्धिमान डिस्पैच सक्षम करने के लिए टूल को केवल-पठन या समवर्तीता-सुरक्षित के रूप में चिह्नित करें:
// A lookup tool that performs no side effects
let lookup = FunctionTool::new("lookup", "Look up data", |_ctx, args| async move {
Ok(json!({"result": "cached data"}))
})
.with_read_only(true)
.with_concurrency_safe(true); // Auto mode requires both signals
// A mutation tool (defaults: read_only=false, concurrency_safe=false)
let update = FunctionTool::new("update", "Update record", |_ctx, args| async move {
Ok(json!({"updated": true}))
});
जब ToolExecutionStrategy::Auto सक्रिय होता है, तो डिस्पैच लूप पहले उन कॉल को समवर्ती रूप से चलाता है जिनके चयनित टूल is_read_only() और is_concurrency_safe() दोनों से true लौटाते हैं। इसके बाद वह शेष सभी कॉल को क्रमिक रूप से निष्पादित करता है। ToolExecutionStrategy::Parallel एक स्पष्ट ओवरराइड है जो इन संकेतों को दरकिनार करता है, इसलिए समवर्तीता की सुरक्षा की ज़िम्मेदारी उसके कॉलर की होती है।
SimpleToolContext: एजेंट लूप के बाहर टूल का उपयोग करना
जब आपको agent loop के बाहर किसी tool को कॉल करने की आवश्यकता हो (testing, MCP server mode, sub-agent delegation), तो पूरी ToolContext trait hierarchy को लागू करने के बजाय SimpleToolContext का उपयोग करें:
use adk_tool::SimpleToolContext;
use adk_core::ToolContext;
use std::sync::Arc;
// Construct with just a caller name — all other fields get sensible defaults
let ctx = SimpleToolContext::new("my-test-harness");
// Optionally override the function call ID
let ctx = SimpleToolContext::new("my-mcp-server")
.with_function_call_id("custom-call-id");
// Bind a session ID so session-aware tools (and MCP servers that key state by
// session) see a stable identifier instead of the empty default.
let ctx = SimpleToolContext::new("my-mcp-server")
.with_session_id("session-42");
// Use it to execute any tool
let tool_ctx: Arc<dyn ToolContext> = Arc::new(ctx);
let result = my_tool.execute(tool_ctx, json!({"key": "value"})).await?;
डिफ़ॉल्ट: user_id() → "anonymous", session_id() / branch() → "", artifacts() → None, search_memory() → empty vec। invocation_id और function_call_id दोनों स्वचालित रूप से जनरेट किए गए UUIDs हैं। जब कोई tool प्रति session state को route या persist करता हो, तब with_session_id(...) के साथ वास्तविक session सेट करें।
StatefulTool: Invocations के बीच साझा State
ऐसे tools के लिए जिन्हें calls के बीच state बनाए रखने की आवश्यकता होती है (counters, caches, connection pools), StatefulTool<S> का उपयोग करें:
use adk_tool::StatefulTool;
use adk_core::ToolContext;
use std::sync::Arc;
use tokio::sync::RwLock;
struct AppCache {
entries: RwLock<HashMap<String, String>>,
}
let cache = Arc::new(AppCache {
entries: RwLock::new(HashMap::new()),
});
let cache_tool = StatefulTool::new(
"cache_lookup",
"Look up a value in the application cache",
cache.clone(),
|state, _ctx, args| async move {
let key = args["key"].as_str().unwrap_or("");
let entries = state.entries.read().await;
let value = entries.get(key).cloned().unwrap_or_default();
Ok(json!({"key": key, "value": value}))
},
)
.with_read_only(true)
.with_concurrency_safe(true);
StatefulTool प्रत्येक invocation पर Arc<S> को clone करता है (सिर्फ़ reference count में मामूली वृद्धि), इसलिए सभी executions एक ही underlying state साझा करते हैं। यह FunctionTool जैसी builder methods को support करता है: with_long_running, with_parameters_schema, with_response_schema, with_scopes, with_read_only, और with_concurrency_safe।
संबंधित
- Built-in Tools - पहले से निर्मित tools (GoogleSearch, ExitLoop)
- MCP Tools - Model Context Protocol integration
- LlmAgent - agents में tools जोड़ना
Multimodal Function Responses
Gemini 3 models function responses में केवल JSON ही नहीं, बल्कि images, audio, PDFs, और file references भी प्राप्त करने का support करते हैं। Tools अपने JSON return value में inline_data और/या file_data arrays शामिल करके multimodal data लौटाए जा सकते हैं:
/// Tool that returns a chart image alongside JSON metadata.
async fn generate_chart(
_ctx: Arc<dyn ToolContext>,
args: serde_json::Value,
) -> Result<serde_json::Value> {
let png_bytes: Vec<u8> = render_chart(&args);
// Include inline_data in the return value — the framework extracts it automatically
Ok(json!({
"response": {
"title": "Q4 Sales",
"chart_type": "bar"
},
"inline_data": [{
"mime_type": "image/png",
"data": png_bytes
}]
}))
}
Framework स्वचालित रूप से:
FunctionResponseData::from_tool_result()के माध्यम सेinline_data/file_dataका पता लगाता है- Inline binary data को Base64-encode करता है
- Parts को
functionResponsewire object के अंदर nest करता है (Gemini 3 API format से मेल खाते हुए)
File References
बाहरी रूप से संग्रहीत बड़ी files के लिए, bytes embed करने के बजाय URI के साथ file_data का उपयोग करें:
Ok(json!({
"response": { "document_id": "report-2024", "pages": 12 },
"file_data": [{
"mime_type": "application/pdf",
"file_uri": "gs://my-bucket/reports/report-2024.pdf"
}]
}))
प्रत्यक्ष निर्माण
फ़्रेमवर्क-स्तरीय कोड (कस्टम एजेंट, रूपांतरण परतों) के लिए, FunctionResponseData का सीधे निर्माण करें:
use adk_core::{FunctionResponseData, InlineDataPart, FileDataPart};
// JSON + inline image
let frd = FunctionResponseData::with_inline_data(
"chart_tool",
json!({"title": "Q4 Chart"}),
vec![InlineDataPart { mime_type: "image/png".into(), data: png_bytes }],
);
// JSON + file reference
let frd = FunctionResponseData::with_file_data(
"doc_tool",
json!({"status": "ok"}),
vec![FileDataPart { mime_type: "application/pdf".into(), file_uri: "gs://bucket/file.pdf".into() }],
);
// JSON + both
let frd = FunctionResponseData::with_multimodal("tool", json, inline_parts, file_parts);
नोट: बहु-माध्यम फ़ंक्शन प्रतिक्रियाओं के लिए Gemini 3 श्रृंखला के मॉडल, जैसे
gemini-3.7-flash, आवश्यक हैं। पुराने मॉडल 400 त्रुटि लौटाते हैं।
पूर्णतः कार्यशील उदाहरण के लिए examples/multimodal_function_response/ देखें।
पिछला: ← mistral.rs | अगला: अंतर्निर्मित उपकरण →