पब्लिश करने की तारीख: 21 जनवरी, 2025
स्ट्रीम किए गए एलएलएम के जवाब में, लगातार और धीरे-धीरे डेटा शामिल होता है. स्ट्रीमिंग डेटा, सर्वर और क्लाइंट से अलग दिखता है.
सर्वर से
स्ट्रीम किए गए जवाब का क्या स्वरूप होता है, यह समझने के लिए मैंने कमांड-लाइन टूल curl
का इस्तेमाल करके, Gemini से एक लंबा चुटकुला सुनाने के लिए कहा. Gemini API के लिए, यहां दिया गया कॉल देखें. अगर आपको इसे आज़माना है, तो यूआरएल में {GOOGLE_API_KEY}
को अपनी Gemini API पासकोड से बदलना न भूलें.
$ curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key={GOOGLE_API_KEY}" \
-H 'Content-Type: application/json' \
--no-buffer \
-d '{ "contents":[{"parts":[{"text": "Tell me a long T-rex joke, please."}]}]}'
यह अनुरोध, इवेंट स्ट्रीम फ़ॉर्मैट में, नीचे दिए गए (छोटे किए गए) आउटपुट को लॉग करता है.
हर लाइन data:
से शुरू होती है. इसके बाद, मैसेज का पेलोड होता है. टेक्स्ट का फ़ॉर्मैट ज़्यादा मायने नहीं रखता. अहम बात यह है कि टेक्स्ट के हिस्से कैसे हैं.
//
data: {"candidates":[{"content": {"parts": [{"text": "A T-Rex"}],"role": "model"},
"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],
"usageMetadata": {"promptTokenCount": 11,"candidatesTokenCount": 4,"totalTokenCount": 15}}
data: {"candidates": [{"content": {"parts": [{ "text": " walks into a bar and orders a drink. As he sits there, he notices a" }], "role": "model"},
"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],
"usageMetadata": {"promptTokenCount": 11,"candidatesTokenCount": 21,"totalTokenCount": 32}}
पहला पेलोड JSON है. हाइलाइट किए गए candidates[0].content.parts[0].text
पर नज़र डालें:
{
"candidates": [
{
"content": {
"parts": [
{
"text": "A T-Rex"
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0,
"safetyRatings": [
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
}
]
}
],
"usageMetadata": {
"promptTokenCount": 11,
"candidatesTokenCount": 4,
"totalTokenCount": 15
}
}
पहली text
एंट्री, Gemini के जवाब की शुरुआत है. text
की ज़्यादा एंट्री निकालने पर, जवाब को नई लाइन से अलग किया जाता है.
नीचे दिया गया स्निपेट, कई text
एंट्री दिखाता है. इससे मॉडल का आखिरी रिस्पॉन्स पता चलता है.
"A T-Rex"
" was walking through the prehistoric jungle when he came across a group of Triceratops. "
"\n\n\"Hey, Triceratops!\" the T-Rex roared. \"What are"
" you guys doing?\"\n\nThe Triceratops, a bit nervous, mumbled,
\"Just... just hanging out, you know? Relaxing.\"\n\n\"Well, you"
" guys look pretty relaxed,\" the T-Rex said, eyeing them with a sly grin.
\"Maybe you could give me a hand with something.\"\n\n\"A hand?\""
...
लेकिन अगर टी-रेक्स के चुटकुलों के बजाय, मॉडल से कुछ ज़्यादा मुश्किल सवाल पूछा जाए, तो क्या होगा. उदाहरण के लिए, Gemini से JavaScript फ़ंक्शन का इस्तेमाल करके यह पता लगाने के लिए कहें कि कोई संख्या, जोड़ी है या विषम. text:
चंक थोड़े अलग दिखते हैं.
आउटपुट में अब Markdown फ़ॉर्मैट है, जो JavaScript कोड ब्लॉक से शुरू होता है. नीचे दिए गए सैंपल में, पहले की तरह ही डेटा को प्रोसेस करने के चरण शामिल हैं.
"```javascript\nfunction"
" isEven(number) {\n // Check if the number is an integer.\n"
" if (Number.isInteger(number)) {\n // Use the modulo operator"
" (%) to check if the remainder after dividing by 2 is 0.\n return number % 2 === 0; \n } else {\n "
"// Return false if the number is not an integer.\n return false;\n }\n}\n\n// Example usage:\nconsole.log(isEven("
"4)); // Output: true\nconsole.log(isEven(7)); // Output: false\nconsole.log(isEven(3.5)); // Output: false\n```\n\n**Explanation:**\n\n1. **`isEven("
"number)` function:**\n - Takes a single argument `number` representing the number to be checked.\n - Checks if the `number` is an integer using `Number.isInteger()`.\n - If it's an"
...
चुनौती को और मुश्किल बनाने के लिए, मार्क किए गए कुछ आइटम एक चंक में शुरू होते हैं और दूसरे में खत्म होते हैं. कुछ मार्कअप नेस्ट किए गए हैं. नीचे दिए गए उदाहरण में, हाइलाइट किए गए फ़ंक्शन को दो लाइनों में बांटा गया है: **isEven(
और number) function:**
. दोनों को जोड़ने पर, आउटपुट **isEven("number) function:**
होता है. इसका मतलब है कि अगर आपको फ़ॉर्मैट किया गया Markdown आउटपुट चाहिए, तो Markdown पार्सर की मदद से हर चंक को अलग-अलग प्रोसेस नहीं किया जा सकता.
क्लाइंट से
अगर MediaPipe LLM जैसे फ़्रेमवर्क के साथ क्लाइंट पर Gemma जैसे मॉडल चलाए जाते हैं, तो स्ट्रीमिंग डेटा, कॉलबैक फ़ंक्शन के ज़रिए आता है.
उदाहरण के लिए:
llmInference.generateResponse(
inputPrompt,
(chunk, done) => {
console.log(chunk);
});
Prompt API की मदद से, ReadableStream
पर बार-बार क्लिक करके, स्ट्रीमिंग डेटा को चंक के तौर पर पाया जा सकता है.
const languageModel = await self.ai.languageModel.create();
const stream = languageModel.promptStreaming(inputPrompt);
for await (const chunk of stream) {
console.log(chunk);
}
अगले चरण
क्या आपको यह जानना है कि स्ट्रीम किए गए डेटा को बेहतर और सुरक्षित तरीके से रेंडर कैसे किया जा सकता है? एलएलएम के जवाब रेंडर करने के सबसे सही तरीके पढ़ें.