利用生成式回退来扩大 intent 覆盖范围并妥善处理错误

1. 概览

上次更新时间:2023 年 8 月 7 日

构建内容

在此 Codelab 中,您将使用 Dialogflow CX 构建、部署和配置一个简单的虚拟客服,以帮助潜水员进行团体预订和私人包机。虚拟客服将使用生成式 AI 和 Google 最新的生成式大语言模型 (LLM) 来生成虚拟客服回答。

学习内容

  • 如何启用相关 API
  • Dialogflow 如何自动预填充页面表单参数值(来自意图参数)
  • 如何在 Dialogflow 中配置事件处理程序
  • 如何在流和参数填充期间使用的无匹配事件处理程序中启用生成式后备
  • 如何配置自己的文本提示,以处理基本对话情况以及与代理相关的对话情况
  • 如何编写良好的意图和参数说明,以生成必需参数的重新提示处理程序(除了用户定义的重新提示之外)
  • 如何测试代理并模拟会触发生成式后备的客户问题

所需条件

  • Google Cloud 项目
  • 浏览器,例如 Chrome

2. 准备工作

您需要先启用 Dialogflow API,然后才能开始在 Dialogflow CX 中使用生成式后备功能。

使用 Cloud 控制台启用 Dialogflow API

  1. 在浏览器中打开 Google Cloud 控制台
  2. 在 Google Cloud 控制台中,前往 API 库,浏览可启用的 API 和服务。
  3. 使用“API 库”页面顶部的搜索栏搜索 Dialogflow API,然后点击搜索结果中的相应服务。
  4. 点击启用按钮,以在您的 Google Cloud 云项目 中启用 Dialogflow API。

使用 gcloud CLI(替代方法)

或者,您也可以使用以下 gcloud 命令启用该 API:

gcloud services enable dialogflow.googleapis.com

如果 API 已成功启用,您应该会看到类似如下的消息:

Operation "operations/..." finished successfully.

获取代码

您无需从头开始创建虚拟客服,我们会为您提供一个代理,您需要从 Dialogflow CX 控制台恢复该代理,然后对其进行改进。

如需下载源代码,请执行以下操作:

  1. 打开新的浏览器标签页,前往代理代码库,然后通过命令行克隆该代码库。
  2. 初始代理已导出为 JSON 软件包。解压缩文件,检查代理设置,查看流程定义 Liveaboards.json,最后浏览流程页面、意图和实体。

3. 创建新代理

打开 Dialogflow 控制台

您将使用 Dialogflow CX 控制台和您的 Google Cloud 云项目来完成本 Codelab 中的剩余步骤。

  1. 在浏览器中,前往 Dialogflow CX 控制台
  2. 选择要使用的 Google Cloud 项目,或创建要使用的新项目。
  3. 您应该会在 Dialogflow CX 控制台中看到代理列表。

如果您是首次使用 Dialogflow CX,请参阅 Dialogflow CX 文档,详细了解如何根据您的需求配置项目和设置。

创建新的 Dialogflow CX 代理

  1. 如需恢复从 GitHub 代码库下载的代理,您需要创建新代理。在 Dialogflow CX 控制台中,点击页面右上角的创建新代理

创建全新代理

  1. 选择自行构建代理的选项。

选择相应选项

  1. 填写包含以下代理设置的表单,然后点击创建以创建代理。
  • 选择以下显示名称:Divebooker
  • 选择以下位置:us-central1
  • 选择您要使用的时区
  • 选择 en - English 作为默认语言
  1. Dialogflow 会自动为您打开代理。我们并不会就此止步!

恢复 Divebooker 代理

  1. 返回到代理列表页面,找到您刚刚创建的代理。点击选项 78d2781c655810e7.png,然后点击恢复按钮。
  2. 选择上传选项,然后放置或选择您之前从 GitHub 代码库下载的 ZIP 文件。
  3. 点击恢复按钮以导入我们提供的代理

点击“恢复”按钮以导入我们提供的代理

太棒了!您已完成潜水预订虚拟客服的构建,该虚拟客服可以帮助您的客户。在下一部分中,您将对其进行测试,看看它在回答用户问题和协助处理预订请求方面的表现如何。

4. 测试代理

Dialogflow 提供了一个内置模拟器,可用于与代理聊天并发现 bug。对于每个回合,您可以验证触发的意图、代理响应、有效页面和会话参数的正确值。

我们将测试几种场景,并针对每种场景分析代理给出特定回答的原因。我们先从第一个开始。

未解决的 intent

  1. 在 Dialogflow 控制台中,从代理内部点击测试代理以打开模拟器。

点击“测试代理”以打开模拟器

  1. 向智能体发送问候语(例如 Hello),然后提出问题 what is a liveaboard?。问题与任何意图都不匹配,系统会显示“抱歉,我不确定怎么回答”等通用提示。您可以在模拟器中检查原始响应,以确认是否调用了 sys.no-match-default 内置事件

向智能体问好,并询问什么是船宿

向下滚动到 JSON 响应的末尾附近。请注意,在搜索匹配的意图时,Dialogflow 发现这是一个 NO_MATCH,并引发了无匹配事件。

检查 Dialogflow 是否引发了 sys.no-match-default 事件

  1. 切换到构建标签页,然后打开 Liveaboards 流程的起始页

切换到“Build”(构建)标签页,然后打开“Liveaboards”(船宿)流程的“Start Page”(起始页)。

默认情况下,每个流都有针对无匹配和无输入内置事件的事件处理脚本。这些事件处理脚本会在您创建流时自动创建,并且不能删除。

  1. 点击 sys.no-match-default 事件处理脚本,然后向下滚动到代理回答部分。Dialogflow 提供了一份替代回答列表,但您也可以定义不同类型的回答消息,以便为最终用户提供比文本回答更丰富的内容。

查看预定义的客服人员回答

现在,我们来了解正常情况下的流程!

理想路径

在第二种情况下,假设您是一名潜水员,想为 12 人团体预订明年 7 月前往加拉帕戈斯群岛的潜水游轮。

  1. 在模拟器面板中,点击重置图标,开始与代理进行新的对话。

重置以发起新对话

考虑切换到竖向画面,以获得更好的用户体验

  1. 告知代理商您想预订前往加拉帕戈斯群岛的包机,并提供您的旅行详细信息。您无需使用以下完全相同的提示,不妨尝试一下!

测试正常路径

  1. 打开起始页,然后点击 head.send.group.request 路由。向下滚动到转换部分,该部分用于告知 Dialogflow 在匹配到相应意图时要转换到的页面。

转换到“收集更多信息”页面

  1. 关闭路线定义,然后展开收集更多信息页面。请注意条目完成情况和参数列表。

“收集更多信息”页面

在 Dialogflow CX 中,您可以为每个页面定义一个表单,该表单上列出应从该页面的最终用户处收集的参数。请注意,由于我们将旅游目的地作为初始输入的一部分传递,并且目的地也是 intent 参数,因此代理并未询问旅游目的地。当页面最初处于活跃状态时,以及在其活跃期间,任何与意向参数同名的表单参数都会自动设置为会话参数值,并跳过相应的提示。

  1. 切换到管理标签页,然后点击意图部分下的 head.send group request 意图。查看为此 intent 提供的训练短语以及训练短语的带注释部分。

查看为此 intent 提供的训练短语以及训练短语的带注释部分。

  1. 假设训练短语为“I need to organize a trip to Costa Rica for 15 divers”(我需要为 15 位潜水员安排一次哥斯达黎加之旅)。“哥斯达黎加”带有目的地注释,“15”带有房客人数注释。当您为训练短语的特定部分添加注释后,Dialogflow 会识别出这些部分只是最终用户将在运行时提供的实际值的示例。因此,对于初始输入“Do you offer charters to the Galapagos Islands?”(你们提供前往加拉帕戈斯群岛的包机服务吗?),Dialogflow 从“加拉帕戈斯群岛”中提取了目的地参数。

接下来,我们将了解当系统要求填入表单参数时,如果我们没有向代理提供有效输入,会发生什么情况。

输入内容无效

  1. 在模拟器面板中,点击重置图标,开始与代理进行新的对话。
  2. 表达进行团体预订的意图,但这次不要告诉代理您想去哪里,当被问及目的地时,请回复一个不是哥斯达黎加、加拉帕戈斯或墨西哥的随机值。

输入无效的目标平台

  1. 管理标签页上,点击资源部分下的实体类型。请注意有两个标签页:在“系统”标签页下,您可以找到您的代理当前使用的系统实体。自定义标签页会列出为匹配特定于此代理的数据而创建的自定义实体。

目标自定义实体

  1. 点击目的地实体,了解该实体匹配哪些值。“欧洲”不是其中一个条目,也不是同义词。
  2. 在流程图中,展开包含表单参数的收集更多信息页面。点击目的地参数。
  3. 在参数面板中,向下滚动到重新提示事件处理脚本部分,然后点击无匹配默认事件处理脚本。

此参数级事件处理脚本专门用于在表单填充过程中处理无效的最终用户输入。由于“欧洲”是意外输入,因此系统调用了 sys.no-match-default 事件,并调用了为此事件定义的相应重新提示处理程序。Agent says部分列出了两条备选的重新提示消息。

当最终用户输入无效目的地时,静态替代重新提示消息。

太棒了!这些测试用例代表了代理应妥善处理的常见场景。用户经常会提出聊天机器人无法回答的问题,或提出聊天机器人无法满足的要求。针对长尾用户进行设计非常复杂,这意味着要设计出大多数用户不会遵循的路径。考虑对话中可能出现的所有问题,以及用户可能采取的所有意外或不受支持的路径。

自动语音识别 (ASR) 技术的进步意味着我们几乎总是能准确知道用户说了什么。不过,确定用户意图仍然是一项挑战。话语通常无法单独理解,只能在上下文中理解。在此 Codelab 的下一部分中,我们将探讨 Google 最新的生成式大语言模型 (LLM) 如何帮助对话重回正轨并继续进行。

5. 启用生成式后备

什么是生成式后备功能?

生成式后备功能是一项 Dialogflow CX 功能,可使用 Google 的大语言模型 (LLM) 生成虚拟客服回答。

有何帮助?

在关键用例之间,还有一些较为常见的用户请求,例如重复代理所说的话(以防用户没听懂)、在用户要求时保持通话以及总结对话。在第一次测试中,代理未能回答“什么是船宿?”这个问题,因为我们尚未为此问题创建意图,也未设计用于处理与水肺潜水和船宿相关的此类一般性问题的流程。

即使意图非常明确,仍有可能出现错误。用户可能会保持沉默(无输入错误)或说出意外内容(无匹配错误),从而偏离脚本。虽然防止错误发生比在错误发生后处理错误更好,但错误是无法完全避免的。“抱歉,我不确定怎么回答”等通用提示或类似的最低可行解决方案通常不够好。错误提示应遵循合作原则,该原则认为,高效的沟通依赖于对话参与者之间存在潜在的合作关系。

在下一部分中,我们将了解如何配置生成式后备功能,以提高意图覆盖率并简化错误处理,从而提供更好的客户体验。

为整个流程的无匹配事件启用生成式后备

您可以为流、页面或参数填充期间使用的无匹配项事件处理程序启用生成式后备。如果为无匹配事件启用了生成式后备,则每当该事件触发时,Dialogflow 都会尝试生成一个响应,并将其反馈给用户。如果生成回答失败,系统会改为发出常规的预设客服人员回答。

您可以在代理中针对无匹配项事件处理脚本启用生成式后备,该后备可用于流、页面或参数 fulfillment。

我们将开始为整个 Liveaboards 流程的 no-match-default 事件启用生成式后备。

  1. 展开流程的初始页
  2. 点击事件处理脚本下的 sys.no-match-default
  3. Agent responses 下,选中启用生成式后备,然后点击 Save

在“代理回答”下,选中“启用生成式后备”

保存即可在 Liveaboards 启动页上启用生成式后备

针对特定无匹配事件启用生成式后备

现在,我们希望启用生成式后备,以便在代理询问乘客人数时处理无效输入:

  1. 打开包含表单参数的收集更多信息页面。点击 number-of-guests 参数。
  2. 找到目标 No-match 事件处理脚本(向下滚动到 Reprompt 事件处理脚本部分,然后点击 No-match default 事件处理脚本)

找到目标“无匹配”事件处理脚本(向下滚动到“重新提示”事件处理脚本部分,然后点击“无匹配”默认事件处理脚本)

  1. 智能体回答下,选中启用生成式后备

在参数 number-of-guest 上启用生成式后备

  1. 最后,点击保存
  2. 现在,重复上述步骤,为目的地电子邮件地址启用生成式后备

太棒了!您已启用生成式后备来处理意外 intent 和无效的参数值。接下来,我们将了解如何通过文本提示来配置生成式后备功能,该提示会指示 LLM 如何响应。

6. 配置生成式后备

生成式后备功能会将请求传递给大语言模型,以生成回答。请求采用文本提示的形式,其中包含自然语言以及有关代理和对话当前状态的信息。您可以通过多种方式配置此功能:

  1. 选择要用于生成回答的特定(已定义的)提示。
  2. 定义自定义提示。

选择已定义的提示

  1. 在 Dialogflow CX 控制台中,点击代理设置

前往代理设置

  1. 前往 机器学习 标签页,然后前往 生成式 AI 子标签页。

生成式 AI 子标签页

该功能随附两个模板提示:“默认”模板(不可见)和“示例”模板,后者可指导您编写自己的提示。

  1. 选择示例模板,然后点击下拉菜单右侧的修改按钮以检查该模板。

点击模板下拉菜单右侧的“修改”按钮即可检查该模板。

借助预定义的提示,虚拟客服可以处理基本的对话情境。例如:

  • 向用户问候并道别。
  • 重复代理所说的内容,以防用户没听懂。
  • 在用户要求时保持通话。
  • 总结对话内容。

让我们尝试为 Divebooker 代理定义一个具体的文本提示!

7. 自行定义提示

  1. 复制下方的提示,然后将其粘贴到文字提示区域中
You are a friendly agent that likes helping traveling divers.
You are under development and you can only help
$flow-description

At the moment you can't help customers with land-based diving and courses. You cannot recommend local dive shops and diving resorts.

Currently you can $route-descriptions

The conversation between the human and you so far was:
${conversation USER:"Human:" AGENT:"AI"}

Then the human asked:
$last-user-utterance

You say:
  1. 选择另存为新模板,将新提示存储为新模板(选择新模板名称),然后点击面板右下角的保存

为代理创建自定义文本提示,并将其另存为新模板

  1. 如需使新创建的提示成为有效提示,您还需要保存设置。

保存新设置

撰写自己的文字提示时,请务必清晰、简洁且具有指导性。向 LLM 提供的提示的撰写方式会极大地影响 LLM 回答的质量。LLM 经过训练,能够遵循指令,因此您的提示越像精确的指令,就越有可能获得更好的结果。撰写提示,然后根据获得的结果反复迭代改进提示。

如需撰写有效的提示,请遵循以下最佳实践:

  1. 提供一个简明扼要的说明,告知 LLM 您希望它完成什么任务。说明内容不应过多,也不应过少。内容要完整且简短。
  2. 此外,提示应该具体化并明确定义,避免使用模糊或不明确的语言。
  3. 将复杂的任务分解为更易于管理的较小任务。通过将任务分解为更小的步骤,您可以帮助模型一次专注于处理一项任务,并降低出错或混乱的可能性。
  4. 如需提高回答质量,请在提示中添加示例。LLM 通过这些示例进行情境学习,了解如何生成回答。

创建提示时,除了使用自然语言描述应生成哪种类型的上下文之外,还可以使用以下占位符:

  • $conversation 代理与用户之间的对话,不包括用户的最后一句话。您可以调整轮次前缀(例如:在文本提示中指定“人类”“AI”或“你”“Agent”
  • $last-user-utterance 用户的最后一句话。
  • $flow-description 有效流程的流程说明。
  • $route-descriptions 有效 intent 的 intent 说明。

现在我们已经有了初始文本提示,下一步是确保流程和意图有良好的说明。

8. 添加流程和意图说明

添加流程说明

  1. 如需向 Liveaboards 流添加说明,请将鼠标悬停在 Flows 部分中的相应流上,以访问流设置。

将鼠标悬停在“流程”部分中的流程上,即可访问流程设置。

  1. 点击选项 78d2781c655810e7.png 按钮。
  2. 选择流程设置,然后添加以下说明(或类似说明):search, find and book liveaboards

为船宿流程添加说明

  1. 点击保存

添加意图说明

  1. 现在,我们为 head.send.group.request intent 添加一个合适的说明。切换到管理标签页,在资源部分下选择意图,然后选择 head.send.group.request 意图。
  2. 添加以下说明:assist users with group or full charter reservations. Initially collect travel details including departure period, destination, number of guests (min 4 max 15 people), contact details. The destination must be one of the following in the Pacific: Costa Rica, Mexico, Galapagos Islands

请注意,说明中包含重要信息,例如船只上允许的乘客人数下限和上限。请谨记!

  1. 点击保存

大功告成!您已为流和参数 fulfillment 的无匹配事件处理脚本启用了生成式后备。您还定义了自己的文本提示,生成式后备功能会将该提示传递给大语言模型,以生成生成式回答。

在下一部分中,您将重新测试代理,看看它如何回答之前提出的相同难题。

9. 重新测试代理

现在,您已在虚拟客服上配置并启用了生成式后备,接下来可以提出类似的难题,看看虚拟客服如何处理回答。

点击测试代理以再次打开模拟器。

再次测试代理

再次向客服人员询问有关船宿和船宿潜水的信息。从现在开始,请注意每个对话框中都有用户定义的消息以及以红色框突出显示的生成的回答。

重新测试代理,并再次询问什么是船宿

您是否收到了有用的信息性回答,而不是通用的重新提示?太棒了!在清晰简洁地描述了您希望代理完成的任务(在文本提示和流程说明中)后,您的机器人现在在回答详细问题方面变得更加智能,而无需创建特定意图。客户会很乐意看到智能体能够提供更明智的回答,而不是无法采取行动的回答。

不要害羞,大胆地向代理提出要求,询问它是否可以帮助您找到潜水课程,因为您还不是认证潜水员。

 询问智能体是否可以帮助您寻找水肺潜水课程

没错,我们目前尚未将 Agent 设计为可协助处理潜水课程相关事宜。How does the agent know that? 在文本提示中,我们明确列出了客服人员可以提供哪些方面的帮助,以及无法提供哪些方面的帮助。“目前,您无法为客户提供陆基潜水和课程方面的帮助。您不得推荐当地潜水商店和潜水度假村”

现在重新测试正常情况,并丰富对话内容。让我们看看体验发生了哪些变化。

重新测试正常情况,并在对话中发挥创意

重新测试正常情况,并在对话中发挥创意

当 Dialogflow 匹配某个意图或尝试根据流程设计收集参数时,它会显示在设计时定义的履单。当用户偏离脚本,要求总结旅行详情或主动提供电话号码时,生成式后备功能就会发挥作用。

太棒了!您已重新测试了正常情况,希望您与代理的对话尽可能贴近与人工客服的对话体验,让您感到愉快和自然。

遗憾的是,对话中可能会出现问题。我们来做另一个测试,这次当系统询问入住人数时,您说一个大于 15 的数字。

提供大于 15 的宾客人数

提供大于 15 的宾客人数

以下是几点注意事项:

  1. 为什么 20 不是有效数字?因为我们在意图说明中设置了允许的入住人数上限:“代理收集出发时间段、目的地、入住人数 ***(最少 4 人,最多 15 人)***、详细联系信息等信息”。LLM 返回的生成式回答“抱歉,我们只能协助预订最多 15 位房客的团体预订”与我们给出的房客人数限制完全一致。为了进一步强制执行此限制,number-of-guests 是一个自定义的正则表达式实体,仅匹配 4 到 15 范围内的数字。
  2. 对话继续进行,因为用户最终仍希望获得 15 名潜水员的报价。这种情况在自然对话中经常发生,我们经常会改变主意!请注意,该智能体非常配合,会温和地引导用户回到成功的道路上。

对话设计涉及编写对话的一半脚本,希望它足够稳健,以便任何人都可以介入并扮演另一半角色。在设计长尾对话时,开发者需要重点关注用户在对话的每个步骤中可能会说的话,以便定义路由、处理程序和参数。因此,我们在 Dialogflow CX 中添加了生成式后备功能,让开发者能够专注于对话设计原则,减少对实现细节的关注,从而为用户提供强大的对话体验。

我们再进行一次测试,这次再次向机器人提出要求,让它推荐马尔代夫等不在可用目的地列表中的地点。然后,我们将快速了解幕后发生的情况。

再次向机器人发起挑战,这次使用不在可用目的地列表中的地点(例如马尔代夫)

请注意,由于我们还为目的地参数的 no-match 事件启用了生成式后备,因此系统会向大语言模型发送请求,以生成回答。系统会忽略常规的预设回答(在“代理说”下方)。

下面的文本框将帮助您更好地了解占位符如何帮助塑造发送给大语言模型的请求。

这是我们在 Dialogflow 中配置的自定义文本提示,其中占位符以粗体突出显示:

You are a friendly agent that likes helping traveling divers.
You are under development and you can only help
$flow-description

At the moment you can't help customers with land-based diving and courses. You cannot recommend local dive shops and diving resorts.

Currently you can $route-descriptions

The conversation between the human and you so far was:
${conversation USER:"Human:" AGENT:"AI"}

Then the human asked:
$last-user-utterance

You say:

在下方的文本框中,我添加了大语言模型收到的输入内容以及包含将向用户读出的生成回答的输出内容:

llm_input:
You are a friendly agent that likes helping traveling divers.
You are under development and you can only help search, find and book liveaboards.

At the moment you can't help customers with land-based diving and courses. You cannot recommend local dive shops and diving resorts.

Currently you can assist users who are looking for a group reservation or a full charter. Initially collect travel details including departure period, destination, number of guests (min 4 max 15 people), contact details. The destination must be one of the following in the Pacific: Costa Rica, Mexico, Galapagos Islands.

The conversation between the human and you so far was:
Human: Hi, my name's Alessia
AI Hi Alessia, what can I help you with today?
Human: Can you help me find a nice boat for myself and my family?
AI To assist you with that I need to collect the details of your travel and then we'll get back to you with an offer shortly.
Where would you like to go? We can organize a charter in Costa Rica, Galapagos Islands and several locations around Mexico

Then the human asked:
The kids want to go to the Maldives

llm_output:
You say:
I'm sorry Alessia, we can only help you with liveaboards in Costa Rica, Galapagos Islands and several locations around Mexico.

与之前进行的测试类似,发送给用户的回答由模型生成,并依赖于我们在意图描述中提供的信息:“目的地必须是太平洋沿岸的以下地点之一:哥斯达黎加、墨西哥、加拉帕戈斯群岛

修改禁用短语列表

您可以通过多种方式配置生成式后备功能:

  1. 选择要用于生成回答的特定(已定义的)提示。
  2. 定义自定义提示。
  3. 更改违规短语列表。

到目前为止,我们已经介绍了前两种方法。我们来了解一下第三种方法。

  1. Agent 设置中,前往 机器学习 标签页,然后前往 生成式 AI 子标签页。
  2. 禁用短语部分中,将以下句子添加到列表中:
  3. Dangerous country
  4. Hateful place
  5. Medical assistance
  6. 点击保存
  7. 点击重置图标,然后重新测试最后一个场景。输入违禁词组,而不是提供世界各地的美丽潜水目的地。

测试某个禁用短语

系统会根据违禁短语列表检查提示和生成的回答。禁止使用的词组是指生成式 AI 禁止使用的词组。如果输入内容包含禁用短语或被视为不安全的短语,生成操作将失败,系统会改为发出常规的预定回答(在同一履单中的“代理说”下)。

太棒了!我们已经介绍了各种对话场景,在这些场景中,生成式回答可以发挥重要作用。欢迎继续测试!

10. 恭喜

恭喜您完成此 Codelab!放松一下!

Cbo Chill

您已成功创建虚拟客服,并已在流中使用的 no-match 事件处理程序中以及在参数填充期间启用生成式后备。

生成式后备功能与良好的流程和意图描述相结合,可以提供智能体特有的协作式回答,而不是“抱歉,我不知道该如何提供帮助”或“抱歉,您输入了无效选项”等通用提示。大语言模型生成的错误提示可以温和地引导用户回到成功的道路上,或者重置用户对可能和不可能的预期。

您可以随意测试其他对话情境,并探索与 Dialogflow CX生成式 AI 相关的其他可用功能。

清理

您可以执行以下清理操作,以避免系统因本 Codelab 中使用的资源向您的 Google Cloud 账号收取费用:

  • 前往 Dialogflow CX 控制台,删除您创建的所有代理。
  • 在 Google Cloud 控制台中,前往“API 和服务”页面,然后停用 Dialogflow API。

深入阅读

请参阅以下指南和资源,继续了解对话式 AI 和生成式 AI:

许可

此作品已获得 Creative Commons Attribution 2.0 通用许可授权。