एआई एज फ़ंक्शन कॉलिंग एसडीके (एफ़सी एसडीके) एक लाइब्रेरी है. इसकी मदद से, डेवलपर डिवाइस पर मौजूद एलएलएम के साथ फ़ंक्शन कॉलिंग का इस्तेमाल कर सकते हैं. फ़ंक्शन कॉल करने की सुविधा की मदद से, मॉडल को बाहरी टूल और एपीआई से कनेक्ट किया जा सकता है. इससे मॉडल, ज़रूरी पैरामीटर के साथ खास फ़ंक्शन कॉल कर सकते हैं, ताकि असल दुनिया में कार्रवाइयां की जा सकें.
FC SDK का इस्तेमाल करने वाला एलएलएम, सिर्फ़ टेक्स्ट जनरेट करने के बजाय, किसी फ़ंक्शन के लिए स्ट्रक्चर्ड कॉल जनरेट कर सकता है. यह फ़ंक्शन, अप-टू-डेट जानकारी खोजने, अलार्म सेट करने या बुकिंग करने जैसी कोई कार्रवाई करता है.
इस गाइड में, Android ऐप्लिकेशन में FC SDK टूल के साथ LLM इंफ़रेंस एपीआई को जोड़ने के लिए, शुरुआती बुनियादी जानकारी दी गई है. इस गाइड में, डिवाइस पर मौजूद एलएलएम में फ़ंक्शन कॉल करने की सुविधाएं जोड़ने के बारे में बताया गया है. LLM Inference API का इस्तेमाल करने के बारे में ज़्यादा जानकारी के लिए, Android के लिए LLM Inference की गाइड देखें.
क्विकस्टार्ट
अपने Android ऐप्लिकेशन में FC SDK टूल का इस्तेमाल करने के लिए, यह तरीका अपनाएं. यह तुरंत शुरू करने वाला ट्यूटोरियल, Hammer 2.1 (1.5B) के साथ LLM Inference API का इस्तेमाल करता है. LLM Inference API, Pixel 8 और Samsung S23 या उसके बाद के वर्शन वाले हाई-एंड Android डिवाइसों के लिए ऑप्टिमाइज़ किया गया है. यह डिवाइस एम्युलेटर के साथ काम नहीं करता.
डिपेंडेंसी जोड़ें
FC SDK टूल, com.google.ai.edge.localagents:localagents-fc
लाइब्रेरी का इस्तेमाल करता है और
LLM इंफ़रेंस एपीआई, com.google.mediapipe:tasks-genai
लाइब्रेरी का इस्तेमाल करता है. अपने Android ऐप्लिकेशन की build.gradle
फ़ाइल में, दोनों डिपेंडेंसी जोड़ें:
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.24'
implementation 'com.google.ai.edge.localagents:localagents-fc:0.1.0'
}
Android 12 (एपीआई 31) या इसके बाद के वर्शन वाले डिवाइसों के लिए, नेटिव OpenCL लाइब्रेरी डिपेंडेंसी जोड़ें. ज़्यादा जानकारी के लिए, uses-native-library
टैग के दस्तावेज़ देखें.
AndroidManifest.xml
फ़ाइल में ये uses-native-library
टैग जोड़ें:
<uses-native-library android:name="libOpenCL.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false"/>
मॉडल डाउनलोड करना
Hugging Face से, आठ बिट के क्वांटाइज़ किए गए फ़ॉर्मैट में Hammer 1B डाउनलोड करें. उपलब्ध मॉडल के बारे में ज़्यादा जानकारी के लिए, मॉडल का दस्तावेज़ देखें.
hammer2.1_1.5b_q8_ekv4096.task
फ़ोल्डर के कॉन्टेंट को Android डिवाइस पर पुश करें.
$ adb shell rm -r /data/local/tmp/llm/ # Remove any previously loaded models
$ adb shell mkdir -p /data/local/tmp/llm/
$ adb push hammer2.1_1.5b_q8_ekv4096.task /data/local/tmp/llm/hammer2.1_1.5b_q8_ekv4096.task
फ़ंक्शन की परिभाषाएं तय करना
वे फ़ंक्शन तय करें जिन्हें मॉडल के लिए उपलब्ध कराया जाएगा. प्रोसेस को समझाने के लिए, इस क्विकस्टार्ट में स्टैटिक तरीकों के तौर पर दो फ़ंक्शन शामिल किए गए हैं. ये फ़ंक्शन, हार्ड कोड किए गए जवाब दिखाते हैं. ज़्यादा व्यावहारिक तरीके से लागू करने के लिए, ऐसे फ़ंक्शन तय किए जाएंगे जो किसी REST API को कॉल करते हैं या किसी डेटाबेस से जानकारी हासिल करते हैं.
getWeather
और getTime
फ़ंक्शन के बारे में यहां बताया गया है:
class ToolsForLlm {
public static String getWeather(String location) {
return "Cloudy, 56°F";
}
public static String getTime(String timezone) {
return "7:00 PM " + timezone;
}
private ToolsForLlm() {}
}
हर फ़ंक्शन के बारे में बताने के लिए, FunctionDeclaration
का इस्तेमाल करें. साथ ही, हर फ़ंक्शन को एक नाम और जानकारी दें. साथ ही, फ़ंक्शन के टाइप की जानकारी दें. इससे मॉडल को यह जानकारी मिलती है कि फ़ंक्शन क्या करते हैं और फ़ंक्शन कॉल कब करने हैं.
var getWeather = FunctionDeclaration.newBuilder()
.setName("getWeather")
.setDescription("Returns the weather conditions at a location.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"location",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The location for the weather report.")
.build())
.build())
.build();
var getTime = FunctionDeclaration.newBuilder()
.setName("getTime")
.setDescription("Returns the current time in the given timezone.")
.setParameters(
Schema.newBuilder()
.setType(Type.OBJECT)
.putProperties(
"timezone",
Schema.newBuilder()
.setType(Type.STRING)
.setDescription("The timezone to get the time from.")
.build())
.build())
.build();
Tool
ऑब्जेक्ट में फ़ंक्शन के एलान जोड़ें:
var tool = Tool.newBuilder()
.addFunctionDeclarations(getWeather)
.addFunctionDeclarations(getTime)
.build();
अनुमान लगाने वाला बैकएंड बनाना
LLM Inference API का इस्तेमाल करके, अनुमान लगाने वाला बैकएंड बनाएं और उसे अपने मॉडल के लिए फ़ॉर्मैटर ऑब्जेक्ट पास करें. FC SDK फ़ॉर्मैटर (ModelFormatter
), फ़ॉर्मैटर और पार्सर, दोनों के तौर पर काम करता है. इस क्विकस्टार्ट में Gemma-3 1B का इस्तेमाल किया गया है. इसलिए, हम इनका इस्तेमाल करेंगे
GemmaFormatter
:
var llmInferenceOptions = LlmInferenceOptions.builder()
.setModelPath(modelFile.getAbsolutePath())
.build();
var llmInference = LlmInference.createFromOptions(context, llmInferenceOptions);
var llmInferenceBackend = new llmInferenceBackend(llmInference, new GemmaFormatter());
ज़्यादा जानकारी के लिए, एलएलएम इनफ़रेंस कॉन्फ़िगरेशन के विकल्प देखें.
मॉडल को इंस्टैंशिएट करना
अनुमान लगाने वाले बैकएंड, सिस्टम के प्रॉम्प्ट, और टूल को कनेक्ट करने के लिए, GenerativeModel
ऑब्जेक्ट का इस्तेमाल करें. हमारे पास पहले से ही अनुमान लगाने की सुविधा और टूल मौजूद हैं. इसलिए, हमें सिर्फ़ सिस्टम प्रॉम्प्ट बनाना होगा:
var systemInstruction = Content.newBuilder()
.setRole("system")
.addParts(Part.newBuilder().setText("You are a helpful assistant."))
.build();
GenerativeModel
की मदद से मॉडल को इंस्टैंशिएट करें:
var generativeModel = new GenerativeModel(
llmInferenceBackend,
systemInstruction,
List.of(tool),
)
चैट सेशन शुरू करना
आसानी से इस्तेमाल करने के लिए, इस क्विकस्टार्ट में एक चैट सेशन शुरू किया जाता है. आपके पास एक से ज़्यादा सेशन बनाने का विकल्प भी होता है.
GenerativeModel
के नए इंस्टेंस का इस्तेमाल करके, चैट सेशन शुरू करें:
var chat = generativeModel.startChat();
चैट सेशन के ज़रिए मॉडल को प्रॉम्प्ट भेजने के लिए, sendMessage
इस तरीके का इस्तेमाल करें:
var response = chat.sendMessage("How's the weather in San Francisco?");
मॉडल के जवाब को पार्स करना
मॉडल को प्रॉम्प्ट देने के बाद, ऐप्लिकेशन को जवाब की जांच करनी चाहिए, ताकि यह तय किया जा सके कि फ़ंक्शन कॉल करना है या सामान्य भाषा में टेक्स्ट दिखाना है.
// Extract the model's message from the response.
var message = response.getCandidates(0).getContent().getParts(0);
// If the message contains a function call, execute the function.
if (message.hasFunctionCall()) {
var functionCall = message.getFunctionCall();
var args = functionCall.getArgs().getFieldsMap();
var result = null;
// Call the appropriate function.
switch (functionCall.getName()) {
case "getWeather":
result = ToolsForLlm.getWeather(args.get("location").getStringValue());
break;
case "getTime":
result = ToolsForLlm.getWeather(args.get("timezone").getStringValue());
break;
default:
throw new Exception("Function does not exist:" + functionCall.getName());
}
// Return the result of the function call to the model.
var functionResponse =
FunctionResponse.newBuilder()
.setName(functionCall.getName())
.setResponse(
Struct.newBuilder()
.putFields("result", Value.newBuilder().setStringValue(result).build()))
.build();
var functionResponseContent = Content.newBuilder()
.setRole("user")
.addParts(Part.newBuilder().setFunctionResponse(functionResponse))
.build();
var response = chat.sendMessage(functionResponseContent);
} else if (message.hasText()) {
Log.i(message.getText());
}
सैंपल कोड को बहुत आसानी से लागू किया जा सकता है. किसी ऐप्लिकेशन के मॉडल के रिस्पॉन्स की जांच करने के तरीके के बारे में ज़्यादा जानने के लिए, फ़ॉर्मैट करना और पार्स करना लेख पढ़ें.
यह कैसे काम करता है
इस सेक्शन में, Android के लिए फ़ंक्शन कॉलिंग SDK टूल के मुख्य कॉन्सेप्ट और कॉम्पोनेंट के बारे में ज़्यादा जानकारी दी गई है.
मॉडल
फ़ंक्शन कॉलिंग SDK के लिए, फ़ॉर्मैटर और पार्स करने वाले टूल के साथ मॉडल की ज़रूरत होती है. FC SDK टूल में, इन मॉडल के लिए पहले से मौजूद फ़ॉर्मैटर और पार्स करने वाला टूल शामिल होता है:
- Gemma:
GemmaFormatter
का इस्तेमाल करें. - Llama:
LlamaFormatter
का इस्तेमाल करें. - हथौड़ा:
HammerFormatter
का इस्तेमाल करें.
FC SDK टूल के साथ किसी दूसरे मॉडल का इस्तेमाल करने के लिए, आपको अपना फ़ॉर्मैटर और पार्स करने वाला टूल बनाना होगा. यह टूल, LLM Inference API के साथ काम करना चाहिए.
फ़ॉर्मैटिंग और पार्स करना
फ़ंक्शन कॉल करने की सुविधा के लिए, प्रॉम्प्ट को फ़ॉर्मैट करना और मॉडल के आउटपुट को पार्स करना ज़रूरी है. ये दोनों अलग-अलग प्रोसेस हैं, लेकिन FC SDK टूल, ModelFormatter
इंटरफ़ेस की मदद से फ़ॉर्मैटिंग और पार्स करने, दोनों काम करता है.
फ़ॉर्मैटर, स्ट्रक्चर्ड फ़ंक्शन के एलान को टेक्स्ट में बदलने, फ़ंक्शन के जवाबों को फ़ॉर्मैट करने, और बातचीत के चरणों की शुरुआत और आखिर में टोक़न डालने के लिए ज़िम्मेदार होता है. साथ ही, वह उन चरणों की भूमिकाओं (उदाहरण के लिए, "उपयोगकर्ता", "मॉडल") के बारे में भी बताता है.
यह पता लगाने की ज़िम्मेदारी पार्सर की होती है कि मॉडल के जवाब में फ़ंक्शन कॉल है या नहीं. अगर पार्स करने वाले टूल को किसी फ़ंक्शन कॉल का पता चलता है, तो वह उसे स्ट्रक्चर्ड डेटा टाइप में पार्स कर देता है. ऐसा न होने पर, यह टेक्स्ट को सामान्य भाषा के जवाब के तौर पर इस्तेमाल करता है.
सीमित डिकोडिंग
सीमित डिकोडिंग एक ऐसी तकनीक है जो एलएलएम के आउटपुट जनरेशन को गाइड करती है, ताकि यह पक्का किया जा सके कि वह पहले से तय किए गए स्ट्रक्चर्ड फ़ॉर्मैट का पालन करता है. जैसे, JSON ऑब्जेक्ट या Python फ़ंक्शन कॉल. इन पाबंदियों को लागू करके, मॉडल अपने आउटपुट को इस तरह से फ़ॉर्मैट करता है कि वे पहले से तय फ़ंक्शन और उनके पैरामीटर टाइप के हिसाब से अलाइन हो जाएं.
सीमित डेकोडिंग की सुविधा चालू करने के लिए, ConstraintOptions
ऑब्जेक्ट में सीमाएं तय करें और ChatSession
इंस्टेंस के enableConstraint
तरीके को लागू करें.
इस पाबंदी को चालू करने पर, जवाब में सिर्फ़ GenerativeModel
से जुड़े टूल शामिल किए जा सकेंगे.
यहां दिए गए उदाहरण में, टूल कॉल के रिस्पॉन्स पर पाबंदी लगाने के लिए, सीमित डिकोडिंग को कॉन्फ़िगर करने का तरीका बताया गया है. इससे टूल कॉल, प्रीफ़िक्स ```tool_code\n
से शुरू और सफ़िक्स \n```
पर खत्म होता है.
ConstraintOptions constraintOptions = ConstraintOptions.newBuilder()
.setToolCallOnly( ConstraintOptions.ToolCallOnly.newBuilder()
.setConstraintPrefix("```tool_code\n")
.setConstraintSuffix("\n```"))
.build();
chatSession.enableConstraint(constraintOptions);
उसी सेशन में चालू पाबंदी को बंद करने के लिए, disableConstraint
तरीके का इस्तेमाल करें:
chatSession.disableConstraint();