Multimodal Live API की मदद से, Gemini के साथ कम इंतज़ार के साथ, दोनों तरफ़ से आवाज़ और वीडियो के ज़रिए इंटरैक्ट किया जा सकता है. Multimodal Live API का इस्तेमाल करके, उपयोगकर्ताओं को नैचुरल और इंसानों जैसी आवाज़ में बातचीत करने का अनुभव दिया जा सकता है. साथ ही, बोलकर दिए गए निर्देशों का इस्तेमाल करके, मॉडल के जवाबों में रुकावट डाली जा सकती है. यह मॉडल, टेक्स्ट, ऑडियो, और वीडियो इनपुट को प्रोसेस कर सकता है. साथ ही, यह टेक्स्ट और ऑडियो आउटपुट दे सकता है.
मल्टीमॉडल लाइव एपीआई को Google AI Studio में आज़माया जा सकता है.
Multimodal Live API का इस्तेमाल करना
इस सेक्शन में, हमारे किसी SDK टूल के साथ मल्टीमोडल लाइव एपीआई का इस्तेमाल करने का तरीका बताया गया है. WebSockets API के बारे में ज़्यादा जानकारी के लिए, नीचे दिया गया WebSockets API रेफ़रंस देखें.
मैसेज भेजना और पाना
import asyncio
from google import genai
client = genai.Client(api_key="GEMINI_API_KEY", http_options={'api_version': 'v1alpha'})
model = "gemini-2.0-flash-exp"
config = {"response_modalities": ["TEXT"]}
async def main():
async with client.aio.live.connect(model=model, config=config) as session:
while True:
message = input("User> ")
if message.lower() == "exit":
break
await session.send(input=message, end_of_turn=True)
async for response in session.receive():
if response.text is not None:
print(response.text, end="")
if __name__ == "__main__":
asyncio.run(main())
ऑडियो पाना
इस उदाहरण में, ऑडियो डेटा पाने और उसे .wav
फ़ाइल में लिखने का तरीका बताया गया है.
import asyncio
import wave
from google import genai
client = genai.Client(api_key="GEMINI_API_KEY", http_options={'api_version': 'v1alpha'})
model = "gemini-2.0-flash-exp"
config = {"response_modalities": ["AUDIO"]}
async def main():
async with client.aio.live.connect(model=model, config=config) as session:
wf = wave.open("audio.wav", "wb")
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(24000)
message = "Hello? Gemini are you there?"
await session.send(input=message, end_of_turn=True)
async for idx,response in async_enumerate(session.receive()):
if response.data is not None:
wf.writeframes(response.data)
# Comment this out to print audio data info
# if response.server_content.model_turn is not None:
# print(response.server_content.model_turn.parts[0].inline_data.mime_type)
wf.close()
if __name__ == "__main__":
asyncio.run(main())
ऑडियो फ़ॉर्मैट
Multimodal Live API, इन ऑडियो फ़ॉर्मैट के साथ काम करता है:
- इनपुट ऑडियो फ़ॉर्मैट: 16kHz के लिटल-इंडियन फ़ॉर्मैट में रॉ 16 बिट PCM ऑडियो
- आउटपुट ऑडियो फ़ॉर्मैट: 24kHz के लिटल-इंडियन फ़ॉर्मैट में रॉ 16 बिट PCM ऑडियो
ऑडियो और वीडियो स्ट्रीम करना
सिस्टम से जुड़े निर्देश
सिस्टम के निर्देशों की मदद से, अपनी ज़रूरतों और इस्तेमाल के उदाहरणों के आधार पर, मॉडल के व्यवहार को कंट्रोल किया जा सकता है. सेटअप कॉन्फ़िगरेशन में सिस्टम के निर्देश सेट किए जा सकते हैं. ये निर्देश पूरे सेशन के लिए लागू रहेंगे.
from google.genai import types
config = {
"system_instruction": types.Content(
parts=[
types.Part(
text="You are a helpful assistant and answer in a friendly tone."
)
]
),
"response_modalities": ["TEXT"],
}
कॉन्टेंट के इंक्रीमेंटल अपडेट
टेक्स्ट इनपुट भेजने, सेशन का कॉन्टेक्स्ट सेट करने या सेशन का कॉन्टेक्स्ट वापस लाने के लिए, इंक्रीमेंटल अपडेट का इस्तेमाल करें. कम शब्दों वाले कॉन्टेक्स्ट के लिए, इवेंट के सटीक क्रम को दिखाने के लिए, बारी-बारी से इंटरैक्शन भेजे जा सकते हैं:
Python
from google.genai import types
turns = [
types.Content(parts=[types.Part(text="What is the capital of France?")], role="user"),
types.Content(parts=[types.Part(text="Paris")], role="model")
]
await session.send(input=types.LiveClientContent(turns=turns))
turns = [types.Content(parts=[types.Part(text="What is the capital of Germany?")], role="user")]
await session.send(input=types.LiveClientContent(turns=turns, turn_complete=True))
JSON
{
"clientContent": {
"turns": [
{
"parts":[
{
"text": ""
}
],
"role":"user"
},
{
"parts":[
{
"text": ""
}
],
"role":"model"
}
],
"turnComplete": true
}
}
लंबे कॉन्टेक्स्ट के लिए, हमारा सुझाव है कि आप एक मैसेज की खास जानकारी दें, ताकि बाद के इंटरैक्शन के लिए कॉन्टेक्स्ट विंडो खाली हो सके.
आवाज़ बदलना
मल्टीमोडल लाइव एपीआई, इन आवाज़ों के साथ काम करता है: Aoede, Charon, Fenrir, Kore, और Puck.
किसी आवाज़ को सेट करने के लिए, सेशन कॉन्फ़िगरेशन के हिस्से के तौर पर, speechConfig
ऑब्जेक्ट में आवाज़ का नाम सेट करें:
Python
from google.genai import types
config = types.LiveConnectConfig(
response_modalities=["AUDIO"],
speech_config=types.SpeechConfig(
voice_config=types.VoiceConfig(
prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Kore")
)
)
)
JSON
{
"voiceConfig": {
"prebuiltVoiceConfig": {
"voiceName": "Kore"
}
}
}
फ़ंक्शन कॉल का इस्तेमाल करना
Multimodal Live API की मदद से, टूल तय किए जा सकते हैं. फ़ंक्शन कॉल करने के बारे में ज़्यादा जानने के लिए, फ़ंक्शन कॉल करने के बारे में ट्यूटोरियल देखें.
टूल को सेशन कॉन्फ़िगरेशन के हिस्से के तौर पर तय किया जाना चाहिए:
config = types.LiveConnectConfig(
response_modalities=["TEXT"],
tools=[set_light_values]
)
async with client.aio.live.connect(model=model, config=config) as session:
await session.send(input="Turn the lights down to a romantic level", end_of_turn=True)
async for response in session.receive():
print(response.tool_call)
एक प्रॉम्प्ट से, मॉडल कई फ़ंक्शन कॉल और उनके आउटपुट को चेन करने के लिए ज़रूरी कोड जनरेट कर सकता है. यह कोड सैंडबॉक्स एनवायरमेंट में चलता है और इसके बाद BidiGenerateContentToolCall मैसेज जनरेट करता है. फ़ंक्शन कॉल के नतीजे उपलब्ध होने तक, एक्ज़ीक्यूशन रोक दिया जाता है. इससे क्रम से प्रोसेस करने की सुविधा मिलती है.
क्लाइंट को BidiGenerateContentToolResponse के साथ जवाब देना चाहिए.
ऑडियो इनपुट और ऑडियो आउटपुट, फ़ंक्शन कॉलिंग का इस्तेमाल करने की मॉडल की क्षमता पर बुरा असर डालते हैं.
रुकावटों को मैनेज करना
उपयोगकर्ता किसी भी समय मॉडल के आउटपुट में रुकावट डाल सकते हैं. जब आवाज़ की गतिविधि का पता लगाने (वीएडी) की सुविधा किसी रुकावट का पता लगाती है, तो जनरेट की जा रही फ़ाइल को रद्द कर दिया जाता है और उसे हटा दिया जाता है. सेशन के इतिहास में सिर्फ़ वह जानकारी सेव रहती है जो क्लाइंट को पहले ही भेज दी गई है. इसके बाद, रुकावट की शिकायत करने के लिए, सर्वर BidiGenerateContentServerContent मैसेज भेजता है.
इसके अलावा, Gemini सर्वर उन सभी फ़ंक्शन कॉल को खारिज कर देता है जो प्रोसेस नहीं हो पाए हैं. साथ ही, रद्द किए गए कॉल के आईडी के साथ एक BidiGenerateContentServerContent
मैसेज भेजता है.
async for response in session.receive():
if response.server_content.interrupted is not None:
# The generation was interrupted
सीमाएं
अपना प्रोजेक्ट प्लान करते समय, Multimodal Live API और Gemini 2.0 की इन सीमाओं का ध्यान रखें.
क्लाइंट प्रमाणीकरण
Multimodal Live API सिर्फ़ सर्वर-टू-सर्वर पुष्टि की सुविधा देता है. साथ ही, इसका सुझाव सीधे क्लाइंट के इस्तेमाल के लिए नहीं दिया जाता. Multimodal Live API की मदद से सुरक्षित तरीके से पुष्टि करने के लिए, क्लाइंट इनपुट को किसी इंटरमीडियरी ऐप्लिकेशन सर्वर के ज़रिए भेजा जाना चाहिए.
बातचीत का इतिहास
मॉडल, सेशन के दौरान हुए इंटरैक्शन को ट्रैक करता है. हालांकि, बातचीत का इतिहास सेव नहीं किया जाता. सेशन खत्म होने पर, उससे जुड़ा कॉन्टेक्स्ट मिट जाता है.
किसी पिछले सेशन को वापस लाने या मॉडल को उपयोगकर्ता के इंटरैक्शन के पुराने कॉन्टेक्स्ट की जानकारी देने के लिए, ऐप्लिकेशन को अपनी बातचीत का लॉग बनाए रखना चाहिए. साथ ही, नए सेशन की शुरुआत में यह जानकारी भेजने के लिए, BidiGenerateContentClientContent मैसेज का इस्तेमाल करना चाहिए.
सेशन की ज़्यादा से ज़्यादा अवधि
ऑडियो के लिए सेशन की अवधि 15 मिनट तक और ऑडियो और वीडियो के लिए दो मिनट तक सीमित है. सेशन की अवधि तय सीमा से ज़्यादा होने पर, कनेक्शन बंद कर दिया जाता है.
मॉडल, कॉन्टेक्स्ट के साइज़ से भी सीमित होता है. वीडियो और ऑडियो स्ट्रीम के साथ-साथ, कॉन्टेंट के बड़े हिस्से भेजने पर, सेशन जल्दी खत्म हो सकता है.
आवाज़ की गतिविधि का पता लगाने की सुविधा (वीएडी)
यह मॉडल, लगातार चलने वाली ऑडियो इनपुट स्ट्रीम पर, आवाज़ की गतिविधि का पता लगाने (वीएडी) की सुविधा अपने-आप चालू करता है. VAD हमेशा चालू रहता है और इसके पैरामीटर कॉन्फ़िगर नहीं किए जा सकते.
टोकन की संख्या
टोकन की संख्या का इस्तेमाल नहीं किया जा सकता.
दर की सीमाएं
दर से जुड़ी ये सीमाएं लागू होती हैं:
- हर एपीआई पासकोड के लिए, एक साथ तीन सेशन
- हर मिनट 40 लाख टोकन
WebSockets API का रेफ़रंस
मल्टीमोडल लाइव एपीआई, एक स्टेटफ़ुल एपीआई है, जो WebSockets का इस्तेमाल करता है. इस सेक्शन में, आपको WebSockets API के बारे में ज़्यादा जानकारी मिलेगी.
सेशन
WebSocket कनेक्शन, क्लाइंट और Gemini सर्वर के बीच सेशन बनाता है. जब कोई क्लाइंट नया कनेक्शन शुरू करता है, तो सेशन सर्वर के साथ मैसेज एक्सचेंज कर सकता है, ताकि:
- Gemini सर्वर पर टेक्स्ट, ऑडियो या वीडियो भेजना.
- Gemini सर्वर से ऑडियो, टेक्स्ट या फ़ंक्शन कॉल के अनुरोध पाना.
कनेक्ट होने के बाद मिलने वाला शुरुआती मैसेज, सेशन कॉन्फ़िगरेशन सेट करता है. इसमें मॉडल, जनरेशन पैरामीटर, सिस्टम के निर्देश, और टूल शामिल होते हैं.
कॉन्फ़िगरेशन का यह उदाहरण देखें. ध्यान दें कि SDK टूल में नाम के केसिंग अलग-अलग हो सकते हैं. Python SDK टूल के कॉन्फ़िगरेशन के विकल्प यहां देखे जा सकते हैं.
{
"model": string,
"generationConfig": {
"candidateCount": integer,
"maxOutputTokens": integer,
"temperature": number,
"topP": number,
"topK": integer,
"presencePenalty": number,
"frequencyPenalty": number,
"responseModalities": [string],
"speechConfig": object
},
"systemInstruction": string,
"tools": [object]
}
मैसेज भेजें
WebSocket कनेक्शन पर मैसेज एक्सचेंज करने के लिए, क्लाइंट को किसी ओपन WebSocket कनेक्शन पर JSON ऑब्जेक्ट भेजना होगा. JSON ऑब्जेक्ट में, नीचे दिए गए ऑब्जेक्ट सेट में से एक फ़ील्ड होना चाहिए:
{
"setup": BidiGenerateContentSetup,
"clientContent": BidiGenerateContentClientContent,
"realtimeInput": BidiGenerateContentRealtimeInput,
"toolResponse": BidiGenerateContentToolResponse
}
इस्तेमाल किए जा सकने वाले क्लाइंट मैसेज
काम करने वाले क्लाइंट मैसेज की जानकारी नीचे दी गई टेबल में देखें:
मैसेज | ब्यौरा |
---|---|
BidiGenerateContentSetup |
पहले मैसेज में भेजा जाने वाला सेशन कॉन्फ़िगरेशन |
BidiGenerateContentClientContent |
क्लाइंट से डिलीवर की गई मौजूदा बातचीत का इंक्रीमेंटल कॉन्टेंट अपडेट |
BidiGenerateContentRealtimeInput |
रीयल टाइम ऑडियो या वीडियो इनपुट |
BidiGenerateContentToolResponse |
सर्वर से मिले ToolCallMessage का जवाब |
मैसेज पाना
Gemini से मैसेज पाने के लिए, WebSocket 'message' इवेंट को सुनें. इसके बाद, काम करने वाले सर्वर मैसेज की परिभाषा के हिसाब से नतीजे को पार्स करें.
यह देखें:
async with client.aio.live.connect(model='...', config=config) as session:
await session.send(input='Hello world!', end_of_turn=True)
async for message in session.receive():
print(message)
सर्वर मैसेज में, नीचे दिए गए ऑब्जेक्ट सेट में से सिर्फ़ एक फ़ील्ड होगा:
{
"setupComplete": BidiGenerateContentSetupComplete,
"serverContent": BidiGenerateContentServerContent,
"toolCall": BidiGenerateContentToolCall,
"toolCallCancellation": BidiGenerateContentToolCallCancellation
}
काम करने वाले सर्वर मैसेज
काम करने वाले सर्वर मैसेज देखने के लिए, नीचे दी गई टेबल देखें:
मैसेज | ब्यौरा |
---|---|
BidiGenerateContentSetupComplete |
सेटअप पूरा होने पर, क्लाइंट से मिला BidiGenerateContentSetup मैसेज |
BidiGenerateContentServerContent |
क्लाइंट मैसेज के जवाब में मॉडल से जनरेट किया गया कॉन्टेंट |
BidiGenerateContentToolCall |
क्लाइंट से फ़ंक्शन कॉल चलाने और मैच होने वाले आईडी के साथ रिस्पॉन्स दिखाने का अनुरोध करना |
BidiGenerateContentToolCallCancellation |
उपयोगकर्ता के मॉडल के आउटपुट में रुकावट डालने की वजह से, फ़ंक्शन कॉल रद्द होने पर भेजा जाता है |
मैसेज और इवेंट
BidiGenerateContentClientContent
क्लाइंट से डिलीवर की गई मौजूदा बातचीत का इंक्रीमेंटल अपडेट. यहां मौजूद सारा कॉन्टेंट, बातचीत के इतिहास में बिना किसी शर्त के जोड़ दिया जाता है. साथ ही, कॉन्टेंट जनरेट करने के लिए मॉडल के प्रॉम्प्ट के हिस्से के तौर पर इसका इस्तेमाल किया जाता है.
यहां कोई मैसेज भेजने पर, मॉडल बनाने की मौजूदा प्रोसेस में रुकावट आएगी.
फ़ील्ड | |
---|---|
turns[] |
ज़रूरी नहीं. मॉडल के साथ मौजूदा बातचीत में जोड़ा गया कॉन्टेंट. एक बार में पूछी गई क्वेरी के लिए, यह एक इंस्टेंस है. एक से ज़्यादा बार की गई क्वेरी के लिए, यह एक दोहराया जाने वाला फ़ील्ड है. इसमें बातचीत का इतिहास और नया अनुरोध शामिल होता है. |
turn_ |
ज़रूरी नहीं. अगर यह सही है, तो इसका मतलब है कि सर्वर पर कॉन्टेंट जनरेशन, इकट्ठा किए गए मौजूदा प्रॉम्प्ट से शुरू होना चाहिए. ऐसा न करने पर, सर्वर जनरेशन शुरू करने से पहले अन्य मैसेज का इंतज़ार करता है. |
BidiGenerateContentRealtimeInput
उपयोगकर्ता का ऐसा इनपुट जो रीयल टाइम में भेजा जाता है.
यह BidiGenerateContentClientContent
से कुछ तरीकों से अलग है:
- मॉडल जनरेशन के लिए, बिना किसी रुकावट के लगातार भेजा जा सकता है.
- अगर
BidiGenerateContentClientContent
औरBidiGenerateContentRealtimeInput
के बीच इंटरलीव किए गए डेटा को मिलाने की ज़रूरत पड़ती है, तो सर्वर सबसे अच्छे जवाब के लिए ऑप्टिमाइज़ करने की कोशिश करता है. हालांकि, इसकी कोई गारंटी नहीं है. - बातचीत खत्म होने का समय साफ़ तौर पर नहीं बताया जाता. यह समय, उपयोगकर्ता की गतिविधि (जैसे, बोली खत्म होने पर) से तय होता है.
- टर्न खत्म होने से पहले ही, डेटा को धीरे-धीरे प्रोसेस किया जाता है, ताकि मॉडल से तुरंत जवाब मिल सके.
- इसे हमेशा उपयोगकर्ता का इनपुट माना जाता है. इसका इस्तेमाल, बातचीत के इतिहास को भरने के लिए नहीं किया जा सकता. बिना किसी रुकावट के लगातार भेजा जा सकता है. यह मॉडल, उपयोगकर्ता की बातचीत की शुरुआत और आखिर में अपने-आप पता लगा लेता है. साथ ही, इसके हिसाब से जवाब की स्ट्रीमिंग शुरू या बंद कर देता है. डेटा आने के साथ-साथ उसे प्रोसेस किया जाता है, ताकि इंतज़ार का समय कम हो.
फ़ील्ड | |
---|---|
media_ |
ज़रूरी नहीं. मीडिया इनपुट के लिए इनलाइन किया गया बाइट डेटा. |
BidiGenerateContentServerContent
क्लाइंट मैसेज के जवाब में, मॉडल से जनरेट किया गया इंक्रीमेंटल सर्वर अपडेट.
कॉन्टेंट रीयल टाइम में नहीं, बल्कि जल्द से जल्द जनरेट होता है. क्लाइंट, रीयल टाइम में बफ़र करके वीडियो चला सकते हैं.
फ़ील्ड | |
---|---|
turn_ |
सिर्फ़ आउटपुट के लिए. अगर यह सही है, तो इसका मतलब है कि मॉडल जनरेट हो गया है. जनरेशन सिर्फ़ क्लाइंट के अन्य मैसेज के जवाब में शुरू होगा. इसे |
interrupted |
सिर्फ़ आउटपुट के लिए. अगर यह 'सही' है, तो इसका मतलब है कि किसी क्लाइंट मैसेज की वजह से, मौजूदा मॉडल जनरेशन में रुकावट आई है. अगर क्लाइंट, कॉन्टेंट को रीयल टाइम में चला रहा है, तो यह मौजूदा वीडियो चलाने की सूची को रोकने और खाली करने का एक अच्छा संकेत है. |
grounding_ |
सिर्फ़ आउटपुट के लिए. जनरेट किए गए कॉन्टेंट के लिए ग्राउंडिंग मेटाडेटा. |
model_ |
सिर्फ़ आउटपुट के लिए. उपयोगकर्ता के साथ मौजूदा बातचीत के दौरान, मॉडल ने जो कॉन्टेंट जनरेट किया है. |
BidiGenerateContentSetup
यह मैसेज, क्लाइंट के पहले और सिर्फ़ पहले मैसेज में भेजा जाएगा. इसमें ऐसा कॉन्फ़िगरेशन होता है जो स्ट्रीमिंग सेशन के दौरान लागू होता है.
क्लाइंट को कोई और मैसेज भेजने से पहले, BidiGenerateContentSetupComplete
मैसेज का इंतज़ार करना चाहिए.
फ़ील्ड | |
---|---|
model |
ज़रूरी है. मॉडल के संसाधन का नाम. यह मॉडल के लिए आईडी के तौर पर काम करता है. फ़ॉर्मैट: |
generation_ |
ज़रूरी नहीं. जनरेशन कॉन्फ़िगरेशन. ये फ़ील्ड काम नहीं करते:
|
system_ |
ज़रूरी नहीं. मॉडल के लिए, उपयोगकर्ता ने सिस्टम के लिए जो निर्देश दिए हैं. ध्यान दें: सिर्फ़ टेक्स्ट का इस्तेमाल किया जाना चाहिए. हर हिस्से का कॉन्टेंट एक अलग पैराग्राफ़ में होगा. |
tools[] |
ज़रूरी नहीं.
|
BidiGenerateContentSetupComplete
इस टाइप में कोई फ़ील्ड नहीं है.
क्लाइंट से मिले BidiGenerateContentSetup
मैसेज के जवाब में भेजा गया.
BidiGenerateContentToolCall
क्लाइंट से फ़ंक्शन कॉल को लागू करने और मैच करने वाले id
के साथ रिस्पॉन्स दिखाने का अनुरोध करें.
फ़ील्ड | |
---|---|
function_ |
सिर्फ़ आउटपुट के लिए. वह फ़ंक्शन कॉल जिसे चलाना है. |
BidiGenerateContentToolCallCancellation
क्लाइंट के लिए सूचना कि तय किए गए id
के साथ पहले जारी किए गए ToolCallMessage
को लागू नहीं किया जाना चाहिए और उसे रद्द कर दिया जाना चाहिए. अगर उन टूल कॉल से कोई साइड इफ़ेक्ट हुआ है, तो क्लाइंट उन टूल कॉल को पहले जैसा करने की कोशिश कर सकते हैं. यह मैसेज सिर्फ़ तब दिखता है, जब क्लाइंट सर्वर के टर्न में रुकावट डालते हैं.
फ़ील्ड | |
---|---|
ids[] |
सिर्फ़ आउटपुट के लिए. रद्द किए जाने वाले टूल कॉल के आईडी. |
BidiGenerateContentToolResponse
सर्वर से मिले ToolCall
के लिए, क्लाइंट से जनरेट किया गया रिस्पॉन्स. id
फ़ील्ड की मदद से, अलग-अलग FunctionResponse
ऑब्जेक्ट को उनके संबंधित FunctionCall
ऑब्जेक्ट से मैच किया जाता है.
ध्यान दें कि यूनीऐरी और सर्वर-स्ट्रीमिंग GenerateContent APIs फ़ंक्शन को कॉल करने के लिए, Content
पार्ट को एक्सचेंज किया जाता है. वहीं, बीडीआई GenerateContent APIs फ़ंक्शन को कॉल करने के लिए, मैसेज के इन खास सेट का इस्तेमाल किया जाता है.
फ़ील्ड | |
---|---|
function_ |
ज़रूरी नहीं. फ़ंक्शन कॉल का रिस्पॉन्स. |
आम तौर पर इस्तेमाल होने वाले टाइप के बारे में ज़्यादा जानकारी
आम तौर पर इस्तेमाल होने वाले एपीआई रिसॉर्स टाइप Blob
,
Content
, FunctionCall
, FunctionResponse
, GenerationConfig
,
GroundingMetadata
, और Tool
के बारे में ज़्यादा जानने के लिए, कॉन्टेंट जनरेट करना लेख पढ़ें.
तीसरे पक्ष के इंटिग्रेशन
वेब और मोबाइल ऐप्लिकेशन को डिप्लॉय करने के लिए, इन विकल्पों को एक्सप्लोर किया जा सकता है: