Chat API-তে StreamMessage রিসোর্স ব্যবহার করে Google Chat-এ কীভাবে ইনক্রিমেন্টাল মেসেজ স্ট্রিম করতে হয় তা এই গাইডে ব্যাখ্যা করা হয়েছে। স্ট্রিমিংয়ের মাধ্যমে আপনার
Google Chat অ্যাপ লাইভ প্রগ্রেস ইন্ডিকেটর, ইন্টারমিডিয়েট
রিজনিং বা টুল-এক্সিকিউশন স্টেপ এবং মেসেজ চূড়ান্ত করার আগে
ইনক্রিমেন্টাল টেক্সট রেসপন্স দেখাতে পারে।
স্ট্রিমিং এমন চ্যাট অ্যাপের জন্য ডিজাইন করা হয়েছে যা জেনারেটিভ AI বা দীর্ঘ সময় ধরে চলা ব্যাকএন্ড ওয়ার্কফ্লো দ্বারা পরিচালিত হয় যেখানে সম্পূর্ণ উত্তর তৈরি করতে কয়েক সেকেন্ড বা মিনিট সময় লাগে।
মেসেজ স্ট্রিমিং কীভাবে কাজ করে
একটি স্ট্রিমিং মেসেজ, স্পেসে স্ট্যান্ডার্ড
Message
রিসোর্স হওয়ার আগে, অ্যাক্টিভ স্ট্রিমিং স্টেট হিসেবে প্রোগ্রেস করে:
- স্ট্রিম শুরু করুন (
spaces.streamMessages.create): আপনার Chat অ্যাপ থ্রেড করা স্পেসে একটিStreamMessageতৈরি করে, যে ব্যবহারকারীর ইন্টার্যাকশন মেসেজের উত্তর দেওয়া হচ্ছে সেটির রেফারেন্স দেয়। API থ্রেডে একটি লাইভ প্রগ্রেস ইন্ডিকেটর দেখায় এবং একটিStreamMessageরিসোর্স নাম এবং একটি প্রাথমিকnextChunkTokenরিটার্ন করে। - স্ট্রিম আপডেট করুন (
appendStreamMessageContentবাpatch): আপনার Chat অ্যাপ আউটপুট জেনারেট করার সাথে সাথে, এটি লেটেস্টnextChunkTokenব্যবহার করে ধারাবাহিক আপডেট পাঠায়:- নতুন টেক্সট চাঙ্ক কনক্যাটিনেট করতে, মধ্যবর্তী ধাপ যোগ করতে, ইনলাইন উদ্ধৃতি যোগ করতে অথবা
progressTextআপডেট করতেspaces.streamMessages.appendStreamMessageContentকল করুন। - স্ট্রিম করা কন্টেন্ট চাঙ্ক পরিবর্তন করতে
spaces.streamMessages.patchকল করুন অথবাprogressTextআপডেট করুন।
- নতুন টেক্সট চাঙ্ক কনক্যাটিনেট করতে, মধ্যবর্তী ধাপ যোগ করতে, ইনলাইন উদ্ধৃতি যোগ করতে অথবা
- স্ট্রিম চূড়ান্ত বা বাতিল করা (
commitবাdelete):- স্ট্রিম চূড়ান্ত করতে
spaces.streamMessages.commitকল করুন এবং এটি স্থায়ীMessageরিসোর্সে পরিবর্তন করুন। এছাড়াও, আপনি কমিট করার সময় কার্ড, অ্যাক্সেসরি উইজেট ও ফুটার সোর্সের মতো শুধু-কমিট এলিমেন্ট অ্যাটাচ করতে পারেন। - স্পেসে মেসেজ সেভ না করে অ্যাক্টিভ স্ট্রিম বাতিল করতে
spaces.streamMessages.deleteকল করুন।
- স্ট্রিম চূড়ান্ত করতে
স্ট্রিম অ্যাক্টিভ থাকাকালীন, শুধুমাত্র রেফারেন্স করা মেসেজের প্রেরক
(referencedMessage) যেটিতে স্ট্রিম করা হচ্ছে, তিনি জেনারেশন বাতিল করতে
বন্ধ করুন বিকল্পে ক্লিক করতে পারবেন। Chat আপনার Chat অ্যাপে একটি বাতিলকরণ সিস্টেম কমান্ড ইভেন্ট পাঠায়
যাতে আপনি ব্যাকএন্ড কাজ বন্ধ করতে পারেন এবং
আংশিক আউটপুট কমিট করতে পারেন অথবা স্ট্রিম মুছে ফেলতে পারেন।
পূর্বশর্ত
Chat API-এর মাধ্যমে মেসেজ স্ট্রিম করতে, নিম্নলিখিত পূর্বপ্রয়োজনীয়তা সম্পূর্ণ করুন:
- Google Chat-এ অ্যাক্সেস সহ Business বা Enterprise Google Workspace অ্যাকাউন্ট।
- আপনার পরিবেশ সেট-আপ করুন:
- Google Cloud প্রোজেক্ট তৈরি করুন।
- আপনার Chat অ্যাপের নাম, আইকন ও বিবরণ সহ Google Chat API চালু ও কনফিগার করুন।
- পরিষেবা অ্যাকাউন্টের ক্রেডেনশিয়াল তৈরি করুন এবং সেগুলিকে
credentials.jsonহিসেবে সেভ করুন। মেসেজ স্ট্রিমিংয়ের জন্যhttps://www.googleapis.com/auth/chat.botঅনুমোদনের স্কোপ সহ অ্যাপ যাচাইকরণ প্রয়োজন; ব্যবহারকারীর যাচাইকরণ কাজ করে না।
- আপনার Chat অ্যাপকে থ্রেডেড
Chat স্পেসে (অথবা ১:১ সরাসরি মেসেজ যাতে আগে থেকেই অন্তত একটি মেসেজ আছে) যোগ করুন এবং উত্তর দেওয়ার জন্য (
spaces/SPACE_ID/messages/MESSAGE_ID) অ্যাক্সেসযোগ্য মেসেজের রিসোর্স নাম পান। Python স্যাম্পেলের জন্য, Python-এর জন্য Google API ক্লায়েন্ট লাইব্রেরি ইনস্টল করুন এবং
google-auth, এবং Chat API পরিষেবা ক্লায়েন্ট শুরু করুন:pip install google-api-python-client google-authfrom google.oauth2 import service_account from googleapiclient.discovery import build SCOPES = ["https://www.googleapis.com/auth/chat.bot"] creds = service_account.Credentials.from_service_account_file( "credentials.json", scopes=SCOPES ) chat = build("chat", "v1", credentials=creds)
স্ট্রিম শুরু করুন
উত্তর স্ট্রিম করা শুরু করতে, spaces.streamMessages.create কল করুন এবং অনুরোধের বডিতে একটি
StreamMessage পাস করুন:
referencedMessage(প্রয়োজনীয়): যে মেসেজ উত্তর ট্রিগার করেছে সেটির রিসোর্সের নাম,spaces/{space}/messages/{message}হিসেবে ফর্ম্যাট করা। রেফারেন্স করা মেসেজটি অবশ্যই একই স্পেসের হতে হবে এবং আপনার Chat অ্যাপের অ্যাক্সেস থাকতে হবে। Chat,referencedMessage-এর মতো একই থ্রেডে স্ট্রিম করা উত্তর পোস্ট করে।progressText(প্রয়োজনীয়): প্রোগ্রেস ইন্ডিকেটরের পাশে দেখানো খালি নয় এমন প্লেন-টেক্সট স্ট্যাটাস লেবেল (সর্বাধিক ২৫০টি অক্ষর), যেমন"Thinking..."।markupSyntax(ঐচ্ছিক): মেসেজের জন্য টেক্সট ফর্ম্যাটিং সিনট্যাক্স, যেমনMARKUP_SYNTAX_MARKDOWNবাMARKUP_SYNTAX_CHAT(MARKUP_SYNTAX_UNSPECIFIEDহলে Chat অ্যাপের কনফিগার করা সিনট্যাক্সে ডিফল্ট হিসেবে সেট করা হয়)। ইনলাইন উদ্ধৃতি যোগ করার পরিকল্পনা থাকলেMARKUP_SYNTAX_MARKDOWNসেট করুন।streamContentChunks(ঐচ্ছিক): অবিলম্বে দেখানোর জন্য প্রাথমিকtext,stepবাcitationচাঙ্ক।
পরবর্তী কলের জন্য উত্তর থেকে name (spaces/{space}/streamMessages/{stream_message}) এবং
nextChunkToken, দুটিই সেভ করুন।
HTTP
POST https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"referencedMessage": "spaces/SPACE_ID/messages/MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN"
}
Python
stream = (
chat.spaces()
.streamMessages()
.create(
parent="spaces/SPACE_ID",
body={
"referencedMessage": "spaces/SPACE_ID/messages/MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
},
)
.execute()
)
stream_name = stream["name"]
chunk_token = stream["nextChunkToken"]
এই পদ্ধতি StreamMessage রিসোর্স রিটার্ন করে:
{
"name": "spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
"nextChunkToken": "INITIAL_CHUNK_TOKEN"
}
কন্টেন্ট চাঙ্ক যোগ করুন
আপনার Chat অ্যাপ ইন্টারমিডিয়েট ধাপ বা টেক্সট টোকেন তৈরি করলে, spaces.streamMessages.appendStreamMessageContent কল করুন:
chunkToken-এ লেটেস্টnextChunkTokenপাস করুন। প্রতিটি সফল কল একটি নতুনnextChunkTokenরিটার্ন করে যা আপনার পরবর্তী আপডেট বা কমিট অনুরোধে পাস করতে হবে।textচাঙ্ক সরাসরি আগে স্ট্রিম করা টেক্সটের সাথে কনক্যাটিনেট করে। প্রয়োজন হলে চাঙ্কের মধ্যে স্পেস বা নতুন লাইন যোগ করুন।stepচাঙ্ক মেসেজে দেখানো মধ্যবর্তী ধাপের তালিকায় যোগ করা হয়েছে।progressTextঐচ্ছিক। আপনিprogressTextবাদ দিলে বা এটি""-এ সেট করলে, Chat আগে থেকে সেট করাprogressTextদেখাতে থাকে।
HTTP
POST https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID:appendStreamMessageContent HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"chunkToken": "INITIAL_CHUNK_TOKEN",
"progressText": "Searching documentation...",
"streamContentChunks": [
{
"step": {
"title": "Search knowledge base",
"description": "Found 3 matching articles."
}
},
{
"text": "See <chat-citation data-id=\"c1\">guide</chat-citation>:\n"
},
{
"citation": {
"id": "c1",
"citedSources": [
{
"title": "System Architecture Guide",
"uri": "https://example.com/docs/arch"
}
]
}
}
]
}
Python
stream = (
chat.spaces()
.streamMessages()
.appendStreamMessageContent(
name=stream_name,
body={
"chunkToken": chunk_token,
"progressText": "Searching documentation...",
"streamContentChunks": [
{
"step": {
"title": "Search knowledge base",
"description": "Found 3 matching articles.",
}
},
{
"text": (
'See <chat-citation data-id="c1">'
"guide</chat-citation>:\n"
)
},
{
"citation": {
"id": "c1",
"citedSources": [
{
"title": "System Architecture Guide",
"uri": "https://example.com/docs/arch",
}
],
}
},
],
},
)
.execute()
)
chunk_token = stream["nextChunkToken"]
স্ট্রিম করা কন্টেন্ট বা প্রোগ্রেস টেক্সট পরিবর্তন করুন
আগে স্ট্রিম করা কন্টেন্ট আবার লিখতে হলে—যেমন, পোস্ট-প্রসেসিং বা নিরাপত্তা ফিল্টার চালানোর পরে—অথবা চাঙ্ক যোগ না করে শুধু progressText আপডেট করতে হলে, spaces.streamMessages.patch কল করুন:
- আপডেট করার জন্য কমা দিয়ে আলাদা করা ফিল্ডের তালিকায়
updateMaskসেট করুন:progressText,streamContentChunks, অথবাprogressText,streamContentChunks. StreamMessageঅনুরোধের বডিতে লেটেস্টnextChunkTokenঅন্তর্ভুক্ত করুন এবং উত্তরে ফেরত আসা নতুনnextChunkTokenরেকর্ড করুন।streamContentChunksযখনupdateMask-এ থাকে, তখন প্রদত্ত চাঙ্ক আগে স্ট্রিম করা কন্টেন্টের সাথে যোগ করার পরিবর্তে সেটিকে রিপ্লেস করে।progressText,updateMask-এ থাকলে,progressTextঅবশ্যই খালি নয় এমন প্লেন টেক্সট হতে হবে, যা ২৫০টি অক্ষর পর্যন্ত হতে পারে।
HTTP
PATCH https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID?updateMask=progressText,streamContentChunks HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"nextChunkToken": "LATEST_CHUNK_TOKEN",
"progressText": "Formatting response...",
"streamContentChunks": [
{
"text": "Updated response text."
}
]
}
Python
stream = (
chat.spaces()
.streamMessages()
.patch(
name=stream_name,
updateMask="progressText,streamContentChunks",
body={
"nextChunkToken": chunk_token,
"progressText": "Formatting response...",
"streamContentChunks": [
{"text": "Updated response text."}
],
},
)
.execute()
)
chunk_token = stream["nextChunkToken"]
স্ট্রিম চূড়ান্ত করা
জেনারেট করা হয়ে গেলে, লেটেস্ট chunkToken সহ spaces.streamMessages.commit কল করুন
যাতে স্ট্রিমটি স্থায়ী Message রিসোর্সে
চূড়ান্ত করা যায়:
- আপনি চাইলে কমিট অনুরোধে চূড়ান্ত
streamContentChunksঅন্তর্ভুক্ত করতে পারেন, যার মধ্যে শুধু কমিট করা যায় এমন চাঙ্ক টাইপ (card,accessoryWidgetএবংcitedSource) অন্তর্ভুক্ত। আপনি যদি আগের কলে খালি নয় এমন কন্টেন্ট স্ট্রিম করে থাকেন, তাহলে কমিট করার সময়
streamContentChunksবাদ দিতে পারবেন। চূড়ান্ত কমিট করা মেসেজ খালি রাখা যাবে না।
HTTP
POST https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID:commit HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"chunkToken": "LATEST_CHUNK_TOKEN",
"streamContentChunks": [
{
"text": "All checks passed."
},
{
"citedSource": {
"title": "Deployment Runbook",
"uri": "https://example.com/docs/runbook"
}
},
{
"card": {
"cardId": "details-card",
"card": {
"header": {
"title": "Build Status"
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": "All 42 checks succeeded."
}
}
]
}
]
}
}
}
]
}
Python
status_card = {
"cardId": "details-card",
"card": {
"header": {"title": "Build Status"},
"sections": [
{
"widgets": [
{"textParagraph": {"text": "All 42 checks succeeded."}}
]
}
],
},
}
commit_response = (
chat.spaces()
.streamMessages()
.commit(
name=stream_name,
body={
"chunkToken": chunk_token,
"streamContentChunks": [
{"text": "All checks passed."},
{
"citedSource": {
"title": "Deployment Runbook",
"uri": "https://example.com/docs/runbook",
}
},
{"card": status_card},
],
},
)
.execute()
)
final_message = commit_response["message"]
print(f"Committed message: {final_message['name']}")
অ্যাক্টিভ স্ট্রিম বাতিল করা
যদি এমন কোনও সমস্যা হয় যা সমাধান করা যাবে না অথবা ব্যবহারকারী জেনারেশন বাতিল করে দেন এবং আপনি
থ্রেডে আংশিক উত্তর রেখে যেতে না চান, তাহলে
spaces.streamMessages.delete কল করুন:
HTTP
DELETE https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Python
chat.spaces().streamMessages().delete(name=stream_name).execute()
কোনও স্ট্রিম Message-এ কমিট করা হয়ে গেলে,
চূড়ান্ত করা মেসেজ মুছে দিতে চাইলে,
পরিবর্তে spaces.messages.delete কল করুন।
যেসব কন্টেন্ট চাঙ্ক টাইপ কাজ করে
streamContentChunks-এর প্রতিটি এন্ট্রি StreamContentChunk ইউনিয়নের একটি ফিল্ড নির্দিষ্ট করে। কিছু চাঙ্ক টাইপ স্ট্রিম চলাকালীন পাঠানো যেতে পারে,
অন্যগুলি শুধুমাত্র spaces.streamMessages.commit-এ গ্রহণ করা হয়:
| চাঙ্ক ফিল্ড | যেসব পদ্ধতি কাজ করে | চূড়ান্ত Message ফিল্ড |
নোট |
|---|---|---|---|
text |
create, appendStreamMessageContent,
patch, commit |
text |
ইনক্রিমেন্টাল টেক্সট। appendStreamMessageContent-এ
কনক্যাটিনেট করা হয়েছে; patch-এ পরিবর্তন করা হয়েছে।
চূড়ান্ত কমিট করা টেক্সট ৩২,০০০ বাইটের বেশি হতে পারবে না। |
step |
create, appendStreamMessageContent,
patch, commit |
elements.steps.steps[] |
প্লেন-টেক্সট title (প্রয়োজনীয়) এবং ঐচ্ছিক description সহ
ইন্টারমিডিয়েট প্রসেসিং ধাপ। |
citation |
create, appendStreamMessageContent,
patch, commit |
elements.citations[] |
ইনলাইন
Citation যার সাথে বর্ণসাংখ্যিক id (৬৩ অক্ষরের
কম, আন্ডারস্কোর ব্যবহার করা যাবে) এবং citedSources। text-এ
markupSyntax: "MARKUP_SYNTAX_MARKDOWN" এবং ম্যাচিং
<chat-citation data-id="ID">...</chat-citation>
ট্যাগ থাকতে হবে। আগে থেকেই আছে এমন id-এর সাথে citation পাঠালে
আগের উদ্ধৃতি ওভাররাইট হয়ে যায়। |
card |
শুধুমাত্র commit |
cardsV2[] |
ইন্টার্যাক্টিভ বা তথ্যমূলক
CardWithId কার্ড। |
accessoryWidget |
শুধুমাত্র commit |
accessoryWidgets[] |
AccessoryWidget মেসেজের নিচে দেখানো বোতাম,
যেমন, মতামত জানানোর বোতাম। |
citedSource |
শুধুমাত্র commit |
elements.citedSources[] |
CitedSource মেসেজের নিচে ফুটার লিঙ্ক দেখানো হয়েছে
ইনলাইন উদ্ধৃতি ট্যাগ ছাড়াই। |
ব্যবহারকারীর অনুরোধে স্ট্রিম বাতিল করা ম্যানেজ করা
কোনও স্ট্রিম অ্যাক্টিভ থাকাকালীন, শুধুমাত্র রেফারেন্স করা মেসেজের প্রেরক
(referencedMessage) স্ট্রিম করা মেসেজে বন্ধ করুন বিকল্পে ক্লিক করতে পারবেন। ব্যবহারকারী কোনও স্ট্রিম বন্ধ করলে, Chat আপনার Chat অ্যাপ এন্ডপয়েন্টে cancelStream.streamMessage (বন্ধ করা স্ট্রিমের spaces/{space}/streamMessages/{stream_message} রিসোর্স নাম) সহ একটি সিস্টেম কমান্ড ইন্টার্যাকশন ইভেন্ট পাঠায়।
ইনকামিং JSON পেলোডের স্ট্রাকচার নির্ভর করে আপনি Google Workspace অ্যাড-অন হিসেবে Chat অ্যাপ তৈরি করেছেন নাকি Chat API ইন্টার্যাকশন ইভেন্ট ব্যবহার করে তৈরি করেছেন তার উপর:
Google Workspace অ্যাড-অন
{
"commonEventObject": {
"hostApp": "CHAT"
},
"chat": {
"user": {
"name": "users/USER_ID"
},
"space": {
"name": "spaces/SPACE_ID"
},
"systemCommandPayload": {
"systemCommandMetadata": {
"cancelStream": {
"streamMessage": "spaces/SPACE_ID/streamMessages/STREAM_ID"
}
}
}
}
}
Google Chat API
{
"type": "SYSTEM_COMMAND",
"space": {
"name": "spaces/SPACE_ID"
},
"user": {
"name": "users/USER_ID"
},
"systemCommandMetadata": {
"cancelStream": {
"streamMessage": "spaces/SPACE_ID/streamMessages/STREAM_ID"
}
}
}
আপনার Chat অ্যাপ cancelStream ইভেন্ট পেলে:
streamMessage-এর জন্য আরও টোকেন জেনারেট করা বা ডাউনস্ট্রিম টুল চালানো বন্ধ করতে আপনার ব্যাকগ্রাউন্ড ওয়ার্কারকে সিগন্যাল দিন।- নিম্নলিখিত পদ্ধতিগুলির মধ্যে কোনও একটি ব্যবহার করে অ্যাক্টিভ স্ট্রিম সংক্রান্ত সমস্যার সমাধান করুন:
- আংশিক আউটপুট রাখুন: লেটেস্ট
chunkTokenসহspaces.streamMessages.commitকল করুন (বিকল্প হিসেবে"\n\n_Generation stopped._"-এর মতো নোট যোগ করুন)। - উত্তর বাতিল করা:
spaces.streamMessages.delete-কে কল করুন যাতে থ্রেডে কিছুই সেভ না হয়।
- আংশিক আউটপুট রাখুন: লেটেস্ট
- আপনার ইন্টার্যাকশন ইভেন্ট হ্যান্ডলার থেকে একটি খালি HTTP
200 OKJSON রেসপন্স ({}) ফেরত পাঠান।
সীমাবদ্ধতা
মেসেজ স্ট্রিমিংয়ের ক্ষেত্রে নিম্নলিখিত সীমাবদ্ধতা রয়েছে:
- প্ল্যাটফর্মের উপলভ্যতা: মেসেজ স্ট্রিমিং শুধুমাত্র ওয়েবে Chat-এ দেখা যায়। Android ও iOS-এর জন্য সহায়তা শীঘ্রই উপলভ্য হবে।
- স্ট্রিম টাইমআউট: একটি অ্যাক্টিভ
StreamMessageতৈরি হওয়ার ১০ মিনিট পরে টাইমআউট হয়ে যায়। আপনার Chat অ্যাপকে অবশ্যই স্ট্রিম শুরু হওয়ার ১০ মিনিটের মধ্যেspaces.streamMessages.commitবাspaces.streamMessages.delete-কে কল করতে হবে।