Z tego przewodnika dowiesz się, jak przyrostowo przesyłać wiadomości w Google Chat za pomocą zasobu StreamMessage w interfejsie Chat API. Przesyłanie strumieniowe umożliwia aplikacji Google Chat wyświetlanie wskaźników postępu na żywo, pośrednich wniosków lub kroków wykonywania narzędzia oraz przyrostowych odpowiedzi tekstowych przed sfinalizowaniem wiadomości.
Przesyłanie strumieniowe jest przeznaczone dla aplikacji do Google Chat opartych na generatywnej AI lub długotrwałych przepływach pracy backendu, w których wygenerowanie pełnej odpowiedzi zajmuje kilka sekund lub minut.
Jak działa strumieniowe przesyłanie wiadomości
Zanim wiadomość przesyłana strumieniowo stanie się standardowym zasobem Message w pokoju, przechodzi przez stan aktywnego przesyłania strumieniowego:
- Rozpoczęcie wątku (
spaces.streamMessages.create): aplikacja do Google Chat tworzy obiektStreamMessagew pokoju z wątkami, odwołując się do wiadomości o interakcji użytkownika, na którą odpowiada. Interfejs API wyświetla w wątku wskaźnik postępu na żywo i zwraca nazwę zasobuStreamMessageoraz początkowynextChunkToken. - Zaktualizuj strumień (
appendStreamMessageContentlubpatch): gdy aplikacja Google Chat generuje dane wyjściowe, wysyła kolejne aktualizacje przy użyciu najnowszej wersjinextChunkToken:- Wywołaj
spaces.streamMessages.appendStreamMessageContent, aby połączyć nowe fragmenty tekstu, dołączyć kroki pośrednie, dodać cytaty w tekście lub zaktualizowaćprogressText. - Wywołaj
spaces.streamMessages.patch, aby zastąpić fragmenty treści przesyłanych strumieniowo lub zaktualizowaćprogressTextna miejscu.
- Wywołaj
- Sfinalizuj lub odrzuć strumień (
commitlubdelete):- Wywołaj
spaces.streamMessages.commit, aby sfinalizować strumień i przekonwertować go na stały zasóbMessage. Podczas zatwierdzania możesz też dołączać elementy, które można tylko zatwierdzić, takie jak karty, widżety akcesoriów i źródła w stopce. - Wywołaj
spaces.streamMessages.delete, aby odrzucić aktywny strumień bez zapisywania wiadomości w pokoju.
- Wywołaj
Gdy strumień jest aktywny, tylko nadawca wiadomości, do której się odnosi (referencedMessage), może kliknąć Zatrzymaj, aby anulować generowanie. Google Chat wysyła do aplikacji do Google Chat zdarzenie polecenia systemowego anulowania, dzięki czemu możesz zatrzymać pracę backendu i zatwierdzić częściowe dane wyjściowe lub usunąć strumień.
Wymagania wstępne
Aby przesyłać wiadomości strumieniowo za pomocą interfejsu Chat API, musisz spełnić te wymagania wstępne:
- Konto Google Workspace w wersji Business lub Enterprise z dostępem do Google Chat.
- Skonfiguruj środowisko:
- Utwórz projekt Google Cloud.
- Włącz i skonfiguruj interfejs Google Chat API, podając nazwę, ikonę i opis aplikacji do Google Chat.
- Utwórz dane logowania konta usługi i zapisz je jako
credentials.json. Strumieniowe przesyłanie wiadomości wymaga uwierzytelniania aplikacji z zakresem autoryzacjihttps://www.googleapis.com/auth/chat.bot. Uwierzytelnianie użytkownika nie jest obsługiwane.
- Dodaj aplikację do Google Chat do pokoju w Google Chat z wątkami (lub do czatu indywidualnego, który zawiera już co najmniej 1 wiadomość) i uzyskaj nazwę zasobu dostępnej wiadomości, na którą chcesz odpowiedzieć (
spaces/SPACE_ID/messages/MESSAGE_ID). W przypadku przykładów w Pythonie zainstaluj bibliotekę klienta interfejsu API Google dla Pythona i
google-auth, a następnie zainicjuj klienta usługi 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)
Rozpoczynanie transmisji
Aby rozpocząć strumieniowe przesyłanie odpowiedzi, wywołaj spaces.streamMessages.create i przekaż StreamMessage w treści żądania:
referencedMessage(wymagany): nazwa zasobu wiadomości, która wywołała odpowiedź, sformatowana jakospaces/{space}/messages/{message}. Wiadomość, do której się odwołujesz, musi należeć do tego samego pokoju i być dostępna dla aplikacji Google Chat. Google Chat opublikuje odpowiedź w tym samym wątku coreferencedMessage.progressText(wymagany): niepusta etykieta stanu w formie zwykłego tekstu (do 250 znaków) wyświetlana obok wskaźnika postępu, np."Thinking...".markupSyntax(opcjonalnie): składnia formatowania tekstu wiadomości, np.MARKUP_SYNTAX_MARKDOWNlubMARKUP_SYNTAX_CHAT(domyślnie jest to składnia skonfigurowana w aplikacji Google Chat, jeśliMARKUP_SYNTAX_UNSPECIFIED). UstawMARKUP_SYNTAX_MARKDOWN, jeśli planujesz dołączyć cytaty w tekście.streamContentChunks(opcjonalnie): początkowe fragmentytext,steplubcitation, które mają być wyświetlane od razu.
Zapisz zarówno name (spaces/{space}/streamMessages/{stream_message}), jak i nextChunkToken z odpowiedzi na potrzeby kolejnych wywołań.
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"]
Metoda zwraca zasób StreamMessage:
{
"name": "spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
"nextChunkToken": "INITIAL_CHUNK_TOKEN"
}
Dołączanie fragmentów treści
Gdy aplikacja do Google Chat generuje etapy pośrednie lub tokeny tekstowe, wywołaj spaces.streamMessages.appendStreamMessageContent:
- Przekaż najnowszą wersję
nextChunkTokenwchunkToken. Każde udane wywołanie zwraca nowy obiektnextChunkToken, który musisz przekazać w następnym żądaniu aktualizacji lub zatwierdzenia. - Fragmenty
textsą łączone bezpośrednio z poprzednio przesłanym tekstem. W razie potrzeby dodaj spacje lub znaki nowego wiersza między fragmentami. - Do listy kroków pośrednich wyświetlanych w komunikacie dodawane są fragmenty
step. progressTextjest opcjonalny. Jeśli pominiesz parametrprogressTextlub ustawisz go na"", Google Chat będzie nadal wyświetlać wcześniej ustawioną wartość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"]
Zastępowanie treści przesyłanych strumieniowo lub tekstu postępu
Jeśli chcesz ponownie zapisać wcześniej przesłane treści – na przykład po uruchomieniu przetwarzania końcowego lub filtra bezpieczeństwa – lub zaktualizować tylko progressText bez dołączania fragmentów, wywołaj spaces.streamMessages.patch:
- Ustaw
updateMaskna listę rozdzielonych przecinkami pól do zaktualizowania:progressText,streamContentChunkslubprogressText,streamContentChunks. - Dołącz najnowszy parametr
nextChunkTokendo treści żądaniaStreamMessagei zapisz nowy parametrnextChunkTokenzwrócony w odpowiedzi. - Gdy parametr
streamContentChunksma wartośćupdateMask, podane fragmenty zastępują wcześniej przesłane treści, zamiast być do nich dołączane. Gdy
progressTextjest wupdateMask,progressTextnie może być puste. Zwykły tekst o długości do 250 znaków.
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"]
Finalizowanie strumienia
Po zakończeniu generowania wywołaj spaces.streamMessages.commit z najnowszym chunkToken, aby sfinalizować strumień w stały zasób Message:
- W żądaniu zatwierdzenia możesz opcjonalnie uwzględnić końcowe
streamContentChunks, w tym typy fragmentów tylko do zatwierdzenia (card,accessoryWidgeticitedSource). Jeśli w poprzednich wywołaniach przesłano już niepuste treści, podczas zatwierdzania możesz pominąć
streamContentChunks. Ostatnia zatwierdzona wiadomość nie może być pusta.
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']}")
Odrzucanie aktywnego strumienia
Jeśli wystąpi nieodwracalny błąd lub użytkownik anuluje generowanie, a nie chcesz pozostawiać w wątku częściowej odpowiedzi, wywołaj 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()
Jeśli strumień został zatwierdzony w Message, wywołaj spaces.messages.delete, jeśli chcesz usunąć sfinalizowaną wiadomość.
Obsługiwane typy fragmentów treści
Każdy wpis w streamContentChunks określa jedno pole w unii StreamContentChunk. Niektóre typy fragmentów można wysyłać przez cały czas trwania transmisji, a inne są akceptowane tylko w spaces.streamMessages.commit:
| Pole fragmentu | Obsługiwane metody | Pole Message końcowe |
Uwagi |
|---|---|---|---|
text |
create, appendStreamMessageContent,
patch, commit |
text |
Tekst przyrostowy. Połączono appendStreamMessageContent; zastąpiono patch.
Ostateczny zatwierdzony tekst nie może przekraczać 32 000 bajtów. |
step |
create, appendStreamMessageContent,
patch, commit |
elements.steps.steps[] |
Pośredni etap przetwarzania z użyciem zwykłego tekstu title (wymagany) i opcjonalnego description. |
citation |
create, appendStreamMessageContent,
patch, commit |
elements.citations[] |
Wstaw w tekście Citation z alfanumerycznym id (mniej niż 63 znaki, dozwolone podkreślenia) i citedSources. Wymaga tagów markupSyntax: "MARKUP_SYNTAX_MARKDOWN" i pasujących tagów <chat-citation data-id="ID">...</chat-citation> w text. Wysłanie citation z istniejącym id zastępuje wcześniejszy cytat. |
card |
Tylko commit |
cardsV2[] |
Karta interaktywna lub informacyjna CardWithId. |
accessoryWidget |
Tylko commit |
accessoryWidgets[] |
AccessoryWidget przyciski wyświetlane pod wiadomością, np. przyciski do wysyłania opinii. |
citedSource |
Tylko commit |
elements.citedSources[] |
CitedSource link w stopce wyświetlany pod wiadomością bez tagów cytatów w tekście. |
Obsługa anulowania strumienia przez użytkownika
Gdy strumień jest aktywny, tylko nadawca wiadomości, do której odnosi się strumień (referencedMessage), może kliknąć Zatrzymaj w wiadomości strumieniowej. Gdy użytkownik zatrzyma strumień, Google Chat wysyła do punktu końcowego aplikacji do Google Chat zdarzenie interakcji polecenia systemowego zawierające cancelStream.streamMessage (nazwę zasobu spaces/{space}/streamMessages/{stream_message} zatrzymanego strumienia).
Struktura przychodzącego ładunku JSON zależy od tego, czy tworzysz aplikację Google Chat jako dodatek do Google Workspace, czy za pomocą zdarzeń interakcji interfejsu Chat API:
Dodatki do 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"
}
}
}
}
}
Interfejs API aplikacji Google Chat
{
"type": "SYSTEM_COMMAND",
"space": {
"name": "spaces/SPACE_ID"
},
"user": {
"name": "users/USER_ID"
},
"systemCommandMetadata": {
"cancelStream": {
"streamMessage": "spaces/SPACE_ID/streamMessages/STREAM_ID"
}
}
}
Gdy aplikacja do Google Chat otrzyma zdarzenie cancelStream:
- Zasygnalizuj pracownikowi działającemu w tle, aby przestał generować kolejne tokeny lub uruchamiać narzędzia podrzędne dla:
streamMessage. - Rozwiąż problem z aktywną transmisją, korzystając z jednej z tych metod:
- Zachowaj częściowe dane wyjściowe: wywołaj
spaces.streamMessages.commitz najnowszymchunkToken(opcjonalnie dodając notatkę, np."\n\n_Generation stopped._"). - Odrzucenie odpowiedzi: wywołaj
spaces.streamMessages.delete, aby nic nie zostało zapisane w wątku.
- Zachowaj częściowe dane wyjściowe: wywołaj
- Zwróć pustą odpowiedź HTTP
200 OKJSON ({}) z modułu obsługi zdarzeń interakcji.
Ograniczenia
Strumień wiadomości ma następujące ograniczenia:
- Dostępność platformy: strumieniowe przesyłanie wiadomości jest widoczne tylko w Google Chat w przeglądarce. Obsługa Androida i iOS już wkrótce.
- Przekroczenie limitu czasu strumienia: aktywny strumień
StreamMessagewygasa po 10 minutach od utworzenia. Aplikacja Google Chat musi wywołać metodęspaces.streamMessages.commitlubspaces.streamMessages.deletew ciągu 10 minut od rozpoczęcia strumienia.