使用 Actions Builder 构建适用于 Google 助理的 Action(第 2 级)

Google 助理是一款虚拟智能个人助理,借助 Google 助理开发者平台,您可以打造软件,从而为超过 10 亿台设备(包括智能音箱、手机、汽车、电视、头戴式耳机等)扩展 Google 助理的功能。用户可通过对话与 Google 助理互动,以这种方式处理各种事务,例如购买日用品或约车。作为开发者,您可以使用 Google 助理开发者平台在用户和您自己的第三方履约服务之间轻松打造并管理愉悦、高效的对话体验。

本 Codelab 介绍了 Google 助理相关开发的中级概念,并以第 1 级 Codelab 中创建的 Action 为基础进一步构建。我们强烈建议您先完成第 1 级 Codelab,然后再开始学习本 Codelab。

您在本 Codelab 中构建的 Action 可根据用户选择的辅助物,告知用户他们探索神秘大陆 Gryffinberg 期间的运势。

构建内容

在本 Codelab 中,您要构建一个具有以下功能的复杂对话型 Action:

  • 收集用户数据,并根据收集到的值修改对话提示
  • 通过提出后续问题进行回应,持续推进对话
  • 创建游戏循环,以便用户能够在收到运势信息后再次与相应 Action 互动

开始构建之前,您可以在内置 Google 助理的设备上与实际 Action 进行互动,只需说出“Ok Google,跟 Fate and Fortune 聊聊”即可。回访用户与该 Action 互动的默认路径如下所示:

dd6f5c61296b8b50.png

eba043f546aa8c51.png

学习内容

  • 如何使用向用户收集数据
  • 如何使用条件向场景添加逻辑
  • 如何添加游戏循环
  • 如何添加辅助路径

所需条件

学习本 Codelab 前,您需要做好以下准备:

  • 网络浏览器,例如 Chrome
  • 已完成的 Codelab 第 1 级 Actions 项目

我们强烈建议(但不强制要求)您熟悉 JavaScript (ES6),以便理解本 Codelab 的执行方式代码。

第一个 Codelab 中,您创建了一个具有单一场景的简单对话型 Action Start

在本 Codelab 中,您可以扩展该 Action 的对话。在以下部分中,您可以配置该 Action 以执行以下操作:

  • 在用户想要听取自己的运势时,过渡到新的 Fortune 场景
  • 询问用户想要为自己的旅程选择哪种辅助物
  • 根据用户所做的选择提供自定义运势

创建 Fortune 场景

在本部分中,您可以创建 Fortune 场景并定义用户在对话期间如何过渡到该场景。

如需创建名为 Fortune 的新场景,请按以下步骤操作:

  1. 打开 Codelab 第 1 级 Actions 项目。
  2. 点击导航栏中的 Develop 按钮。
  3. Scenes 下,点击 Start 场景。
  4. 点击 yes intent(When yes is matched 复选框)以打开相关选项。
  5. 取消选中 Send prompts 以移除相关提示。
  6. Transition 部分中,点击下拉菜单,点击进入文本框,然后输入 Fortune
  7. 点击 Add。这会创建一个名为 Fortune 的新场景。在用户想要听取运势信息时,它还会添加从 Start 场景向 Fortune 场景的过渡。

56682a0c7459b98c.png

Fortune 场景定义对话逻辑

在本 Codelab 中,您将配置 Fortune 场景,以便向用户提出以下问题:“What do you choose to help you on your quest, a dragon, a translator, or a compass?”(你选择哪一样辅助物来帮助你完成探索之旅,巨龙、翻译还是罗盘?)您可以使用一项名为槽填充的功能向用户收集必要的信息,然后再继续操作。

您的 Action 可针对 3 种辅助物提供对应的运势信息:dragon(巨龙)、translator(翻译)和 compass(罗盘)。若要配置您的 Action 以识别用户输入中的这 3 个选项,您必须创建一个新的“类型”。

您可以在场景的槽填充阶段使用类型来定义您想要从用户那里获取的信息。当 NLU 引擎在用户输入中检测到槽匹配时,它会将相应槽提取为已分类参数,让您能够在场景中使用该参数执行逻辑。

创建 available_options 类型

在本部分中,您将创建一个名为 available_options 的新类型,该类型可以指定用户在对提示做出回应时可以选择的 3 个选项(dragon、translator 和 compass)。您还可以为这些选项定义几个同义词,以便在用户说出类似内容时也能识别。在后续部分中,您要将 available_options 类型添加到某个槽中,以便指明您想要获取用户的选择。

如需创建 available_options 类型,请按以下步骤操作:

  1. 在导航栏中,点击 Types
  2. 点击 +(加号),输入 available_options,然后按 Enter
  3. 点击 available_options 以打开相关选项。

类型将被配置为信息键值对,其中“键”为类型的名称,而“值”为相应键的同义词。定义键后,系统会自动为该键添加值。

如需添加用户可选择的 3 个选项,请按以下步骤操作:

  1. 向下滚动到 Add entries 部分。
  2. New entry 字段中,输入 dragon 并按 Enter。该操作会创建一个 dragon 键。
  3. Add values 字段中输入 hydra,然后按 Enter 将其添加为值(同义词)。然后,针对值 lizard 重复该步骤。
  4. 添加其余的键和相应的值:
  • translator | translator, communicator, machine, decoder, translate
  • compass | compass, direction, guide

8333b1b67445f21.png

  1. 点击 Save

现在,您的 Action 不仅可以理解 available_options 是 dragon、translator 和 compass,还能识别出各选项对应的一些同义词。

配置槽填充

接下来,您需要配置 Fortune 场景中的槽填充。如需配置槽填充逻辑,请按以下步骤操作:

  1. 在导航栏的 Scenes 下,点击 Fortune
  2. Fortune 场景中,点击 Slot filling 对应的 +(加号)
  3. Enter slot name 字段中,添加 chosenOptions 作为槽名称。
  4. Select type 下拉菜单中,选择 available_options 作为槽类型。
  5. 选中 This slot is required

a461b906476e244.png

  1. 选中 Send prompts,然后添加以下消息和建议内容信息卡:
 candidates:
  - first_simple:
      variants:
        - speech: >-
            What do you choose to help you on your quest, a dragon, a
            translator, or a compass?
    suggestions:
      - title: 'Dragon'
      - title: 'Translator'
      - title: 'Compass'
  1. 点击 Save

现在,您已将 available_options 类型添加到相应的槽,这样可以告知 Action 您需要先向用户收集哪些信息(用户选择哪个辅助物),然后再继续操作。此外,您还在该槽中配置了提示;在用户到达场景的槽填充阶段后,系统会将该提示添加到提示队列。

请注意,将槽命名为 chosenOptions 后,Customize slot value writeback 字段会更新为相同的名称 ($session.params.chosenOptions)。您可以在 Actions Builder 中使用该名称访问此参数,也可以通过客户端库在执行方式中使用该名称访问此参数。

配置 scene.slots.status == "FINAL" 条件

添加槽后,系统会自动将条件 scene.slots.status == "FINAL" 添加到条件列表。

条件 scene.slots.status == "FINAL" 会检查槽填充是否已完成。在所有槽填充完毕后,此条件可以触发网络钩子、过渡到新场景或向提示队列添加提示。

在本部分中,您将配置 scene.slots.status == "FINAL",以便在槽填充完毕后向提示队列添加提示。

如需将该提示添加到 FINAL 条件,请按以下步骤操作:

  1. 点击 scene.slots.status == "FINAL" 条件以打开选项窗口。
  2. 选中 Send prompts 并添加以下提示:
candidates:
  - first_simple:
      variants:
        - speech: You picked $session.params.chosenOptions.
  1. 点击 Save

在模拟器中测试您的 Action

此时,您已定义用户应该选择哪些选项以填充槽。向用户获取这些信息后,您的 Action 应该会提供提及用户所选的特定选项的提示。

如需测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. Input 字段中点击或输入 Talk to my test app,然后按 Enter
  3. Input 字段中输入 Yes,然后按 Enter。(或者,您也可以点击 Yes 建议内容信息卡。)

a899d45c542668f6.png

  1. 点击、输入或说出 dragon。您应该会收到内容为“You have pick dragon”(您已选择巨龙)的提示。

在下一部分中,您可以自定义用户可选的每个辅助物对应的提示。

使用条件自定义提示

在本部分中,您将为用户可以选择的每个选项添加条件,然后为每个条件添加一条自定义提示。

自定义 dragon 选项对应的运势

如需针对用户选择“dragon”的情况更新条件并自定义提示,请按以下步骤操作:

  1. 点击导航栏中的 Develop 按钮。
  2. 点击导航栏中的 Fortune 场景。
  3. 点击 scene.slots.status == "FINAL" 条件以打开选项窗口。
  4. 将条件语句更新为:scene.slots.status == "FINAL" && session.params.chosenOptions == "dragon"
  5. 选中 Send prompts
  6. 在代码编辑器中,使用以下运势信息来更新提示:
 candidates:
  - first_simple:
      variants:
        - speech: >-
            The people of Gryffinberg will be awestruck by the beauty and power
            of the ancient dragon. Much to your dismay, the townspeople fall
            into dispute over who will receive the honor of riding the dragon
            first. You return home from your quest without everlasting glory or
            a dragon.
  1. 点击 Save

d31767232ad908bd.png

现在,当用户说出“dragon”或其同义词时,您的 Action 会根据该选项提供对应的运势信息。接下来,您可以为剩余的两个选项添加运势。

自定义 translator 选项对应的运势

如需针对用户选择“translator”的情况更新条件并自定义提示,请按以下步骤操作:

  1. 点击 Condition 旁边的 +(加号)
  2. scene.slots.status == "FINAL" && session.params.chosenOptions == "translator" 添加到 else if 字段。
  3. 选中 Send prompts
  4. 在代码编辑器中添加以下提示:
candidates:
  - first_simple:
      variants:
        - speech: >-
            With the help of the translator, the rival factions in Gryffinberg
            are finally able to communicate with each other and resolve their
            disputes. You will complete your quest to restore peace in the town.
            The translator will be used on many subsequent journeys across the
            earth. After its work is done, it retires honorably to a premier
            location in the Gryffinberg History Museum.
  1. 点击 Save

c1af65e70dbf3dfe.png

自定义 compass 选项对应的运势

如需针对用户选择“compass”的情况更新条件并自定义提示,请按以下步骤操作:

  1. 点击 Condition 旁边的 +(加号)
  2. scene.slots.status == "FINAL" && session.params.chosenOptions == "compass" 添加到 else if 文本框。
  3. 选中 Send prompts
  4. 在代码编辑器中添加以下提示:
 candidates:
  - first_simple:
      variants:
        - speech: >-
            The compass will help you find the mystical and ancient Library of
            Gryffinberg. Among its infinite stacks of dusty books, you find one
            entitled "Wisdom of the Ages". By the time you've read the
            50,000-page tome, the townspeople have forgotten their problems. You
            will write a second edition of "Wisdom of the Ages", but have
            limited commercial success.
  1. 点击 Save

在模拟器中测试您的 Action

此时,您的 Action 应该会根据用户选择的选项为用户提供自定义的运势信息。

如需测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. Input 字段中输入 Talk to my test app,然后按 Enter
  3. Input 字段中输入“Yes”,然后按 Enter**。**或者,点击“Yes”建议内容信息卡。
  4. 点击、输入或说出 Translator

29e17f950bd0dd71.png

您应该会收到“translator”选项对应的运势信息。

在本部分中,您将配置 Action,以便用户在选择某选项后,能够改选其他选项并听取对应的运势信息。这项更改与游戏结束时显示的“Do you want to play again?”(要再玩一次吗?)消息类似。如需构建此循环,您可以重复使用之前创建的 yesno intent,然后将其添加到名为 Again 的新场景。

创建 Again 场景

在本部分中,您将创建一个新的 Again 场景,然后添加提示,以询问用户是否要选择其他选项。

如需创建 Again 场景,请按以下步骤操作:

  1. 点击导航栏中的 Develop 按钮。
  2. 点击 Scenes 下的 +(加号)
  3. 输入 Again,然后按 Enter
  4. 点击导航栏中的 Again 场景。
  5. 点击 On enter 旁边的 +(加号)
  6. 选中 Send prompts,然后添加以下提示和建议内容信息卡:
candidates:
  - first_simple:
      variants:
        - speech: >-
            That is what I see for you. Would you like to choose a different option and
            explore another future?
    suggestions:
      - title: 'Yes'
      - title: 'No'
  1. 点击 Save

添加从 FortuneAgain 场景的过渡

在用户收到运势信息后,对话需要过渡到新的 Again 场景。

如需添加从 Fortune 场景到 Again 场景的过渡,请按以下步骤操作:

  1. 点击 Fortune 场景。
  2. 点击第一个条件 (scene.slots.status == "FINAL" && session.params.chosenOptions == "dragon") 以打开选项窗口。
  3. 滚动并选择 Transition 下方的 Again
  4. 点击 Save
  5. 点击第二个条件以打开选项窗口。
  6. 滚动并选择 Transition 下方的 Again
  7. 点击 Save
  8. 点击第三个条件以打开选项窗口。
  9. 滚动并选择 Transition 下方的 Again
  10. 点击 Save

在模拟器中测试您的 Action

此时,在用户收到运势信息后,您的 Action 应该为用户提供以下提示:“That is what I see for you. Would you like to choose a different option and explore another future?”(我预见到你的运势就是这样。是否要选择其他选项,探索未来的另一种走向?)

如需测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. Input 字段中输入 Talk to my test app,然后按 Enter
  3. Input 字段中输入 Yes,然后按 Enter。或者,点击 Yes 建议内容信息块。
  4. 点击、输入或说出 dragon

b299e9fed9aedb69.png您应该会收到 dragon 选项对应的运势信息和 Again 提示。

添加 intent 以及向 Again 场景的过渡

在本部分中,您将向 Again 场景添加 yesno intent,以便您的 Action 能够理解用户是否想要选择新选项。此外,您还可以针对 yesno intent 添加适当的过渡。yes intent 会过渡到 Fortune 场景,而 no intent 会过渡到系统场景 End conversation

如需向 Again 场景添加 intent 和过渡,请按以下步骤操作:

  1. 点击导航栏中的 Develop 按钮。
  2. 点击 Again 场景。
  3. 点击 User intent handling 旁边的 +(加号)
  4. 从 intent 下拉菜单中选择 yes
  5. Transition 下拉菜单中选择 Fortune
  6. 点击 Save

c2efba35ea881b0d.png

  1. 点击 User intent handling 旁边的 +(加号)
  2. 从 intent 下拉菜单中选择 no
  3. Transition 下拉菜单中选择 End conversation
  4. 选中 Send prompts,然后在代码编辑器中添加以下提示:
candidates:
  - first_simple:
      variants:
        - speech: >-
            It pleases me that you are satisfied with your choice. Best of luck on your quest. Farewell.
  1. 点击 Save

在模拟器中测试您的 Action

现在,您的 Action 应该能够理解用户是要选择新选项,还是要结束对话。

如需测试 yes intent,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. Input 字段中输入 Talk to my test app,然后按 Enter
  3. Input 字段中输入 Yes,然后按 Enter。或者,点击 Yes 建议内容信息块。
  4. 点击、输入或说出其中一个选项。
  5. 在输入字段中输入 Yes,然后按 Enter

5d0690332efe2e29.png

您应该会收到以下提示:“What do you choose to help you on your quest, a dragon, a translator, or a compass?”

如需测试 no intent,请按以下步骤操作:

  1. 点击、输入或说出其中一个选项。
  2. 在输入字段中输入 No,然后按 Enter

您应该会收到 End conversation 提示:“It pleases me that you are satisfied with your choice. Best of luck on your quest. Farewell.“(看来你对自己的选择很满意,我很欣慰。祝你顺利完成探索之旅。后会有期。)

现在,您已经构建了大多数用户在您的 Action 中选择的主要路径。不过,对于 Fortune 场景中的提示“What do you choose to help you on your quest, a dragon, a translator, or a compass?”,用户在回应时可能会选择所提供选项之外的其他内容。

在本部分中,您将配置 Action,使其能够在用户选择“magic”(魔法)、“money”(钱)、“horse”(马)或“phone”(手机)时理解用户意图,并在用户选择这些物件中的某一项时重新提示用户从原有的 3 个选项中选择一项。如需配置此逻辑,您需要创建一个新的 type(其中包含范围外的其他选项),以及一个新的 intent other_option(当用户说出范围外的某一选项时,便会与该 intent 匹配)。此外,您还需要为 other_option intent 中的训练短语添加注解,以便识别并提取 intent 参数。

Google 助理的自然语言处理引擎在用户输入中检测到参数匹配后,会将相应值提取为已分类参数,让您能够在场景中使用该参数执行逻辑。在本 Codelab 中,您将配置 Action,以便提取用户选择的辅助物,并在提示中提及相应选择。

创建 unavailable_options 类型

现在,您可以创建包含各种其他选项的 unavailable_options 类型,以便您的 Action 可以识别用户输入中的此类数据。

如需创建 unavailable_options 类型,请按以下步骤操作:

  1. 点击导航栏中的 Develop 按钮。
  2. 点击 Types 下的 +(加号)
  3. 输入 unavailable_options,然后按 Enter
  4. 点击 unavailable_options 以打开相关选项。
  5. Add entries 部分中输入以下条目和相应的值:

horse

horse, stallion, steed

magic

magic, enchanted, spells

money

money, cash, gold

phone

phone, cell, apps

键值对表格应该大致如下所示:

c9e119e0f5fb2a47.png

  1. 点击 Save

创建 other_option intent

接下来,您要创建一个名为 other_option 的 intent,并添加带有 unavailable_options 类型包含的选项的训练短语。如果用户选择 unavailable_options 类型中包含的选项,便会与该 intent 匹配。

如需创建和配置 other_option intent,请按以下步骤操作:

  1. 点击 Intents 下的 +(加号)
  2. 输入 other_option,然后按 Enter
  3. 点击 other_option 以打开相关窗口。
  4. 添加以下训练短语,然后按每个短语后面的 Enter
  • I want to use spells
  • I really really want to use a phone
  • magic!
  • cash
  • I want to ride a horse
  1. Add intent parameters 部分中,将参数名称更新为 chosenUnavailableOption
  2. 点击 Save

在您输入短语时,Actions Builder 会识别 unavailable_options 类型中的 spellsphonemagiccashhorse,并自动突出显示这些字词(为其添加注解)。Actions Builder 会自动在 Add intent parameters 部分中添加 intent 参数,如下图所示。

借助 intent 参数,您可以提取选项的名称,并在提示中使用相应选项。

df61d4489f0910.png

Fortune 场景添加 other_option intent

您现在已经有了一个 intent (other_option),它可以处理用户指定原有选项范围外的其他选项的情况。在本部分中,您将向 Fortune 场景添加 other_option intent。您可以使用该 intent 参数,根据用户输入自定义提示。

如需将 other_option intent 添加到 Fortune 场景,请按以下步骤操作:

  1. 点击 Fortune 场景。
  2. 点击 User intent handling 旁边的 +(加号)
  3. 从 intent 下拉菜单中选择 other_option
  4. 选中 Send prompts 并添加以下提示:
candidates:
  - first_simple:
      variants:
        - speech: >-
            I have seen the future and a $intent.params.chosenUnavailableOption.original
            will not aid you on your journey.

表达式 $intent.params.chosenUnavailableOption 可引用 intent 参数对象,而 $intent.params.chosenUnavailableOption.original 可引用该对象的值。original 属性可引用用户指定的原始输入。

  1. 点击 Save

4bab1efbe21056aa.png

如果用户在 Fortune 场景中说出 unavailable_options 类型中列出的某个选项,则会与 other_option intent 匹配,并向提示队列添加提示。由于未指定过渡,因此场景执行循环会通过重新评估条件阶段继续运行。然后,chosenOptions 槽会将其提示添加到提示队列,接着,系统会将提示队列分发到用户。

在模拟器中测试您的 Action

现在,用户选择 unavailable_options 类型中列出的某个选项后,您的 Action 应该会作出适当回应,并明确说出用户所选的辅助物。然后,您的 Action 应该重新提示用户选择原有选项之一(dragon、translator 或 compass)。

如需在模拟器中测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. Input 字段中输入 Talk to my test app,然后按 Enter
  3. Input 字段中输入 Yes,然后按 Enter。或者,点击 Yes 建议内容信息块。
  4. Input 字段中输入 magic,然后按 Enter

3a42c33eca435f32.png

您可能会发现,如果用户选择“magic”,由于在该字词前面放置了冠词“a”,因此提示听起来有错误。您将在后面的部分中解决该问题。

添加 unavailable_options 处理脚本

如需在 unavailable_options 类型中的适当选项前面加上冠词“a”,您可以在执行方式逻辑中配置事件处理脚本,以便检查用户选择的选项前面是否需要冠词“a”。首先,您需要将 Action 配置为在控制台中调用该处理脚本。

如需添加 unavailable_options 处理脚本,请按以下步骤操作:

  1. 点击导航栏中的 Develop 按钮。
  2. 点击 Fortune 场景。
  3. User intent handling 下方,点击 When other_option is matched 以打开相关窗口。
  4. 取消选中 Send prompts
  5. 选中 Call your webhook
  6. 在事件处理脚本的文本框中输入 unavailable_options

52a0fba115f1b377.png

  1. 点击 Save

更新和部署执行方式

现在,您已将 Action 配置为调用 unavailable_options 事件处理脚本,接下来,您可以在您的执行方式中更新该处理脚本并进行部署。

如需更新您的执行方式,请按以下步骤操作:

  1. 点击导航栏中的 Webhook
  2. greeting 处理脚本下方添加以下代码:
app.handle('unavailable_options', conv => {
  const option = conv.intent.params.chosenUnavailableOption.original;
  const optionKey = conv.intent.params.chosenUnavailableOption.resolved;
  let message = 'I have seen the future and ';
  if(optionsNeedA.has(optionKey)){
    message = message + 'a ';
  }
  message = message + `${option} will not aid you on your journey. `;
  conv.add(message);
});
  1. const app = conversation(); 下方添加以下代码:
const optionsNeedA = new Set();
optionsNeedA.add('horse').add('phone');
  1. 点击 Save Fulfillment
  2. 点击 Deploy Fulfillment。部署完成后,编辑器上方会显示以下消息:Your Cloud Function deployment is up to date.(您的 Cloud Functions 函数部署已是最新版本。)

了解代码

unavailable_options 处理脚本会执行以下操作:

  • conv 对象获取 option 数据,并将 option 分配给 original 属性(用户的原始输入)
  • optionKey 分配给 resolved 属性(前者为 unavailable_options 类型的键)
  • 检查 optionKey 是否为需要“a”的选项之一;如果是,则在构建消息时加上“a”
  • 通过 conv.add(message) 添加消息

在模拟器中测试您的 Action

现在,您的 Action 应该会根据用户在 unavailable_options 类型中选择的选项前面是否需要冠词“a”来调整提示。

如需测试您的 Action,请按以下步骤操作:

  1. 在导航栏中,点击 Test
  2. Input 字段中点击或输入 Talk to my test app,然后按 Enter
  3. Input 字段中输入 Yes,然后按 Enter。或者,点击 Yes 建议内容信息块。
  4. Input 字段中输入 magic,然后按 Enter
  5. Input 字段中输入 horse,然后按 Enter

54ee24c5c3c56e.png

您的 Action 应该会在“horse”选项前面添加冠词“a”,而在针对“magic”选项构建提示时则不会添加冠词“a”。

恭喜您!

现在,您已经掌握了构建适用于 Google 助理的 Action 所需的中级技能。

所学内容

  • 如何使用 Node.js 执行方式库开发对话型 Action
  • 如何使用槽向用户收集数据
  • 如何使用条件向场景添加逻辑
  • 如何添加游戏循环
  • 如何添加辅助路径

其他学习资源

您可以探索以下资源,了解如何构建适用于 Google 助理的 Action:

清理项目 [推荐]

为避免可能产生的费用,建议您移除不想使用的项目。如需删除您在本 Codelab 中创建的项目,请按以下步骤操作:

  1. 如需删除 Cloud 项目和资源,请完成关停(删除)项目部分中所列的步骤。
  1. 可选:如需立即从 Actions 控制台移除您的项目,请完成删除项目部分中所列的步骤。如果您未完成该步骤,系统会在大约 30 天后自动移除您的项目。

欢迎关注我们的 Twitter 帐号 @ActionsOnGoogle,及时了解我们的最新公告,还可以使用标签 #AoGDevs 发布 Twitter 微博,分享您构建的成果!

反馈意见调查

在您离开本页面前,请填写简短的调查问卷,与我们分享您的体验。