स्कीमा सामान्यीकरण
ADK-Rust अनुरोध के समय प्रत्येक LLM प्रदाता के लिए MCP टूल स्कीमा को स्वचालित रूप से सामान्यीकृत करता है। इसका अर्थ है कि MCP टूल Gemini, OpenAI, Anthropic और अन्य प्रदाताओं में बिना मैन्युअल स्कीमा समायोजन के सहज रूप से काम करते हैं।
यह कैसे काम करता है
MCP Server → raw JSON Schema → McpToolset (stores verbatim)
↓
Model.generate_content()
↓
SchemaAdapter.normalize_schema()
↓
Provider API (Gemini/OpenAI/Anthropic)
- McpToolset टूल खोजता है और उनके मूल
inputSchemaको बिना किसी बदलाव के संग्रहीत करता है - जब मॉडल अनुरोध बनाता है, तो वह प्रत्येक टूल के स्कीमा पर
schema_adapter().normalize_schema()को कॉल करता है - प्रत्येक प्रदाता का अपना अडैप्टर होता है, जो केवल उन्हीं रूपांतरणों को लागू करता है जिनकी उसके API को आवश्यकता होती है
- अनावश्यक सामान्यीकरण से बचने के लिए परिणामों को सामग्री हैश द्वारा कैश किया जाता है
प्रदाता का व्यवहार
| सुविधा | Gemini | OpenAI सख्त | OpenAI | Anthropic | Generic |
|---|---|---|---|---|---|
$ref रिज़ॉल्यूशन | ✅ इनलाइन करता है | ❌ संरक्षित रखता है | ❌ संरक्षित रखता है | ❌ संरक्षित रखता है | ❌ संरक्षित रखता है |
anyOf/oneOf | समेटता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है |
allOf | विलय करता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है |
additionalProperties | हटाता है | false सेट करता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है |
| प्रकार सारणियाँ | संक्षिप्त करता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है | संरक्षित रखता है |
$schema | हटाता है | हटाता है | हटाता है | हटाता है | हटाता है |
if/then/else | हटा देता है | हटा देता है | हटा देता है | हटा देता है | हटा देता है |
const | → enum | → enum | → enum | सुरक्षित रखता है | → enum |
असमर्थित format | हटा देता है | हटा देता है | हटा देता है | सुरक्षित रखता है | हटा देता है |
| नेस्टिंग गहराई सीमा | 5 स्तर | कोई नहीं | कोई नहीं | कोई नहीं | कोई नहीं |
exclusiveMin/Max | हटाता है | सुरक्षित रखता है | सुरक्षित रखता है | सुरक्षित रखता है | सुरक्षित रखता है |
SchemaAdapter ट्रेट
सभी एडेप्टर adk-core से इस ट्रेट को लागू करते हैं:
use serde_json::Value;
use std::borrow::Cow;
pub trait SchemaAdapter: Send + Sync + std::fmt::Debug {
/// Normalize a raw JSON Schema for this provider.
fn normalize_schema(&self, schema: Value) -> Value;
/// Normalize a tool name (default: truncate to 64 bytes at UTF-8 boundary).
fn normalize_tool_name<'a>(&self, name: &'a str) -> Cow<'a, str>;
/// Fallback schema when no parameters_schema is provided.
fn empty_schema(&self) -> Value;
}
प्रत्येक Llm इम्प्लीमेंटेशन schema_adapter() के माध्यम से अपना एडेप्टर लौटाता है:
use adk_core::Llm;
let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;
let adapter = model.schema_adapter(); // Returns &GeminiSchemaAdapter
उपलब्ध एडेप्टर
GeminiSchemaAdapter
सबसे आक्रामक एडेप्टर। Gemini के फ़ंक्शन-कॉलिंग API के लिए आवश्यक सभी विनाशकारी रूपांतरण लागू करता है:
use adk_gemini::schema_adapter::GeminiSchemaAdapter;
use adk_core::SchemaAdapter;
// Standard Gemini API
let adapter = GeminiSchemaAdapter::new();
// Vertex AI (sets additionalProperties: false instead of removing)
let adapter = GeminiSchemaAdapter::vertex_ai();
रूपांतरण पाइपलाइन:
$refको हल करें (डिफ़िनिशन से इनलाइन करें, गहराई 10 पर चक्रों को तोड़ें)$schemaहटाएँanyOf/oneOfको संक्षिप्त करें → पहला गैर-नल सब-स्कीमाallOfसब-स्कीमा मर्ज करें- टाइप ऐरे संक्षिप्त करें (
["string", "null"]→"string") if/then/elseहटाएँconstको एकल-तत्वenumमें बदलेंenumऐरे से नल हटाएँ- निहित
type: "object"जोड़ें - असमर्थित कीवर्ड हटाएँ
- असमर्थित
formatमान हटाएँ - नेस्टिंग गहराई लागू करें (5 स्तर)
definitions/$defsहटाएँ
OpenAiStrictSchemaAdapter
स्ट्रक्चर्ड आउटपुट के लिए additionalProperties: false जोड़ते हुए स्कीमा संरचना को सुरक्षित रखता है:
use adk_model::openai::OpenAiStrictSchemaAdapter;
use adk_core::SchemaAdapter;
let adapter = OpenAiStrictSchemaAdapter;
OpenAiSchemaAdapter
गैर-सख्त मोड के लिए न्यूनतम सुरक्षित सुधार:
use adk_model::openai::OpenAiSchemaAdapter;
let adapter = OpenAiSchemaAdapter;
AnthropicSchemaAdapter
लगभग पास-थ्रू — Anthropic अधिकांश JSON Schema सुविधाओं का समर्थन करता है:
use adk_model::anthropic::AnthropicSchemaAdapter;
let adapter = AnthropicSchemaAdapter;
GenericSchemaAdapter
अज्ञात प्रदाताओं (Ollama, DeepSeek आदि) के लिए डिफ़ॉल्ट:
use adk_core::GenericSchemaAdapter;
let adapter = GenericSchemaAdapter;
स्कीमा कैशिंग
अनावश्यक गणना से बचने के लिए सामान्यीकृत स्कीमा को कंटेंट हैश द्वारा कैश किया जाता है:
use adk_core::{GenericSchemaAdapter, SchemaCache};
use serde_json::json;
use std::sync::Arc;
let cache = SchemaCache::for_adapter(Arc::new(GenericSchemaAdapter));
let schema = json!({"type": "object", "properties": {"name": {"type": "string"}}});
// First call normalizes and caches
let result = cache.normalize(&schema);
// Subsequent calls return cached result (no re-normalization)
let cached = cache.normalize(&schema);
// Invalidate when tools change
cache.clear();
प्रत्येक कैश एक एडेप्टर इंस्टेंस का स्वामी होता है, इसलिए अलग-अलग प्रदाताओं या एडेप्टर कॉन्फ़िगरेशन के लिए सामान्यीकृत प्रविष्टियाँ आपस में टकरा नहीं सकतीं। प्रदाता क्लाइंट generate_content() के दौरान इन कैश का स्वचालित रूप से उपयोग करते हैं।
टूल नामों का संक्षिप्तीकरण
सभी एडेप्टर 64 बाइट से अधिक लंबाई वाले टूल नामों को मान्य UTF-8 वर्ण सीमाओं पर संक्षिप्त करते हैं:
use adk_core::SchemaAdapter;
use adk_gemini::schema_adapter::GeminiSchemaAdapter;
let adapter = GeminiSchemaAdapter::new();
// Short names pass through unchanged
let name = adapter.normalize_tool_name("get_weather");
assert_eq!(name, "get_weather");
// Long names are truncated to 64 bytes
let long = "mcp_server_github_com_organization_repository_pull_request_review_comments";
let truncated = adapter.normalize_tool_name(long);
assert!(truncated.len() <= 64);
// Multi-byte characters are never split
let emoji_name = "🔧_tool_名前が長い";
let result = adapter.normalize_tool_name(emoji_name);
assert!(std::str::from_utf8(result.as_bytes()).is_ok());
साझा यूटिलिटीज
adk_core::schema_utils मॉड्यूल कंपोज़ेबल ट्रांसफ़ॉर्म फ़ंक्शन प्रदान करता है, जिनका उपयोग एडेप्टर आंतरिक रूप से करते हैं:
use adk_core::schema_utils;
use serde_json::json;
let mut schema = json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"status": { "const": "active" },
"email": { "type": "string", "format": "hostname" }
},
"if": { "properties": { "x": { "type": "number" } } },
"then": { "required": ["x"] }
});
// Apply individual transforms
schema_utils::strip_schema_keyword(&mut schema);
schema_utils::strip_conditional_keywords(&mut schema);
schema_utils::convert_const_to_enum(&mut schema);
schema_utils::strip_unsupported_formats(&mut schema, &["date-time", "email", "uri"]);
उपलब्ध यूटिलिटी:
strip_schema_keyword—$schemaहटाता हैstrip_conditional_keywords—if/then/elseहटाता हैadd_implicit_object_type—propertiesमौजूद होने परtype: "object"जोड़ता हैconvert_const_to_enum—constको एकल-तत्व वालेenumमें परिवर्तित करता हैstrip_unsupported_formats— अनुमति-सूची में नहीं होने वाले फ़ॉर्मैट मान हटाता हैstrip_null_from_enum— enum ऐरे से null हटाता हैtruncate_tool_name— UTF-8 सीमा पर छोटा करता हैresolve_refs— डेफ़िनिशन से$refसंदर्भों को इनलाइन करता हैcollapse_combiners—anyOf/oneOfको पहले non-null मान में समेटता हैmerge_all_of—allOfसब-स्कीमा को मर्ज करता हैcollapse_type_arrays—["string", "null"]को"string"में समेटता हैenforce_nesting_depth— गहरे स्कीमा को{"type": "object"}से प्रतिस्थापित करता है
कस्टम एडेप्टर
कस्टम प्रदाताओं के लिए SchemaAdapter लागू करें:
use adk_core::{SchemaAdapter, schema_utils};
use serde_json::Value;
use std::borrow::Cow;
#[derive(Debug)]
struct MyProviderAdapter;
impl SchemaAdapter for MyProviderAdapter {
fn normalize_schema(&self, mut schema: Value) -> Value {
// Apply only the transforms your provider needs
schema_utils::strip_schema_keyword(&mut schema);
schema_utils::strip_conditional_keywords(&mut schema);
schema_utils::add_implicit_object_type(&mut schema);
// Keep everything else as-is
schema
}
}
उदाहरण
सभी एडेप्टर को कार्य करते हुए देखने के लिए स्कीमा सामान्यीकरण डेमो चलाएँ:
cd examples/schema_normalization
cargo run
किसी API कुंजी की आवश्यकता नहीं है — यह स्थानीय रूप से सामान्यीकरण लॉजिक प्रदर्शित करता है।
sanitize_schema से माइग्रेशन
यदि आपने पहले सेनेटाइज़ किए गए स्कीमा लौटाने वाले McpToolset पर निर्भर किया था:
- मानक उपयोग के लिए कोड में किसी बदलाव की आवश्यकता नहीं है।
Toolsettrait API अपरिवर्तित है। - अब स्कीमा को टूल रजिस्ट्रेशन के समय नहीं, बल्कि मॉडल एडेप्टर द्वारा अनुरोध के समय सामान्यीकृत किया जाता है।
- यदि आप
parameters_schema()को कॉल कर रहे थे और Gemini-फ़ॉर्मैट किए गए आउटपुट की अपेक्षा कर रहे थे, तो अब इसके बजाय रॉ स्कीमा लौटाया जाता है। आवश्यकता होने पर इसे स्वयं सामान्यीकृत करने के लिए उपयुक्तSchemaAdapterका उपयोग करें।