Khám phá trong Dialogflow
Nhấp vào Tiếp tục để nhập mẫu Phản hồi của chúng tôi vào Dialogflow. Sau đó, hãy làm theo các bước bên dưới để triển khai và thử nghiệm mẫu:
- Nhập tên nhân viên hỗ trợ và tạo một nhân viên hỗ trợ Dialogflow mới cho mẫu.
- Sau khi nhân viên hỗ trợ nhập xong, hãy nhấp vào Chuyển đến nhân viên hỗ trợ.
- Trong trình đơn điều hướng chính, hãy chuyển đến phần Fulfillment (Thực hiện đơn hàng).
- Bật Inline Editor (Trình chỉnh sửa cùng dòng), sau đó nhấp vào Deploy (Triển khai). Trình chỉnh sửa chứa mẫu .
- Trong trình đơn điều hướng chính, hãy chuyển đến mục Tích hợp, rồi nhấp vào Google Trợ lý Google.
- Trong cửa sổ phụ xuất hiện, hãy bật tuỳ chọn Tự động xem trước các thay đổi rồi nhấp vào Kiểm tra để mở Trình mô phỏng thao tác.
- Trong trình mô phỏng, hãy nhập
Talk to my test app
để kiểm tra mẫu!
Sử dụng câu trả lời đa dạng thức nếu bạn muốn hiển thị các yếu tố hình ảnh để nâng cao chất lượng cho người dùng với Hành động của bạn. Những phần tử hình ảnh này có thể đưa ra gợi ý về cách để tiếp tục cuộc trò chuyện.
Câu trả lời nhiều định dạng có thể xuất hiện trong trải nghiệm chỉ có màn hình hoặc trải nghiệm âm thanh và màn hình. Chúng có thể chứa các thành phần sau:
- Một hoặc hai câu trả lời đơn giản (bong bóng trò chuyện).
- Thẻ cơ bản không bắt buộc.
- Khối đề xuất không bắt buộc.
- Một khối liên kết ra (không bắt buộc).
Bạn cũng có thể xem nguyên tắc thiết kế cuộc trò chuyện của chúng tôi để tìm hiểu cách kết hợp các thành phần hình ảnh này vào Hành động của bạn.
Thuộc tính
Câu trả lời nhiều định dạng có những yêu cầu sau đây và không bắt buộc các thuộc tính mà bạn có thể định cấu hình:
- Được hỗ trợ trên các nền tảng có chức năng
actions.capability.SCREEN_OUTPUT
. - Mục đầu tiên trong phản hồi nhiều định dạng phải là phản hồi đơn giản.
- Tối đa là hai câu trả lời đơn giản.
- Tối đa một thẻ cơ bản hoặc
StructuredResponse
. - Tối đa 8 khối đề xuất.
- Không được phép sử dụng khối đề xuất trong
FinalResponse
- Tính năng liên kết đến web từ màn hình thông minh hiện không được hỗ trợ.
Các phần sau đây cho bạn biết cách tạo nhiều loại phản hồi đa dạng thức.
Thẻ cơ bản
Một thẻ cơ bản cho thấy thông tin có thể bao gồm:
- Bài đăng có hình ảnh
- Tiêu đề
- Phụ đề
- Nội dung văn bản
- Nút liên kết
- Đường viền
Chủ yếu sử dụng các thẻ cơ bản cho mục đích hiển thị. Chúng được thiết kế để ngắn gọn, để trình bày thông tin quan trọng (hoặc tóm tắt) cho người dùng và cho phép người dùng tìm hiểu nếu bạn chọn (bằng cách sử dụng đường liên kết trang web).
Trong hầu hết trường hợp, bạn nên thêm khối đề xuất ở bên dưới các thẻ để tiếp tục hoặc chuyển hướng cuộc trò chuyện.
Tránh lặp lại thông tin trình bày trong thẻ trong bong bóng trò chuyện chi phí.
Thuộc tính
Loại phản hồi cơ bản của thẻ có các yêu cầu sau và không bắt buộc các thuộc tính mà bạn có thể định cấu hình:
- Được hỗ trợ trên các nền tảng có chức năng
actions.capability.SCREEN_OUTPUT
. - Văn bản được định dạng (bắt buộc nếu không có hình ảnh)
- Văn bản thuần tuý theo mặc định.
- Không được chứa đường liên kết.
- Giới hạn 10 dòng đối với một hình ảnh, tối đa 15 dòng đối với hình ảnh. Vấn đề này liên quan đến 500 (có hình ảnh) hoặc 750 (không có hình ảnh) ký tự. Điện thoại màn hình nhỏ hơn cũng có thể cắt ngắn văn bản so với điện thoại có màn hình lớn hơn. Nếu văn bản cũng chứa nhiều dòng, nhưng dòng này được cắt ngắn ở dấu ngắt từ cuối cùng bằng dấu ba chấm.
- Một số ít Markdown được hỗ trợ:
- Dòng mới với một dấu cách đôi, tiếp theo là \n
**bold**
*italics*
- Hình ảnh (bắt buộc nếu không có văn bản được định dạng)
- Tất cả hình ảnh phải có chiều cao là 192 dp.
- Nếu tỷ lệ khung hình của hình ảnh khác với tỷ lệ khung hình của màn hình, thì hình ảnh ở giữa bằng các thanh màu xám trên các cạnh dọc hoặc ngang.
- Nguồn hình ảnh là một URL.
- Cho phép GIF chuyển động.
Không bắt buộc
- Tên sách
- Văn bản thuần túy.
- Phông chữ và kích thước cố định.
- Tối đa một dòng; ký tự thừa bị cắt ngắn.
- Chiều cao của thẻ sẽ thu gọn nếu bạn không chỉ định tiêu đề.
- Phụ đề
- Văn bản thuần túy.
- Phông chữ và kích thước phông chữ cố định.
- Tối đa một dòng; ký tự thừa bị cắt ngắn.
- Chiều cao của thẻ sẽ thu gọn nếu bạn không chỉ định phụ đề.
- Nút liên kết
- Bạn phải điền tiêu đề của đường liên kết
- Tối đa một đường liên kết
- Được phép liên kết đến các trang web bên ngoài miền của nhà phát triển.
- Văn bản liên kết không được gây hiểu lầm. Điều này được kiểm tra trong quy trình phê duyệt.
- Thẻ cơ bản không thể tương tác nếu không có đường liên kết. Nhấn vào đường liên kết đưa người dùng đến đường liên kết trong khi phần chính của thẻ vẫn không hoạt động.
- Đường viền
- Bạn có thể điều chỉnh đường viền giữa thẻ và vùng chứa hình ảnh thành tuỳ chỉnh cách trình bày thẻ cơ bản.
- Được định cấu hình bằng cách đặt thuộc tính chuỗi JSON
imageDisplayOptions
Mã mẫu
Node.js
app.intent('Basic Card', (conv) => { if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask(`Here's an example of a basic card.`); conv.ask(new BasicCard({ text: `This is a basic card. Text in a basic card can include "quotes" and most other unicode characters including emojis. Basic cards also support some markdown formatting like *emphasis* or _italics_, **strong** or __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other things like line \nbreaks`, // Note the two spaces before '\n' required for // a line break to be rendered in the card. subtitle: 'This is a subtitle', title: 'Title: this is a title', buttons: new Button({ title: 'This is a button', url: 'https://assistant.google.com/', }), image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), display: 'CROPPED', })); conv.ask('Which response would you like to see next?'); });
Java
@ForIntent("Basic Card") public ActionResponse basicCard(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } // Prepare formatted text for card String text = "This is a basic card. Text in a basic card can include \"quotes\" and\n" + " most other unicode characters including emoji \uD83D\uDCF1. Basic cards also support\n" + " some markdown formatting like *emphasis* or _italics_, **strong** or\n" + " __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n" + " things like line \\nbreaks"; // Note the two spaces before '\n' required for // a line break to be rendered in the card. responseBuilder .add("Here's an example of a basic card.") .add( new BasicCard() .setTitle("Title: this is a title") .setSubtitle("This is a subtitle") .setFormattedText(text) .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setImageDisplayOptions("CROPPED") .setButtons( new ArrayList<Button>( Arrays.asList( new Button() .setTitle("This is a Button") .setOpenUrlAction( new OpenUrlAction().setUrl("https://assistant.google.com")))))) .add("Which response would you like to see next?"); return responseBuilder.build(); }
Node.js
if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask(`Here's an example of a basic card.`); conv.ask(new BasicCard({ text: `This is a basic card. Text in a basic card can include "quotes" and most other unicode characters including emojis. Basic cards also support some markdown formatting like *emphasis* or _italics_, **strong** or __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other things like line \nbreaks`, // Note the two spaces before '\n' required for // a line break to be rendered in the card. subtitle: 'This is a subtitle', title: 'Title: this is a title', buttons: new Button({ title: 'This is a button', url: 'https://assistant.google.com/', }), image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), display: 'CROPPED', })); conv.ask('Which response would you like to see next?');
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } // Prepare formatted text for card String text = "This is a basic card. Text in a basic card can include \"quotes\" and\n" + " most other unicode characters including emoji \uD83D\uDCF1. Basic cards also support\n" + " some markdown formatting like *emphasis* or _italics_, **strong** or\n" + " __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n" + " things like line \\nbreaks"; // Note the two spaces before '\n' required for // a line break to be rendered in the card. responseBuilder .add("Here's an example of a basic card.") .add( new BasicCard() .setTitle("Title: this is a title") .setSubtitle("This is a subtitle") .setFormattedText(text) .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setImageDisplayOptions("CROPPED") .setButtons( new ArrayList<Button>( Arrays.asList( new Button() .setTitle("This is a Button") .setOpenUrlAction( new OpenUrlAction().setUrl("https://assistant.google.com")))))) .add("Which response would you like to see next?"); return responseBuilder.build();
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Here's an example of a basic card." } }, { "basicCard": { "title": "Title: this is a title", "subtitle": "This is a subtitle", "formattedText": "This is a basic card. Text in a basic card can include \"quotes\" and\n most other unicode characters including emojis. Basic cards also support\n some markdown formatting like *emphasis* or _italics_, **strong** or\n __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n things like line \nbreaks", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" }, "buttons": [ { "title": "This is a button", "openUrlAction": { "url": "https://assistant.google.com/" } } ], "imageDisplayOptions": "CROPPED" } }, { "simpleResponse": { "textToSpeech": "Which response would you like to see next?" } } ] } } } }
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Here's an example of a basic card." } }, { "basicCard": { "title": "Title: this is a title", "subtitle": "This is a subtitle", "formattedText": "This is a basic card. Text in a basic card can include \"quotes\" and\n most other unicode characters including emojis. Basic cards also support\n some markdown formatting like *emphasis* or _italics_, **strong** or\n __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n things like line \nbreaks", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" }, "buttons": [ { "title": "This is a button", "openUrlAction": { "url": "https://assistant.google.com/" } } ], "imageDisplayOptions": "CROPPED" } }, { "simpleResponse": { "textToSpeech": "Which response would you like to see next?" } } ] } } } ] }
Băng chuyền duyệt web
Băng chuyền duyệt web là một loại phản hồi đa dạng thức cho phép người dùng cuộn theo chiều dọc rồi chọn một thẻ thông tin trong bộ sưu tập. Băng chuyền duyệt web được thiết kế riêng đối với nội dung trên web bằng cách mở ô đã chọn trong một trình duyệt web (hoặc trình duyệt AMP nếu tất cả các ô đều hỗ trợ AMP). Băng chuyền duyệt web cũng vẫn duy trì trên nền tảng Trợ lý của người dùng để duyệt web sau.
Thuộc tính
Loại phản hồi duyệt qua băng chuyền có các yêu cầu sau và không bắt buộc các thuộc tính mà bạn có thể định cấu hình:
- Được hỗ trợ trên các nền tảng có cả
actions.capability.SCREEN_OUTPUT
vàactions.capability.WEB_BROWSER
. Loại phản hồi này là hiện không dùng được trên màn hình thông minh. - Băng chuyền duyệt web
- Tối đa 10 ô.
- Tối thiểu 2 ô.
- Tất cả các thẻ thông tin trong băng chuyền phải liên kết đến nội dung web (nội dung AMP
khuyến nghị).
- Để người dùng được đưa đến trình xem AMP,
urlHintType
trên ô nội dung AMP phải được đặt thành "AMP_CONTENT".
- Để người dùng được đưa đến trình xem AMP,
- Duyệt qua ô băng chuyền
- Tính nhất quán của thẻ thông tin (bắt buộc):
- Tất cả các thẻ thông tin trong một băng chuyền duyệt web phải có cùng các thành phần. Ví dụ: nếu một thẻ thông tin có trường hình ảnh, thì các thẻ thông tin còn lại trong băng chuyền cũng phải có trường hình ảnh.
- Nếu tất cả các ô trong băng chuyền duyệt web liên kết đến nội dung hỗ trợ AMP, người dùng sẽ được chuyển đến một trình duyệt AMP có thêm chức năng. Nếu thẻ thông tin bất kỳ liên kết đến nội dung không phải AMP, thì tất cả các thẻ thông tin đều chuyển hướng người dùng trên trình duyệt web.
- Hình ảnh (không bắt buộc)
- Hình ảnh bắt buộc phải có kích thước cao 128 dp x rộng 232 dp.
- Nếu tỷ lệ khung hình của hình ảnh không phù hợp với hộp giới hạn hình ảnh, thì hình ảnh đó sẽ được căn giữa với các thanh ở hai bên. Trên điện thoại thông minh, ảnh được căn giữa ở dạng hình vuông với góc bo tròn.
- Nếu đường liên kết của hình ảnh bị hỏng, thì hệ thống sẽ dùng hình ảnh ở dạng phần giữ chỗ.
- Phải có văn bản thay thế trên hình ảnh.
- Tiêu đề (bắt buộc)
- Tuỳ chọn định dạng giống với thẻ văn bản cơ bản.
- Tiêu đề phải là duy nhất (để hỗ trợ chọn giọng nói).
- Tối đa 2 dòng văn bản.
- Cỡ chữ 16 sp.
- Nội dung mô tả (không bắt buộc)
- Tuỳ chọn định dạng giống với thẻ văn bản cơ bản.
- Tối đa 4 dòng văn bản.
- Được cắt ngắn bằng dấu ba chấm (...)
- Cỡ chữ 14sp, màu xám.
- Chân trang (không bắt buộc)
- Phông chữ và kích thước phông chữ cố định.
- Tối đa một dòng văn bản.
- Được cắt ngắn bằng dấu ba chấm (...)
- Được neo ở dưới cùng, nên các thẻ thông tin có ít dòng văn bản nội dung hơn có thể có khoảng trắng phía trên văn bản phụ.
- Cỡ chữ 14sp, màu xám.
- Tính nhất quán của thẻ thông tin (bắt buộc):
- Lần tương tác
- Người dùng có thể cuộn theo chiều dọc để xem các mục.
- Thẻ nhấn: Khi nhấn vào một mục, người dùng sẽ được đưa đến một trình duyệt, hiển thị trang được liên kết.
- Nhập bằng giọng nói
- Cách hoạt động của micrô
- Micrô sẽ không mở lại khi băng chuyền duyệt web được gửi tới người dùng.
- Người dùng vẫn có thể nhấn vào micrô hoặc gọi Trợ lý ("Ok Google") để mở lại micrô.
- Cách hoạt động của micrô
Hướng dẫn
Theo mặc định, micrô sẽ vẫn ở trạng thái đóng sau khi gửi băng chuyền duyệt qua. Nếu bạn muốn để tiếp tục cuộc trò chuyện sau đó, bạn nên thêm khối đề xuất bên dưới băng chuyền.
Không bao giờ lặp lại các tuỳ chọn có trong danh sách dưới dạng khối đề xuất. Khoai tây chiên trong ngữ cảnh này được dùng để tổng hợp cuộc trò chuyện (không phải để lựa chọn).
Tương tự như với danh sách, bong bóng trò chuyện đi kèm với thẻ băng chuyền là một một tập hợp con của âm thanh (TTS/SSML). Âm thanh (TTS/SSML) ở đây tích hợp ô trong băng chuyền và bạn cũng không nên đọc tất cả các thành phần khỏi băng chuyền. Tốt nhất là bạn nên đề cập đến mục đầu tiên và lý do tại sao bộ sưu tập đó (ví dụ: video phổ biến nhất, được mua gần đây nhất, nói về).
Mã mẫu
Node.js
app.intent('Browsing Carousel', (conv) => { if (!conv.screen || !conv.surface.capabilities.has('actions.capability.WEB_BROWSER')) { conv.ask('Sorry, try this on a phone or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask(`Here's an example of a browsing carousel.`); conv.ask(new BrowseCarousel({ items: [ new BrowseCarouselItem({ title: 'Title of item 1', url: 'https://example.com', description: 'Description of item 1', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), footer: 'Item 1 footer', }), new BrowseCarouselItem({ title: 'Title of item 2', url: 'https://example.com', description: 'Description of item 2', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), footer: 'Item 2 footer', }), ], })); });
Java
@ForIntent("Browsing Carousel") public ActionResponse browseCarousel(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue()) || !request.hasCapability(Capability.WEB_BROWSER.getValue())) { return responseBuilder .add("Sorry, try this on a phone or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("Here's an example of a browsing carousel.") .add( new CarouselBrowse() .setItems( new ArrayList<CarouselBrowseItem>( Arrays.asList( new CarouselBrowseItem() .setTitle("Title of item 1") .setDescription("Description of item 1") .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com")) .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setFooter("Item 1 footer"), new CarouselBrowseItem() .setTitle("Title of item 2") .setDescription("Description of item 2") .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com")) .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setFooter("Item 2 footer"))))); return responseBuilder.build(); }
Node.js
if (!conv.screen || !conv.surface.capabilities.has('actions.capability.WEB_BROWSER')) { conv.ask('Sorry, try this on a phone or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask(`Here's an example of a browsing carousel.`); conv.ask(new BrowseCarousel({ items: [ new BrowseCarouselItem({ title: 'Title of item 1', url: 'https://example.com', description: 'Description of item 1', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), footer: 'Item 1 footer', }), new BrowseCarouselItem({ title: 'Title of item 2', url: 'https://example.com', description: 'Description of item 2', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), footer: 'Item 2 footer', }), ], }));
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue()) || !request.hasCapability(Capability.WEB_BROWSER.getValue())) { return responseBuilder .add("Sorry, try this on a phone or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("Here's an example of a browsing carousel.") .add( new CarouselBrowse() .setItems( new ArrayList<CarouselBrowseItem>( Arrays.asList( new CarouselBrowseItem() .setTitle("Title of item 1") .setDescription("Description of item 1") .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com")) .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setFooter("Item 1 footer"), new CarouselBrowseItem() .setTitle("Title of item 2") .setDescription("Description of item 2") .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com")) .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setFooter("Item 2 footer"))))); return responseBuilder.build();
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "Here's an example of a browsing carousel." } }, { "carouselBrowse": { "items": [ { "title": "Title of item 1", "openUrlAction": { "url": "https://example.com" }, "description": "Description of item 1", "footer": "Item 1 footer", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" } }, { "title": "Title of item 2", "openUrlAction": { "url": "https://example.com" }, "description": "Description of item 2", "footer": "Item 2 footer", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" } } ] } } ] } } } }
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "Here's an example of a browsing carousel." } }, { "carouselBrowse": { "items": [ { "description": "Description of item 1", "footer": "Item 1 footer", "image": { "accessibilityText": "Image alternate text", "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png" }, "openUrlAction": { "url": "https://example.com" }, "title": "Title of item 1" }, { "description": "Description of item 2", "footer": "Item 2 footer", "image": { "accessibilityText": "Image alternate text", "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png" }, "openUrlAction": { "url": "https://example.com" }, "title": "Title of item 2" } ] } } ] } }, "possibleIntents": [ { "intent": "actions.intent.TEXT" } ] } ] }
Xử lý mục đã chọn
Không cần thực hiện thêm hành động tiếp theo cho các hoạt động tương tác của người dùng với băng chuyền duyệt qua vì băng chuyền xử lý quá trình chuyển giao trình duyệt. Xin lưu ý rằng micrô sẽ không mở lại sau khi người dùng tương tác với một mục băng chuyền duyệt qua. Vì vậy, bạn nên kết thúc cuộc trò chuyện hoặc thêm khối đề xuất trong câu trả lời của bạn theo hướng dẫn ở trên.
Khối đề xuất
Sử dụng khối đề xuất để gợi ý câu trả lời nhằm tiếp tục hoặc chuyển hướng cuộc trò chuyện. Nếu có một lời kêu gọi hành động chính trong cuộc trò chuyện, hãy cân nhắc liệt kê làm khối đề xuất đầu tiên.
Bất cứ khi nào có thể, bạn nên đưa một gợi ý quan trọng vào cuộc trò chuyện bong bóng trò chuyện nhưng chỉ làm vậy nếu câu trả lời hoặc cuộc trò chuyện trở nên tự nhiên.
Thuộc tính
Khối đề xuất có những yêu cầu sau đây và không bắt buộc các thuộc tính mà bạn có thể định cấu hình:
- Được hỗ trợ trên các nền tảng có chức năng
actions.capability.SCREEN_OUTPUT
. - Để liên kết khối đề xuất chuyển sang web, các nền tảng cũng phải có
Chức năng
actions.capability.WEB_BROWSER
. Tính năng này hiện không có trên màn hình thông minh. - Tối đa 8 khối.
- Độ dài văn bản tối đa là 25 ký tự.
Chỉ hỗ trợ văn bản thuần tuý.
Mã mẫu
Node.js
app.intent('Suggestion Chips', (conv) => { if (!conv.screen) { conv.ask('Chips can be demonstrated on screen devices.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('These are suggestion chips.'); conv.ask(new Suggestions('Suggestion 1')); conv.ask(new Suggestions(['Suggestion 2', 'Suggestion 3'])); conv.ask(new LinkOutSuggestion({ name: 'Suggestion Link', url: 'https://assistant.google.com/', })); conv.ask('Which type of response would you like to see next?'); ; });
Java
@ForIntent("Suggestion Chips") public ActionResponse suggestionChips(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("These are suggestion chips.") .addSuggestions(new String[] {"Suggestion 1", "Suggestion 2", "Suggestion 3"}) .add( new LinkOutSuggestion() .setDestinationName("Suggestion Link") .setUrl("https://assistant.google.com/")) .add("Which type of response would you like to see next?"); return responseBuilder.build(); }
Node.js
if (!conv.screen) { conv.ask('Chips can be demonstrated on screen devices.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('These are suggestion chips.'); conv.ask(new Suggestions('Suggestion 1')); conv.ask(new Suggestions(['Suggestion 2', 'Suggestion 3'])); conv.ask(new LinkOutSuggestion({ name: 'Suggestion Link', url: 'https://assistant.google.com/', })); conv.ask('Which type of response would you like to see next?');
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("These are suggestion chips.") .addSuggestions(new String[] {"Suggestion 1", "Suggestion 2", "Suggestion 3"}) .add( new LinkOutSuggestion() .setDestinationName("Suggestion Link") .setUrl("https://assistant.google.com/")) .add("Which type of response would you like to see next?"); return responseBuilder.build();
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "These are suggestion chips." } }, { "simpleResponse": { "textToSpeech": "Which type of response would you like to see next?" } } ], "suggestions": [ { "title": "Suggestion 1" }, { "title": "Suggestion 2" }, { "title": "Suggestion 3" } ], "linkOutSuggestion": { "destinationName": "Suggestion Link", "url": "https://assistant.google.com/" } } } } }
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "These are suggestion chips." } }, { "simpleResponse": { "textToSpeech": "Which type of response would you like to see next?" } } ], "suggestions": [ { "title": "Suggestion 1" }, { "title": "Suggestion 2" }, { "title": "Suggestion 3" } ], "linkOutSuggestion": { "destinationName": "Suggestion Link", "url": "https://assistant.google.com/" } } } } ] }
Phản hồi về nội dung nghe nhìn
Phản hồi nội dung đa phương tiện cho phép Hành động của bạn phát nội dung âm thanh trong thời lượng phát dài hơn giới hạn 240 giây của SSML. Thành phần chính của nội dung nghe nhìn là thẻ "một dấu". Thẻ này cho phép người dùng thực hiện toán tử:
- Phát lại 10 giây vừa qua.
- Tua đi 30 giây.
- Xem tổng thời lượng của nội dung nghe nhìn.
- Xem chỉ báo tiến trình để phát âm thanh.
- Xem thời gian phát đã trôi qua.
Tính năng phản hồi nội dung đa phương tiện hỗ trợ các chế độ điều khiển âm thanh sau đây cho tương tác bằng giọng nói:
- “Ok Google, phát.”
- "Ok Google, tạm dừng."
- "Ok Google, dừng lại."
- “Ok Google, bắt đầu lại.”
Người dùng cũng có thể điều khiển âm lượng bằng cách nói các cụm từ như "Ok Google, xoay tăng âm lượng." hoặc "Ok Google, đặt âm lượng ở mức 50%". Ý định trong Hành động sẽ được ưu tiên nếu chúng xử lý các cụm từ huấn luyện tương tự nhau. Cho phép Trợ lý xử lý các yêu cầu của người dùng này trừ phi Hành động của bạn có lý do cụ thể.
Thuộc tính
Phản hồi về nội dung nghe nhìn có các yêu cầu và thuộc tính không bắt buộc sau đây có thể định cấu hình:
- Được hỗ trợ trên các nền tảng có
actions.capability.MEDIA_RESPONSE_AUDIO
chức năng. - Âm thanh để phát phải nằm trong tệp
.mp3
có định dạng chính xác. Trực tiếp không hỗ trợ phát trực tuyến. - Tệp nội dung nghe nhìn để phát phải được chỉ định dưới dạng URL HTTPS.
- Hình ảnh (không bắt buộc)
- Bạn có thể thêm biểu tượng hoặc hình ảnh (không bắt buộc).
- Biểu tượng
- Biểu tượng của bạn xuất hiện dưới dạng hình thu nhỏ không đường viền ở bên phải nội dung nghe nhìn thẻ người chơi.
- Kích thước phải là 36 x 36 dp. Hình ảnh có kích thước lớn hơn có thể đổi kích thước cho vừa.
- Hình ảnh
- Vùng chứa hình ảnh sẽ cao 192 dp.
- Hình ảnh của bạn xuất hiện ở đầu thẻ trình phát đa phương tiện và kéo dài toàn bộ chiều rộng của thẻ. Hầu hết hình ảnh sẽ xuất hiện với các thanh dọc trên cùng hoặc bên cạnh.
- Cho phép GIF chuyển động.
- Bạn phải chỉ định nguồn hình ảnh là URL.
- Bắt buộc phải có văn bản thay thế trên tất cả hình ảnh.
Hành vi trên các nền tảng
Phản hồi về nội dung nghe nhìn được hỗ trợ trên điện thoại Android và trên Google Home. Chiến lược phát hành đĩa đơn hành vi của phản hồi nội dung nghe nhìn phụ thuộc vào nền tảng mà người dùng tương tác bằng các Hành động của bạn.
Trên điện thoại Android, người dùng có thể thấy phản hồi của nội dung nghe nhìn khi bất kỳ điều kiện nào sau đây được đáp ứng:
- Trợ lý Google đang ở nền trước và màn hình điện thoại đang bật.
- Người dùng rời khỏi Trợ lý Google trong khi âm thanh đang phát rồi quay lại Trợ lý Google trong vòng 10 phút sau khi phát xong. Khi quay lại Trợ lý Google, người dùng sẽ thấy thẻ nội dung nghe nhìn và khối đề xuất.
- Trợ lý cho phép người dùng điều chỉnh âm lượng của thiết bị trong hành động trò chuyện bằng cách nói những câu như "tăng âm lượng" hoặc "đặt 50%". Nếu bạn có ý định xử lý các cụm từ huấn luyện tương tự, ý định của bạn sẽ được ưu tiên. Bạn nên để Trợ lý xử lý những việc này yêu cầu của người dùng trừ phi Hành động của bạn có lý do cụ thể.
Các nút điều khiển nội dung nghe nhìn có thể dùng được khi điện thoại đang khoá. Trên Android, các chế độ điều khiển cũng sẽ xuất hiện trong vùng thông báo.
Mã mẫu
Mã mẫu sau đây cho bạn biết cách bạn có thể cập nhật câu trả lời chi tiết cho bao gồm nội dung nghe nhìn.
Node.js
app.intent('Media Response', (conv) => { if (!conv.surface.capabilities .has('actions.capability.MEDIA_RESPONSE_AUDIO')) { conv.ask('Sorry, this device does not support audio playback.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('This is a media response example.'); conv.ask(new MediaObject({ name: 'Jazz in Paris', url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3', description: 'A funky Jazz tune', icon: new Image({ url: 'https://storage.googleapis.com/automotive-media/album_art.jpg', alt: 'Album cover of an ocean view', }), })); conv.ask(new Suggestions(['Basic Card', 'List', 'Carousel', 'Browsing Carousel'])); });
Java
@ForIntent("Media Response") public ActionResponse mediaResponse(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue())) { return responseBuilder .add("Sorry, this device does not support audio playback.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a media response example.") .add( new MediaResponse() .setMediaObjects( new ArrayList<MediaObject>( Arrays.asList( new MediaObject() .setName("Jazz in Paris") .setDescription("A funky Jazz tune") .setContentUrl( "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3") .setIcon( new Image() .setUrl( "https://storage.googleapis.com/automotive-media/album_art.jpg") .setAccessibilityText("Album cover of an ocean view"))))) .setMediaType("AUDIO")) .addSuggestions(new String[] {"Basic Card", "List", "Carousel", "Browsing Carousel"}); return responseBuilder.build(); }
Node.js
if (!conv.surface.capabilities .has('actions.capability.MEDIA_RESPONSE_AUDIO')) { conv.ask('Sorry, this device does not support audio playback.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('This is a media response example.'); conv.ask(new MediaObject({ name: 'Jazz in Paris', url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3', description: 'A funky Jazz tune', icon: new Image({ url: 'https://storage.googleapis.com/automotive-media/album_art.jpg', alt: 'Album cover of an ocean view', }), })); conv.ask(new Suggestions(['Basic Card', 'List', 'Carousel', 'Browsing Carousel']));
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue())) { return responseBuilder .add("Sorry, this device does not support audio playback.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a media response example.") .add( new MediaResponse() .setMediaObjects( new ArrayList<MediaObject>( Arrays.asList( new MediaObject() .setName("Jazz in Paris") .setDescription("A funky Jazz tune") .setContentUrl( "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3") .setIcon( new Image() .setUrl( "https://storage.googleapis.com/automotive-media/album_art.jpg") .setAccessibilityText("Album cover of an ocean view"))))) .setMediaType("AUDIO")) .addSuggestions(new String[] {"Basic Card", "List", "Carousel", "Browsing Carousel"}); return responseBuilder.build();
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "This is a media response example." } }, { "mediaResponse": { "mediaType": "AUDIO", "mediaObjects": [ { "contentUrl": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3", "description": "A funky Jazz tune", "icon": { "url": "https://storage.googleapis.com/automotive-media/album_art.jpg", "accessibilityText": "Album cover of an ocean view" }, "name": "Jazz in Paris" } ] } } ], "suggestions": [ { "title": "Basic Card" }, { "title": "List" }, { "title": "Carousel" }, { "title": "Browsing Carousel" } ] } } } }
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "This is a media response example." } }, { "mediaResponse": { "mediaType": "AUDIO", "mediaObjects": [ { "contentUrl": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3", "description": "A funky Jazz tune", "icon": { "url": "https://storage.googleapis.com/automotive-media/album_art.jpg", "accessibilityText": "Album cover of an ocean view" }, "name": "Jazz in Paris" } ] } } ], "suggestions": [ { "title": "Basic Card" }, { "title": "List" }, { "title": "Carousel" }, { "title": "Browsing Carousel" } ] } } } ] }
Hướng dẫn
Câu trả lời của bạn phải có mediaResponse
với mediaType
là AUDIO
và
chứa mediaObject
trong mảng mục của nội dung phản hồi chi tiết. Nội dung nghe nhìn
phản hồi hỗ trợ một đối tượng nội dung nghe nhìn duy nhất. Đối tượng đa phương tiện phải bao gồm nội dung
URL của tệp âm thanh. Đối tượng nội dung nghe nhìn có thể bao gồm tên hoặc văn bản phụ (không bắt buộc)
(mô tả) và biểu tượng hoặc URL hình ảnh.
Trên điện thoại và Google Home, khi Hành động của bạn phát xong âm thanh,
Trợ lý Google sẽ kiểm tra xem phản hồi của nội dung nghe nhìn có phải là FinalResponse
hay không.
Nếu không, lệnh này sẽ gửi một lệnh gọi lại đến phương thức thực hiện của bạn, cho phép bạn phản hồi
người dùng.
Hành động của bạn phải có khối đề xuất nếu
câu trả lời không phải là FinalResponse
.
Xử lý lệnh gọi lại sau khi phát xong
Hành động của bạn phải xử lý ý định actions.intent.MEDIA_STATUS
để nhắc
người dùng để theo dõi (ví dụ: phát bài hát khác). Hành động của bạn nhận được
lệnh gọi lại này sau khi phát xong nội dung nghe nhìn. Trong lệnh gọi lại, hàm
Đối số MEDIA_STATUS
chứa thông tin trạng thái về nội dung nghe nhìn hiện tại. Chiến lược phát hành đĩa đơn
giá trị trạng thái sẽ là FINISHED
hoặc STATUS_UNSPECIFIED
.
Sử dụng Dialogflow
Nếu muốn phân nhánh cuộc trò chuyện trong Dialogflow, bạn cần
thiết lập ngữ cảnh đầu vào của actions_capability_media_response_audio
trên
ý định đảm bảo chỉ kích hoạt trên các nền tảng hỗ trợ phản hồi cho nội dung nghe nhìn.
Xây dựng phương thức thực hiện đơn hàng
Đoạn mã dưới đây cho biết cách bạn có thể viết mã thực hiện cho
Hành động. Nếu bạn đang sử dụng Dialogflow, hãy thay thế actions.intent.MEDIA_STATUS
với tên hành động được chỉ định trong ý định nhận
sự kiện actions_intent_MEDIA_STATUS
(ví dụ: "media.status.update").
Node.js
app.intent('Media Status', (conv) => { const mediaStatus = conv.arguments.get('MEDIA_STATUS'); let response = 'Unknown media status received.'; if (mediaStatus && mediaStatus.status === 'FINISHED') { response = 'Hope you enjoyed the tune!'; } conv.ask(response); conv.ask('Which response would you like to see next?'); });
Java
@ForIntent("Media Status") public ActionResponse mediaStatus(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); String mediaStatus = request.getMediaStatus(); String response = "Unknown media status received."; if (mediaStatus != null && mediaStatus.equals("FINISHED")) { response = "Hope you enjoyed the tune!"; } responseBuilder.add(response); responseBuilder.add("Which response would you like to see next?"); return responseBuilder.build(); }
Node.js
app.intent('actions.intent.MEDIA_STATUS', (conv) => { const mediaStatus = conv.arguments.get('MEDIA_STATUS'); let response = 'Unknown media status received.'; if (mediaStatus && mediaStatus.status === 'FINISHED') { response = 'Hope you enjoyed the tune!'; } conv.ask(response); conv.ask('Which response would you like to see next?'); });
Java
@ForIntent("actions.intent.MEDIA_STATUS") public ActionResponse mediaStatus(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); String mediaStatus = request.getMediaStatus(); String response = "Unknown media status received."; if (mediaStatus != null && mediaStatus.equals("FINISHED")) { response = "Hope you enjoyed the tune!"; } responseBuilder.add(response); responseBuilder.add("Which response would you like to see next?"); return responseBuilder.build(); }
JSON
Xin lưu ý rằng tệp JSON bên dưới mô tả một yêu cầu webhook.
{ "responseId": "151b68df-98de-41fb-94b5-caeace90a7e9-21947381", "queryResult": { "queryText": "actions_intent_MEDIA_STATUS", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Media Status", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Media Status" ] } } ], "outputContexts": [ { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_account_linking" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_web_browser" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_screen_output" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_audio_output" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/google_assistant_input_type_voice" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_intent_media_status", "parameters": { "MEDIA_STATUS": { "@type": "type.googleapis.com/google.actions.v2.MediaStatus", "status": "FINISHED" } } } ], "intent": { "name": "projects/df-responses-kohler/agent/intents/068b27d3-c148-4044-bfab-dfa37eebd90d", "displayName": "Media Status" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-08-04T23:57:15Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.MEDIA_STATUS", "rawInputs": [ { "inputType": "VOICE" } ], "arguments": [ { "name": "MEDIA_STATUS", "extension": { "@type": "type.googleapis.com/google.actions.v2.MediaStatus", "status": "FINISHED" } } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "isInSandbox": true, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ], "requestType": "SIMULATOR" } }, "session": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA" }
JSON
Xin lưu ý rằng tệp JSON bên dưới mô tả một yêu cầu webhook.
{ "user": { "locale": "en-US", "lastSeen": "2019-08-06T07:38:40Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGcqunXh1M6IE0lu2sVqXdpJfdpC5FWMkMSXQskK1nzb4IkSUSRqQzoEr0Ly0z_G3mwyZlk5rFtd1w", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.MEDIA_STATUS", "rawInputs": [ { "inputType": "VOICE" } ], "arguments": [ { "name": "MEDIA_STATUS", "extension": { "@type": "type.googleapis.com/google.actions.v2.MediaStatus", "status": "FINISHED" } } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" } ] }, "isInSandbox": true, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ], "requestType": "SIMULATOR" }
Thẻ bảng
Thẻ bảng giúp bạn hiển thị dữ liệu dạng bảng trong câu trả lời của bạn (ví dụ: bảng xếp hạng thể thao, kết quả bầu cử và chuyến bay). Bạn có thể xác định các cột và hàng (tối đa 3 hàng) mà Trợ lý cần phải hiển thị trong thẻ bảng. Bạn cũng có thể xác định các cột và hàng bổ sung cùng với mức độ ưu tiên của chúng.
Bảng khác với danh sách dọc vì bảng hiển thị dữ liệu tĩnh và không tương tác được, như các phần tử danh sách.
Thuộc tính
Thẻ bảng có những yêu cầu và thuộc tính không bắt buộc mà bạn có thể định cấu hình:
- Được hỗ trợ trên các nền tảng có chức năng
actions.capability.SCREEN_OUTPUT
.
Phần sau đây tóm tắt cách bạn có thể tuỳ chỉnh các phần tử trong bảng .
Tên | Không bắt buộc | Có thể tuỳ chỉnh | Lưu ý về việc tuỳ chỉnh |
---|---|---|---|
title |
Có | Có | Tiêu đề chung của bảng. Bạn phải đặt tiêu đề phụ nếu đã đặt tiêu đề phụ. Bạn có thể tuỳ chỉnh bộ phông chữ và màu sắc. |
subtitle |
Có | Không | Tiêu đề phụ cho bảng. |
image |
Có | Có | Hình ảnh được liên kết với bảng. |
Row |
Không | Có |
Dữ liệu về hàng của bảng. Bao gồm một mảng 3 hàng đầu tiên được đảm bảo sẽ xuất hiện, nhưng các hàng khác có thể sẽ không xuất hiện xuất hiện trên một số bề mặt. Vui lòng kiểm tra với trình mô phỏng để xem những hàng nào được hiển thị cho một
nền tảng nhất định. Trên các nền tảng hỗ trợ |
ColumnProperties |
Có | Có | Tiêu đề và căn chỉnh cho một cột. Bao gồm một header
thuộc tính (đại diện cho văn bản tiêu đề của cột) và
Thuộc tính horizontal_alignment (loại
HorizontalAlignment ). |
Cell |
Không | Có | Mô tả một ô trong một hàng. Mỗi ô chứa một chuỗi đại diện cho một giá trị văn bản. Bạn có thể tuỳ chỉnh văn bản trong ô. |
Button |
Có | Có | Đối tượng nút thường xuất hiện ở cuối thẻ. Một bảng thẻ chỉ có thể có 1 nút. Bạn có thể tuỳ chỉnh màu của nút. |
HorizontalAlignment |
Có | Có | Căn chỉnh nội dung theo chiều ngang trong ô. Giá trị có thể là
LEADING , CENTER hoặc TRAILING . Nếu
chưa chỉ định, nội dung sẽ được căn chỉnh theo cạnh đầu của ô. |
Mã mẫu
Các đoạn mã sau đây cho biết cách triển khai một thẻ bảng đơn giản:
Node.js
app.intent('Simple Table Card', (conv) => { if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('This is a simple table example.'); conv.ask(new Table({ dividers: true, columns: ['header 1', 'header 2', 'header 3'], rows: [ ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'], ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'], ], })); conv.ask('Which response would you like to see next?'); });
Java
@ForIntent("Simple Table Card") public ActionResponse simpleTable(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a simple table example.") .add( new TableCard() .setColumnProperties( Arrays.asList( new TableCardColumnProperties().setHeader("header 1"), new TableCardColumnProperties().setHeader("header 2"), new TableCardColumnProperties().setHeader("header 3"))) .setRows( Arrays.asList( new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 1 item 1"), new TableCardCell().setText("row 1 item 2"), new TableCardCell().setText("row 1 item 3"))), new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 2 item 1"), new TableCardCell().setText("row 2 item 2"), new TableCardCell().setText("row 2 item 3")))))); return responseBuilder.build(); }
Node.js
if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('This is a simple table example.'); conv.ask(new Table({ dividers: true, columns: ['header 1', 'header 2', 'header 3'], rows: [ ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'], ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'], ], })); conv.ask('Which response would you like to see next?');
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a simple table example.") .add( new TableCard() .setColumnProperties( Arrays.asList( new TableCardColumnProperties().setHeader("header 1"), new TableCardColumnProperties().setHeader("header 2"), new TableCardColumnProperties().setHeader("header 3"))) .setRows( Arrays.asList( new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 1 item 1"), new TableCardCell().setText("row 1 item 2"), new TableCardCell().setText("row 1 item 3"))), new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 2 item 1"), new TableCardCell().setText("row 2 item 2"), new TableCardCell().setText("row 2 item 3")))))); return responseBuilder.build();
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "This is a simple table example." } }, { "tableCard": { "rows": [ { "cells": [ { "text": "row 1 item 1" }, { "text": "row 1 item 2" }, { "text": "row 1 item 3" } ], "dividerAfter": true }, { "cells": [ { "text": "row 2 item 1" }, { "text": "row 2 item 2" }, { "text": "row 2 item 3" } ], "dividerAfter": true } ], "columnProperties": [ { "header": "header 1" }, { "header": "header 2" }, { "header": "header 3" } ] } }, { "simpleResponse": { "textToSpeech": "Which response would you like to see next?" } } ] } } } }
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "This is a simple table example." } }, { "tableCard": { "columnProperties": [ { "header": "header 1" }, { "header": "header 2" }, { "header": "header 3" } ], "rows": [ { "cells": [ { "text": "row 1 item 1" }, { "text": "row 1 item 2" }, { "text": "row 1 item 3" } ], "dividerAfter": true }, { "cells": [ { "text": "row 2 item 1" }, { "text": "row 2 item 2" }, { "text": "row 2 item 3" } ], "dividerAfter": true } ] } }, { "simpleResponse": { "textToSpeech": "Which response would you like to see next?" } } ] } }, "possibleIntents": [ { "intent": "actions.intent.TEXT" } ] } ] }
Các đoạn mã sau đây cho biết cách triển khai một thẻ bảng phức tạp:
Node.js
app.intent('Advanced Table Card', (conv) => { if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('This is a table with all the possible fields.'); conv.ask(new Table({ title: 'Table Title', subtitle: 'Table Subtitle', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Alt Text', }), columns: [ { header: 'header 1', align: 'CENTER', }, { header: 'header 2', align: 'LEADING', }, { header: 'header 3', align: 'TRAILING', }, ], rows: [ { cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'], dividerAfter: false, }, { cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'], dividerAfter: true, }, { cells: ['row 3 item 1', 'row 3 item 2', 'row 3 item 3'], }, ], buttons: new Button({ title: 'Button Text', url: 'https://assistant.google.com', }), })); conv.ask('Which response would you like to see next?'); });
Java
@ForIntent("Advanced Table Card") public ActionResponse advancedTable(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a table with all the possible fields.") .add( new TableCard() .setTitle("Table Title") .setSubtitle("Table Subtitle") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Alt text")) .setButtons( Arrays.asList( new Button() .setTitle("Button Text") .setOpenUrlAction( new OpenUrlAction().setUrl("https://assistant.google.com")))) .setColumnProperties( Arrays.asList( new TableCardColumnProperties() .setHeader("header 1") .setHorizontalAlignment("CENTER"), new TableCardColumnProperties() .setHeader("header 2") .setHorizontalAlignment("LEADING"), new TableCardColumnProperties() .setHeader("header 3") .setHorizontalAlignment("TRAILING"))) .setRows( Arrays.asList( new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 1 item 1"), new TableCardCell().setText("row 1 item 2"), new TableCardCell().setText("row 1 item 3"))) .setDividerAfter(false), new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 2 item 1"), new TableCardCell().setText("row 2 item 2"), new TableCardCell().setText("row 2 item 3"))) .setDividerAfter(true), new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 2 item 1"), new TableCardCell().setText("row 2 item 2"), new TableCardCell().setText("row 2 item 3")))))); return responseBuilder.build(); }
Node.js
if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); conv.ask('Which response would you like to see next?'); return; } conv.ask('This is a table with all the possible fields.'); conv.ask(new Table({ title: 'Table Title', subtitle: 'Table Subtitle', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Alt Text', }), columns: [ { header: 'header 1', align: 'CENTER', }, { header: 'header 2', align: 'LEADING', }, { header: 'header 3', align: 'TRAILING', }, ], rows: [ { cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'], dividerAfter: false, }, { cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'], dividerAfter: true, }, { cells: ['row 3 item 1', 'row 3 item 2', 'row 3 item 3'], }, ], buttons: new Button({ title: 'Button Text', url: 'https://assistant.google.com', }), })); conv.ask('Which response would you like to see next?');
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a table with all the possible fields.") .add( new TableCard() .setTitle("Table Title") .setSubtitle("Table Subtitle") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Alt text")) .setButtons( Arrays.asList( new Button() .setTitle("Button Text") .setOpenUrlAction( new OpenUrlAction().setUrl("https://assistant.google.com")))) .setColumnProperties( Arrays.asList( new TableCardColumnProperties() .setHeader("header 1") .setHorizontalAlignment("CENTER"), new TableCardColumnProperties() .setHeader("header 2") .setHorizontalAlignment("LEADING"), new TableCardColumnProperties() .setHeader("header 3") .setHorizontalAlignment("TRAILING"))) .setRows( Arrays.asList( new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 1 item 1"), new TableCardCell().setText("row 1 item 2"), new TableCardCell().setText("row 1 item 3"))) .setDividerAfter(false), new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 2 item 1"), new TableCardCell().setText("row 2 item 2"), new TableCardCell().setText("row 2 item 3"))) .setDividerAfter(true), new TableCardRow() .setCells( Arrays.asList( new TableCardCell().setText("row 2 item 1"), new TableCardCell().setText("row 2 item 2"), new TableCardCell().setText("row 2 item 3")))))); return responseBuilder.build();
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "payload": { "google": { "expectUserResponse": true, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "This is a table with all the possible fields." } }, { "tableCard": { "title": "Table Title", "subtitle": "Table Subtitle", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Alt Text" }, "rows": [ { "cells": [ { "text": "row 1 item 1" }, { "text": "row 1 item 2" }, { "text": "row 1 item 3" } ], "dividerAfter": false }, { "cells": [ { "text": "row 2 item 1" }, { "text": "row 2 item 2" }, { "text": "row 2 item 3" } ], "dividerAfter": true }, { "cells": [ { "text": "row 3 item 1" }, { "text": "row 3 item 2" }, { "text": "row 3 item 3" } ] } ], "columnProperties": [ { "header": "header 1", "horizontalAlignment": "CENTER" }, { "header": "header 2", "horizontalAlignment": "LEADING" }, { "header": "header 3", "horizontalAlignment": "TRAILING" } ], "buttons": [ { "title": "Button Text", "openUrlAction": { "url": "https://assistant.google.com" } } ] } }, { "simpleResponse": { "textToSpeech": "Which response would you like to see next?" } } ] } } } }
JSON
Xin lưu ý rằng JSON bên dưới mô tả phản hồi webhook.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.TEXT" } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "This is a table with all the possible fields." } }, { "tableCard": { "title": "Table Title", "subtitle": "Table Subtitle", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Alt Text" }, "rows": [ { "cells": [ { "text": "row 1 item 1" }, { "text": "row 1 item 2" }, { "text": "row 1 item 3" } ], "dividerAfter": false }, { "cells": [ { "text": "row 2 item 1" }, { "text": "row 2 item 2" }, { "text": "row 2 item 3" } ], "dividerAfter": true }, { "cells": [ { "text": "row 3 item 1" }, { "text": "row 3 item 2" }, { "text": "row 3 item 3" } ] } ], "columnProperties": [ { "header": "header 1", "horizontalAlignment": "CENTER" }, { "header": "header 2", "horizontalAlignment": "LEADING" }, { "header": "header 3", "horizontalAlignment": "TRAILING" } ], "buttons": [ { "title": "Button Text", "openUrlAction": { "url": "https://assistant.google.com" } } ] } }, { "simpleResponse": { "textToSpeech": "Which response would you like to see next?" } } ] } } } ] }
Tuỳ chỉnh câu trả lời của bạn
Bạn có thể thay đổi giao diện của các câu trả lời chi tiết bằng cách tạo một giao diện tuỳ chỉnh. Nếu bạn xác định một giao diện cho dự án Actions (Hành động), các phản hồi đa dạng thức trên Hành động trong dự án sẽ được tạo kiểu theo chủ đề của bạn. Nhãn hiệu tuỳ chỉnh này có thể hữu ích trong việc xác định một giao diện độc đáo cho cuộc trò chuyện khi người dùng gọi Hành động của bạn trên một nền tảng bằng màn hình.
Để đặt giao diện phản hồi tuỳ chỉnh, hãy làm như sau:
- Trong Bảng điều khiển Actions, hãy chuyển đến phần Phát triển > Tuỳ chỉnh giao diện.
- Đặt bất kỳ hoặc tất cả các tuỳ chọn sau:
- Màu nền để dùng làm nền cho thẻ. Trong thông thường, bạn nên sử dụng màu sáng cho nền để thẻ dễ đọc.
- Màu chính là màu chính cho thẻ của bạn văn bản tiêu đề và giao diện người dùng phần tử. Nhìn chung, bạn nên dùng màu chính tối hơn để tương phản có nền.
- Bộ phông chữ mô tả loại phông chữ dùng cho tiêu đề và các thành phần văn bản nổi bật.
- Kiểu góc ảnh có thể thay đổi giao diện thẻ của bạn các góc.
- Hình nền sử dụng một hình ảnh tùy chỉnh thay cho nền . Bạn cần cung cấp hai hình ảnh khác nhau để thiết bị bề mặt ở chế độ ngang hoặc dọc. Lưu ý rằng nếu bạn dùng hình nền, màu chính sẽ được đặt thành trắng.
- Nhấp vào Lưu.