এলএলএম কীভাবে প্রতিক্রিয়া স্ট্রিম করে

প্রকাশিত: জানুয়ারী 21, 2025

একটি স্ট্রিমড এলএলএম প্রতিক্রিয়া ক্রমবর্ধমান এবং ক্রমাগত নির্গত ডেটা নিয়ে গঠিত। স্ট্রিমিং ডেটা সার্ভার এবং ক্লায়েন্ট থেকে আলাদা দেখায়।

সার্ভার থেকে

স্ট্রিম করা প্রতিক্রিয়া কেমন তা বোঝার জন্য, আমি জেমিনিকে কমান্ড লাইন টুল curl ব্যবহার করে আমাকে একটি দীর্ঘ কৌতুক বলার জন্য অনুরোধ করেছিলাম। Gemini API-তে নিম্নলিখিত কলটি বিবেচনা করুন। আপনি এটি চেষ্টা করলে, আপনার Gemini API কী দিয়ে URL-এ {GOOGLE_API_KEY} প্রতিস্থাপন করতে ভুলবেন না।

$ 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 এন্ট্রি হল মিথুনের প্রতিক্রিয়ার শুরু৷ আপনি যখন আরও 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?\""

...

কিন্তু কি হবে যদি টি-রেক্স জোকসের পরিবর্তে, আপনি মডেলটিকে কিছুটা জটিল কিছুর জন্য জিজ্ঞাসা করেন। উদাহরণস্বরূপ, একটি সংখ্যা জোড় বা বিজোড় কিনা তা নির্ধারণ করতে জেমিনিকে একটি জাভাস্ক্রিপ্ট ফাংশন নিয়ে আসতে বলুন। text: খণ্ডগুলি কিছুটা আলাদা দেখায়।

আউটপুটে এখন জাভাস্ক্রিপ্ট কোড ব্লক দিয়ে শুরু করে মার্কডাউন ফরম্যাট রয়েছে। নিম্নলিখিত নমুনায় আগের মতো একই প্রাক-প্রসেসিং ধাপ রয়েছে।

"```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:** । এর মানে আপনি যদি মার্কডাউন ফর্ম্যাট আউটপুট করতে চান, আপনি মার্কডাউন পার্সার দিয়ে প্রতিটি খণ্ডকে পৃথকভাবে প্রক্রিয়া করতে পারবেন না।

ক্লায়েন্ট থেকে

আপনি যদি MediaPipe LLM এর মতো ফ্রেমওয়ার্ক সহ ক্লায়েন্টে জেমমার মতো মডেলগুলি চালান, স্ট্রিমিং ডেটা একটি কলব্যাক ফাংশনের মাধ্যমে আসে।

যেমন:

llmInference.generateResponse(
  inputPrompt,
  (chunk, done) => {
     console.log(chunk);
});

প্রম্পট API-এর সাহায্যে, আপনি একটি ReadableStream এ পুনরাবৃত্তি করে খণ্ড হিসাবে স্ট্রিমিং ডেটা পান।

const languageModel = await self.ai.languageModel.create();
const stream = languageModel.promptStreaming(inputPrompt);
for await (const chunk of stream) {
  console.log(chunk);
}

পরবর্তী পদক্ষেপ

আপনি কি ভাবছেন কিভাবে পারফরম্যান্টলি এবং নিরাপদে স্ট্রিম করা ডেটা রেন্ডার করবেন? LLM প্রতিক্রিয়া রেন্ডার করার জন্য আমাদের সেরা অনুশীলনগুলি পড়ুন।