Hướng dẫn này giải thích cách truyền trực tuyến tin nhắn theo từng phần trong Google Chat bằng cách sử dụng tài nguyên StreamMessage trong API Chat. Tính năng truyền trực tuyến cho phép
ứng dụng Google Chat hiển thị các chỉ báo tiến trình trực tiếp, các bước suy luận trung gian hoặc thực thi công cụ và các phản hồi văn bản gia tăng trước khi
hoàn tất tin nhắn.
Tính năng truyền trực tuyến được thiết kế cho các ứng dụng Chat dựa trên AI tạo sinh hoặc các quy trình làm việc phụ trợ chạy trong thời gian dài, trong đó việc tạo phản hồi hoàn chỉnh mất vài giây hoặc vài phút.
Cách hoạt động của tính năng truyền tin nhắn trực tuyến
Tin nhắn truyền trực tuyến sẽ trải qua trạng thái truyền trực tuyến đang hoạt động trước khi trở thành tài nguyên Message chuẩn trong một không gian:
- Bắt đầu một chuỗi tin nhắn (
spaces.streamMessages.create): Ứng dụng Chat của bạn tạo mộtStreamMessagetrong một không gian theo chuỗi, tham chiếu đến tin nhắn tương tác của người dùng mà ứng dụng đang trả lời. API này hiển thị chỉ báo tiến trình trực tiếp trong chuỗi tin nhắn và trả về tên tài nguyênStreamMessagevànextChunkTokenban đầu. - Cập nhật luồng (
appendStreamMessageContenthoặcpatch): Khi tạo kết quả, ứng dụng Chat sẽ gửi các bản cập nhật tuần tự bằngnextChunkTokenmới nhất:- Gọi
spaces.streamMessages.appendStreamMessageContentđể nối các đoạn văn bản mới, thêm các bước trung gian, thêm trích dẫn cùng dòng hoặc cập nhậtprogressText. - Gọi
spaces.streamMessages.patchđể thay thế các đoạn nội dung được truyền trực tuyến hoặc cập nhậtprogressTexttại chỗ.
- Gọi
- Hoàn tất hoặc loại bỏ luồng (
commithoặcdelete):- Gọi
spaces.streamMessages.commitđể hoàn tất luồng và chuyển đổi luồng đó thành tài nguyênMessagevĩnh viễn. Bạn cũng có thể đính kèm các phần tử chỉ cam kết như thẻ, tiện ích phụ kiện và nguồn chân trang khi cam kết. - Gọi
spaces.streamMessages.deleteđể loại bỏ một sự kiện phát trực tiếp đang hoạt động mà không lưu tin nhắn trong không gian.
- Gọi
Khi một luồng đang hoạt động, chỉ người gửi tin nhắn được tham chiếu (referencedMessage) đang được truyền trực tuyến mới có thể nhấp vào Dừng để huỷ quá trình tạo. Chat sẽ gửi một sự kiện lệnh hệ thống huỷ đến
ứng dụng Chat của bạn để bạn có thể dừng công việc phụ trợ và
cam kết kết quả một phần hoặc xoá luồng.
Điều kiện tiên quyết
Để truyền trực tuyến tin nhắn bằng API Chat, hãy hoàn tất các điều kiện tiên quyết sau:
- Tài khoản Google Workspace dành cho Doanh nghiệp hoặc Doanh nghiệp lớn có quyền truy cập vào Google Chat.
- Thiết lập môi trường:
- Tạo một dự án trên Google Cloud.
- Bật và định cấu hình API Google Chat bằng tên, biểu tượng và nội dung mô tả cho ứng dụng Chat của bạn.
- Tạo thông tin đăng nhập tài khoản dịch vụ và lưu dưới dạng
credentials.json. Tính năng truyền trực tuyến tin nhắn yêu cầu xác thực ứng dụng bằng phạm vi uỷ quyềnhttps://www.googleapis.com/auth/chat.bot; tính năng xác thực người dùng không được hỗ trợ.
- Thêm ứng dụng Chat vào một không gian Chat theo chuỗi (hoặc tin nhắn trực tiếp 1:1 đã chứa ít nhất một tin nhắn) và lấy tên tài nguyên của một tin nhắn có thể truy cập để trả lời (
spaces/SPACE_ID/messages/MESSAGE_ID). Đối với các mẫu Python, hãy cài đặt Thư viện ứng dụng API của Google cho Python và
google-auth, sau đó khởi động ứng dụng dịch vụ API Chat: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)
Bắt đầu phát trực tiếp
Để bắt đầu truyền trực tuyến câu trả lời, hãy gọi spaces.streamMessages.create và truyền StreamMessage trong nội dung yêu cầu:
referencedMessage(Bắt buộc): Tên tài nguyên của tin nhắn đã kích hoạt phản hồi, được định dạng làspaces/{space}/messages/{message}. Tin nhắn được tham chiếu phải thuộc cùng một không gian và ứng dụng Chat của bạn phải truy cập được. Chat sẽ đăng câu trả lời được truyền trực tuyến trong cùng một chuỗi vớireferencedMessage.progressText(Bắt buộc): Nhãn trạng thái văn bản thuần túy không trống (tối đa 250 ký tự) xuất hiện bên cạnh chỉ báo tiến trình, chẳng hạn như"Thinking...".markupSyntax(Không bắt buộc): Cú pháp định dạng văn bản cho tin nhắn, chẳng hạn nhưMARKUP_SYNTAX_MARKDOWNhoặcMARKUP_SYNTAX_CHAT(mặc định là cú pháp đã định cấu hình của ứng dụng Chat nếuMARKUP_SYNTAX_UNSPECIFIED). ĐặtMARKUP_SYNTAX_MARKDOWNnếu bạn dự định thêm trích dẫn cùng dòng.streamContentChunks(Không bắt buộc): Các đoạntext,stephoặccitationban đầu để hiển thị ngay lập tức.
Lưu cả name (spaces/{space}/streamMessages/{stream_message}) và nextChunkToken từ phản hồi cho các lệnh gọi tiếp theo.
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"]
Phương thức này trả về một tài nguyên StreamMessage:
{
"name": "spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
"nextChunkToken": "INITIAL_CHUNK_TOKEN"
}
Thêm các đoạn nội dung
Khi ứng dụng Chat của bạn tạo ra các bước trung gian hoặc mã thông báo văn bản, hãy gọi spaces.streamMessages.appendStreamMessageContent:
- Truyền
nextChunkTokenmới nhất vàochunkToken. Mỗi lệnh gọi thành công sẽ trả về mộtnextChunkTokenmới mà bạn phải chuyển vào yêu cầu cập nhật hoặc cam kết tiếp theo. - Các đoạn
textnối trực tiếp vào văn bản đã truyền trực tuyến trước đó. Thêm dấu cách hoặc dòng mới nếu cần giữa các đoạn. stepđoạn được thêm vào danh sách các bước trung gian xuất hiện trên thông báo.progressTextlà không bắt buộc. Nếu bạn bỏ quaprogressTexthoặc đặt thành"", Chat sẽ tiếp tục hiển thịprogressTextđã đặt trước đó.
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"]
Thay thế nội dung được truyền trực tuyến hoặc văn bản tiến trình
Nếu bạn cần viết lại nội dung đã truyền trực tuyến trước đó (ví dụ: sau khi chạy bộ lọc an toàn hoặc hậu xử lý) hoặc chỉ cập nhật progressText mà không thêm các đoạn, hãy gọi spaces.streamMessages.patch:
- Đặt
updateMaskthành danh sách các trường được phân tách bằng dấu phẩy để cập nhật:progressText,streamContentChunkshoặcprogressText,streamContentChunks. - Đưa
nextChunkTokenmới nhất vào nội dung yêu cầuStreamMessagevà ghi lạinextChunkTokenmới được trả về trong phản hồi. - Khi
streamContentChunksở chế độupdateMask, các đoạn được cung cấp sẽ thay thế nội dung đã truyền trực tuyến trước đó thay vì thêm vào nội dung đó. Khi
progressTextởupdateMask,progressTextphải là văn bản thuần túy không trống, tối đa 250 ký tự.
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"]
Hoàn tất một sự kiện phát trực tiếp
Khi quá trình tạo hoàn tất, hãy gọi spaces.streamMessages.commit bằng chunkToken mới nhất để hoàn tất luồng thành tài nguyên Message vĩnh viễn:
- Bạn có thể tuỳ ý thêm
streamContentChunkscuối cùng vào yêu cầu cam kết, bao gồm cả các loại đoạn chỉ cam kết (card,accessoryWidgetvàcitedSource). Nếu đã truyền trực tuyến nội dung không trống trong các lệnh gọi trước đó, bạn có thể bỏ qua
streamContentChunkskhi cam kết. Thông báo cam kết cuối cùng không được để trống.
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']}")
Huỷ một luồng đang hoạt động
Nếu xảy ra lỗi không thể khôi phục hoặc người dùng huỷ quá trình tạo và bạn không muốn để lại một phần câu trả lời trong chuỗi, hãy gọi 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()
Sau khi một luồng được cam kết vào Message, hãy gọi spaces.messages.delete nếu bạn cần xoá thông báo đã hoàn tất.
Các loại đoạn nội dung được hỗ trợ
Mỗi mục nhập trong streamContentChunks chỉ định một trường trong hợp nhất StreamContentChunk. Một số loại đoạn có thể được gửi trong suốt luồng, trong khi một số loại khác chỉ được chấp nhận trong spaces.streamMessages.commit:
| Trường đoạn | Các phương thức được hỗ trợ | Trường Message cuối cùng |
Ghi chú |
|---|---|---|---|
text |
create, appendStreamMessageContent,
patch, commit |
text |
Văn bản gia tăng. Được nối vào ngày
appendStreamMessageContent; được thay thế vào ngày patch.
Văn bản cuối cùng được xác nhận không được vượt quá 32.000 byte. |
step |
create, appendStreamMessageContent,
patch, commit |
elements.steps.steps[] |
Bước xử lý trung gian với title văn bản thuần tuý (bắt buộc) và description không bắt buộc. |
citation |
create, appendStreamMessageContent,
patch, commit |
elements.citations[] |
Citation cùng dòng với id gồm chữ và số (dưới 63 ký tự, cho phép dấu gạch dưới) và citedSources. Yêu cầu thẻ markupSyntax: "MARKUP_SYNTAX_MARKDOWN" và thẻ <chat-citation data-id="ID">...</chat-citation> tương ứng trong text. Việc gửi citation có id hiện có sẽ ghi đè trích dẫn trước đó. |
card |
Chỉ commit |
cardsV2[] |
Thẻ CardWithId tương tác hoặc cung cấp thông tin. |
accessoryWidget |
Chỉ commit |
accessoryWidgets[] |
AccessoryWidget nút hiển thị bên dưới thông báo, chẳng hạn như nút phản hồi. |
citedSource |
Chỉ commit |
elements.citedSources[] |
CitedSource đường liên kết ở chân trang xuất hiện bên dưới thông báo
mà không có thẻ trích dẫn cùng dòng. |
Xử lý việc huỷ luồng do người dùng bắt đầu
Khi một luồng đang hoạt động, chỉ người gửi tin nhắn được tham chiếu (referencedMessage) đang được truyền trực tuyến mới có thể nhấp vào Dừng trên tin nhắn truyền trực tuyến. Khi người dùng dừng một sự kiện phát trực tiếp, Chat sẽ gửi một sự kiện tương tác lệnh hệ thống chứa cancelStream.streamMessage (tên tài nguyên spaces/{space}/streamMessages/{stream_message} của sự kiện phát trực tiếp đã dừng) đến điểm cuối của ứng dụng Chat.
Cấu trúc của tải trọng JSON đến phụ thuộc vào việc bạn xây dựng ứng dụng Chat dưới dạng tiện ích bổ sung của Google Workspace hay sử dụng các sự kiện tương tác của API Chat:
Tiện ích bổ sung cho 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"
}
}
}
Khi ứng dụng Chat của bạn nhận được một sự kiện cancelStream:
- Báo hiệu cho trình thực thi trong nền ngừng tạo thêm mã thông báo hoặc chạy các công cụ hạ nguồn cho
streamMessage. - Giải quyết luồng đang hoạt động bằng một trong các phương pháp sau:
- Giữ lại kết quả một phần: Gọi
spaces.streamMessages.commitbằngchunkTokenmới nhất (tuỳ ý thêm ghi chú như"\n\n_Generation stopped._"). - Huỷ thư trả lời: Gọi
spaces.streamMessages.deleteđể không lưu nội dung nào vào chuỗi tin nhắn.
- Giữ lại kết quả một phần: Gọi
- Trả về phản hồi JSON
200 OKHTTP trống ({}) từ trình xử lý sự kiện tương tác.
Các điểm hạn chế
Tính năng truyền trực tuyến tin nhắn có các hạn chế sau:
- Phạm vi cung cấp trên nền tảng: Tính năng truyền trực tuyến tin nhắn chỉ có trong Chat trên web. Chúng tôi sẽ sớm hỗ trợ Android và iOS.
- Hết thời gian chờ của luồng: Một
StreamMessageđang hoạt động sẽ hết thời gian chờ sau 10 phút kể từ khi tạo. Ứng dụng Chat của bạn phải gọispaces.streamMessages.commithoặcspaces.streamMessages.deletetrong vòng 10 phút kể từ khi bắt đầu luồng.