Google Chat API का इस्तेमाल करके मैसेज स्ट्रीम करना

इस गाइड में, Chat API में StreamMessage संसाधन का इस्तेमाल करके, Google Chat में मैसेज को धीरे-धीरे स्ट्रीम करने का तरीका बताया गया है. स्ट्रीमिंग की सुविधा से, Google Chat ऐप्लिकेशन को लाइव प्रोग्रेस इंडिकेटर, इंटरमीडिएट रीज़निंग या टूल-एक्ज़ीक्यूशन के चरण, और मैसेज को फ़ाइनल करने से पहले, टेक्स्ट के जवाबों को इंक्रीमेंटल तौर पर दिखाने की सुविधा मिलती है.

स्ट्रीमिंग की सुविधा, जनरेटिव एआई की मदद से काम करने वाले Chat ऐप्लिकेशन या लंबे समय तक चलने वाले बैकएंड वर्कफ़्लो के लिए डिज़ाइन की गई है. इनमें पूरा जवाब जनरेट करने में कुछ सेकंड या मिनट लगते हैं.

मैसेज स्ट्रीमिंग की सुविधा कैसे काम करती है

किसी स्पेस में स्टैंडर्ड Message संसाधन बनने से पहले, स्ट्रीमिंग मैसेज को ऐक्टिव स्ट्रीमिंग स्टेटस से गुज़रना पड़ता है:

  1. स्ट्रीम शुरू करना (spaces.streamMessages.create): आपका चैट ऐप्लिकेशन, थ्रेड वाले स्पेस में StreamMessage बनाता है. इसमें उपयोगकर्ता के उस इंटरैक्शन मैसेज का रेफ़रंस दिया जाता है जिसका जवाब दिया जा रहा है. एपीआई, थ्रेड में लाइव प्रोग्रेस इंडिकेटर दिखाता है. साथ ही, StreamMessage संसाधन का नाम और शुरुआती nextChunkToken दिखाता है.
  2. स्ट्रीम (appendStreamMessageContent या patch) को अपडेट करना: Chat ऐप्लिकेशन, आउटपुट जनरेट करने के बाद, नए nextChunkToken का इस्तेमाल करके क्रम से अपडेट भेजता है:
    • टेक्स्ट के नए हिस्सों को जोड़ने, बीच के चरणों को जोड़ने, इनलाइन उद्धरण जोड़ने या progressText को अपडेट करने के लिए, spaces.streamMessages.appendStreamMessageContent को कॉल करें.
    • स्ट्रीम किए गए कॉन्टेंट के हिस्सों को बदलने या progressText को अपडेट करने के लिए, spaces.streamMessages.patch को कॉल करें.
  3. स्ट्रीम को सेव करें या खारिज करें (commit या delete):
    • स्ट्रीम को पूरा करने और उसे स्थायी Message संसाधन में बदलने के लिए, spaces.streamMessages.commit को कॉल करें. कमिट करते समय, सिर्फ़ कमिट किए जा सकने वाले एलिमेंट भी अटैच किए जा सकते हैं. जैसे, कार्ड, ऐक्सेसरी विजेट, और फ़ुटर सोर्स.
    • स्पेस में मैसेज सेव किए बिना, किसी ऐक्टिव स्ट्रीम को खारिज करने के लिए, spaces.streamMessages.delete को कॉल करें.

स्ट्रीम चालू होने पर, सिर्फ़ उस रेफ़रंस मैसेज (referencedMessage) को भेजने वाला व्यक्ति रोकें पर क्लिक करके, जवाब जनरेट होने की प्रोसेस को रद्द कर सकता है जिस पर स्ट्रीम की जा रही है. Chat, आपके चैट ऐप्लिकेशन को रद्द करने का सिस्टम कमांड इवेंट भेजता है, ताकि बैकएंड का काम रोका जा सके. साथ ही, आउटपुट का कुछ हिस्सा सेव किया जा सके या स्ट्रीम को मिटाया जा सके.

ज़रूरी शर्तें

Chat API की मदद से मैसेज स्ट्रीम करने के लिए, ये ज़रूरी शर्तें पूरी करें:

  • Business या Enterprise Google Workspace खाता, जिसमें Google Chat का ऐक्सेस हो.
  • अपना एनवायरमेंट सेट अप करने का तरीका:
  • अपने चैट ऐप्लिकेशन को थ्रेड वाली Chat स्पेस (या 1:1 सीधी बातचीत जिसमें पहले से कम से कम एक मैसेज मौजूद हो) में जोड़ें. इसके बाद, जवाब देने के लिए ऐक्सेस किए जा सकने वाले मैसेज (spaces/SPACE_ID/messages/MESSAGE_ID) का संसाधन नाम पाएं.
  • Python के सैंपल के लिए, Python के लिए Google API क्लाइंट लाइब्रेरी और google-auth इंस्टॉल करें. इसके बाद, Chat API सेवा क्लाइंट को शुरू करें:

    pip install google-api-python-client google-auth
    from 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, स्ट्रीम किए गए जवाब को referencedMessage के तौर पर उसी थ्रेड में पोस्ट करता है.
  • progressText (ज़रूरी है): प्रोग्रेस इंडिकेटर के बगल में दिखने वाला सादे टेक्स्ट वाला स्टेटस लेबल (ज़्यादा से ज़्यादा 250 वर्ण). जैसे, "Thinking...". यह खाली नहीं होना चाहिए.
  • markupSyntax (ज़रूरी नहीं): मैसेज के लिए टेक्स्ट फ़ॉर्मैटिंग सिंटैक्स, जैसे कि MARKUP_SYNTAX_MARKDOWN या MARKUP_SYNTAX_CHAT (अगर MARKUP_SYNTAX_UNSPECIFIED है, तो चैट ऐप्लिकेशन के कॉन्फ़िगर किए गए सिंटैक्स पर डिफ़ॉल्ट रूप से सेट होता है). अगर आपको इनलाइन उद्धरण शामिल करने हैं, तो 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"
}

कॉन्टेंट के हिस्सों को जोड़ना

जब आपका चैट ऐप्लिकेशन, इंटरमीडिएट स्टेप या टेक्स्ट टोकन जनरेट करता है, तो 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"]

स्ट्रीम किए गए कॉन्टेंट या प्रोग्रेस टेक्स्ट को बदलना

अगर आपको पहले से स्ट्रीम किए गए कॉन्टेंट को फिर से लिखना है, तो spaces.streamMessages.patch को कॉल करें. उदाहरण के लिए, पोस्ट-प्रोसेसिंग या सुरक्षा फ़िल्टर चलाने के बाद या चंक जोड़े बिना सिर्फ़ progressText को अपडेट करने के बाद:

  • updateMask को अपडेट किए जाने वाले फ़ील्ड की कॉमा लगाकर अलग की गई सूची पर सेट करें: progressText, streamContentChunks या progressText,streamContentChunks.
  • StreamMessage अनुरोध के मुख्य हिस्से में नया nextChunkToken शामिल करें. साथ ही, जवाब में मिले नए nextChunkToken को रिकॉर्ड करें.
  • जब streamContentChunks, updateMask में होता है, तो उपलब्ध कराए गए चंक, पहले से स्ट्रीम किए गए कॉन्टेंट में जुड़ने के बजाय, उसे बदल देते हैं.
  • जब progressText की वैल्यू updateMask हो, तब progressText की वैल्यू खाली नहीं होनी चाहिए. यह ज़्यादा से ज़्यादा 250 वर्णों का सादा टेक्स्ट होना चाहिए.

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 को बदला गया. फ़ाइनल टेक्स्ट 32,000 बाइट से ज़्यादा नहीं हो सकता.
step create, appendStreamMessageContent, patch, commit elements.steps.steps[] सादे टेक्स्ट title (ज़रूरी है) और वैकल्पिक description के साथ इंटरमीडिएट प्रोसेसिंग चरण.
citation create, appendStreamMessageContent, patch, commit elements.citations[] इनलाइन Citation, जिसमें अक्षर और अंक वाला id (63 से कम वर्ण, अंडरस्कोर इस्तेमाल किए जा सकते हैं) और 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 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 इवेंट मिलता है, तब:

  1. बैकग्राउंड में काम करने वाले वर्कर को सिग्नल भेजें, ताकि वह streamMessage के लिए और टोकन जनरेट करना या डाउनस्ट्रीम टूल चलाना बंद कर दे.
  2. इनमें से किसी एक तरीके का इस्तेमाल करके, चालू स्ट्रीम को बंद करें:
    • Keep partial output: सबसे नए chunkToken के साथ spaces.streamMessages.commit को कॉल करें. इसके अलावा, "\n\n_Generation stopped._" जैसा कोई नोट भी जोड़ा जा सकता है.
    • जवाब को खारिज करना: spaces.streamMessages.delete को कॉल करें, ताकि थ्रेड में कुछ भी सेव न हो.
  3. इंटरैक्शन इवेंट हैंडलर से, खाली एचटीटीपी 200 OK JSON रिस्पॉन्स ({}) दिखाएं.

सीमाएं

मैसेज स्ट्रीमिंग की ये सीमाएं हैं:

  • प्लैटफ़ॉर्म की उपलब्धता: मैसेज स्ट्रीमिंग की सुविधा, सिर्फ़ Chat के वेब वर्शन पर उपलब्ध है. Android और iOS के लिए यह सुविधा जल्द ही उपलब्ध होगी.
  • स्ट्रीम टाइम आउट: चालू StreamMessage, बनने के 10 मिनट बाद बंद हो जाता है. आपके Chat ऐप्लिकेशन को स्ट्रीम शुरू होने के 10 मिनट के अंदर, spaces.streamMessages.commit या spaces.streamMessages.delete को कॉल करना होगा.