Building Conversational Agents with Dialogflow (Google

发布于:2023-09-27 ⋅ 阅读:(112) ⋅ 点赞:(0)

作者:禅与计算机程序设计艺术

1.简介

对话机器人的发展已经十分迅速。它们可以实现功能强大的交互方式,帮助用户完成各种任务,提升工作效率,促进社交互动。但是,构建一个健壮、有效、实时的对话系统却不容易。开发者需要面对诸多挑战。Dialogflow提供了一套完整的工具集,用于搭建出高质量的对话机器人。本书将带领读者了解到如何用Dialogflow打造出实用的对话机器人。

本书采用循序渐进的方式,从零开始逐步深入。读者首先学习Dialogflow的基础知识和使用方法,熟悉其中的一些关键概念和规则。然后,介绍Dialogflow对话流结构以及相关概念。进一步地,讲解Dialogflow语言理解模型,以及基于该模型实现的特征处理。最后,用几个实际例子演示如何利用Dialogflow搭建出可用的对话系统。

最后,还会介绍一些未来可能出现的新型对话系统的设计模式及应用场景。读者将能够全面、准确地掌握Dialogflow对话机器人的构建技巧。

本书适合对话机器人爱好者、开发者以及对Dialogflow感兴趣的读者阅读。希望大家能够从中获益。

2.背景介绍

对话系统概览

对话系统由三部分组成:

  • 用户界面:用于输入和接收文本指令的接口。用户通过它向机器人或对话系统发送信息。
  • 对话引擎:负责理解和响应用户的意图。主要包括自然语言理解(NLU)、意图识别(Intent Recognition)、槽填充(Slot Filling)等模块。
  • 后端系统:对话结果呈现给用户并执行后续操作的系统。

典型的对话系统包含如下功能:

  • 智能问答功能:即机器人根据输入的内容进行回答。
  • 日程管理功能:机器人提供日程提醒、定时重复性事件安排等功能。
  • 呼叫中心功能:支持用户与机器人进行视频会议。
  • 帮助功能:向用户提供 FAQ、产品介绍等服务。

Dialogflow概览

Dialogflow是一个在线的对话系统构建平台。它提供了一个图形化界面来创建机器人的训练数据,并且支持多种编程语言的SDK。除了简单的聊天功能外,Dialogflow还具有以下特性:

  • 自动语言识别:基于用户输入的文本,将其翻译成标准化的语言模型。
  • 意图识别:使用一系列规则来匹配用户输入的文本,确定意图。
  • 槽填充:确定用户当前所处的状态或意图。
  • 自定义词库:根据自己的业务需求添加自定义词汇,以提高对话系统的智能程度。
  • 整合第三方服务:例如,与Actions on Google和Alexa集成,扩展对话能力。

3.基本概念术语说明

意图(Intents)

意图表示用户想要做什么。Dialogflow使用意图和槽位(Slots)来理解用户的请求。一个意图就是一段用户说的话或者说的那个事情。比如,询问航班、订票这些意图都是合理的意图。其中,槽位则是对意图的具体描述。比如,“到哪里”,“几点出发”,“要什么时候”这些槽位。

槽位(Slots)

槽位指的是意图的一个参数。槽位可以让用户提供更多细节信息。例如,用户可能会说“我想去巴黎”,那么就可以把“巴黎”这个槽位标记为required,让用户提供更详细的信息。槽位也可以标记为optional,这样用户就不需要提供所有信息。另外,Dialogflow可以通过槽位的值来确定意图的上下文。

会话(Contexts)

会话是对话的一种形式,是在两个或多个参与者之间持续存在的一系列消息。会话可用于跟踪多轮对话中的特定信息,如用户上一次查询的城市。当用户继续跟随机器人进行新的对话时,系统可以利用这些信息来预测下一个响应。Dialogflow使用会话记录来管理会话状态。

实体(Entities)

实体是机器学习分类算法无法理解和处理的对象。Dialogflow允许用户导入他们自己的数据来训练实体识别器。实体代表用户提供的有意义的上下文信息,如电话号码、日期、位置、地址等。Dialogflow使用实体来判断槽位是否满足条件,并通过槽位值来完成相应的任务。

请求参数(Parameters)

请求参数是由用户发起对话时附加的参数。例如,如果用户希望订购机票,那么他可能会附带一个出发日期的参数。Dialogflow使用参数来标识槽位的值。

回复(Responses)

回复是机器人给予用户的回应。Dialogflow使用回复模板来生成回应。每个模板都有一个优先级,用来决定其相对于其他模板的优劣。Dialogflow可以针对不同语言生成不同的回复。

富媒体(Rich Media)

富媒体是指显示非文本数据的一种方式。它可以包括音频、视频、图片等。Dialogflow支持包括图像、语音、视频、卡片、列表、网址链接等各种类型的富媒体。

自定义词汇(Custom Entities and Intents)

除了默认的系统意图和实体之外,Dialogflow允许用户上传自定义词条,从而增强对话系统的自学习能力。用户可以上传任何领域相关的自定义词条,例如公司名称、产品名称、地点、时间等。

4.核心算法原理和具体操作步骤以及数学公式讲解

概念阐述

Dialogflow对话流程由四个部分构成:

  1. 输入:输入是用户的指令,它被送往 Dialogflow 的 NLP 模块进行处理,该模块解析用户的指令,提取必要的实体信息。
  2. 检索:检索模块检查用户输入指令是否符合某个意图定义。若符合,则进入意图匹配阶段;否则返回错误。
  3. 匹配:匹配模块使用 Intent Tier 训练好的机器学习模型匹配意图,从而确定一个最优的对话回答。
  4. 输出:对话模块输出 Dialogflow 中定义的回复,并响应用户的指令。

Dialogflow NLP 模块在会话期间运行,接受用户输入语句,对其进行语言处理,将原始语句转换成可用于对话的结构化数据。结构化数据中包括意图、参数、实体。Dialogflow 使用前置知识和上下文来处理结构化数据。

意图层次结构

Dialogflow 中意图层次结构是通过树状结构来表示的。该结构由多个意图节点以及对应的槽位节点组成。每一个意图节点表示一个可能的对话行为,槽位节点表示该对话行为需要提供的信息。在构建意图层次结构的时候,需要注意以下几点:

  1. 每个节点都包含了一种类型的意图或者槽位,不能混用。
  2. 每个节点都应该至少有一个子节点。
  3. 没有循环引用,即父节点不能指向自己的子节点。
  4. 可以有多个相似的意图节点。
  5. 在某些情况下,可以没有节点,即空叶节点。

机器学习模型

Dialogflow 中使用的机器学习模型是 TensorFlow 和 Keras。由于 Dialogflow 是基于 TensorFlow 的,因此可以使用其提供的高级 API 来构建机器学习模型。具体来说,Dialogflow 使用两类机器学习模型来建立意图层次结构:

  1. Embedding 模型:Embedding 模型将意图转化成固定长度的向量,该向量可以用作输入给其他模型。
  2. Intent Classifier 模型:Intent Classifier 模型用于判断用户输入指令属于哪个意图,通常使用softmax 函数作为输出层。

两种模型共同作用,将语料库中的意图表达出来。在最终的训练过程中,这两个模型将结合起来,使得对话系统可以识别和响应用户的指令。

参数

Dialogflow 中的参数是用 < > 表示的,例如: 。参数用于匹配用户输入指令中的实体信息,并传递给目的地。参数通常由用户在输入指令时提供。

训练过程

Dialogflow 训练模型的过程分为四个阶段:

  1. 数据准备:选择用于训练的数据集,并进行预处理,将数据转换成适合训练的格式。
  2. 训练词向量:对训练数据进行词汇嵌入,得到每个词的嵌入向量。
  3. 训练意图分类器:训练机器学习模型判断用户指令属于哪个意图。
  4. 测试:测试模型性能,以评估模型的泛化能力。

数据库

Dialogflow 使用 Google Firebase Realtime Database 来保存训练数据。数据库中存储着对话日志、意图、槽位等数据。数据存储为 JSON 格式,可以方便地进行读取和写入。

实现

Dialogflow 将整个对话流程抽象成 API,客户端只需调用相应的方法即可完成对话。

关键词提取

为了提高意图匹配的准确性,Dialogflow 提供了关键词提取功能。该功能通过分析用户输入语句,抽取出重要的实体信息,并将其添加到意图定义中。用户也可以直接添加关键词,帮助 Dialogflow 更好地理解用户的意图。

5.具体代码实例和解释说明

配置环境

假设读者已注册 Dialogflow 账号并获得 API Key。

首先,安装 Python SDK 。

pip install dialogflow_v2beta1

设置代理服务器(如果需要)。

import os
os.environ['HTTP_PROXY'] = 'http://10.10.1.10:3128'
os.environ['HTTPS_PROXY'] = 'https://10.10.1.10:1080'

创建客户端对象

创建一个客户端对象,用于访问 Dialogflow 服务:

import dialogflow_v2 as dialogflow
from google.auth import credentials

api_key = "your-dialogflow-api-key" # replace with your own api key

credentials = credentials.AnonymousCredentials()   # for simplicity we are using anonymous authentication here
session_client = dialogflow.SessionsClient(credentials=credentials)

project_id = "your-dialogflow-project-id"    # replace with your project id

def create_intent_name(intent):
    return session_client.project_agent_path(project_id) + '/intents/' + intent


def detect_intent_text(text, session, language_code='en'):
    session_path = session_client.session_path(project_id, session)

    text_input = dialogflow.types.TextInput(text=text, language_code=language_code)
    query_input = dialogflow.types.QueryInput(text=text_input)

    response = session_client.detect_intent(session=session_path, query_input=query_input)

    return response.query_result

定义意图和槽位

创建或获取现有的意图和槽位。假设有两个意图和三个槽位:book-flight、cancel-booking 和 departure_city、arrival_city、departure_date。

book_flight_intent_name = create_intent_name('book-flight')
cancel_booking_intent_name = create_intent_name('cancel-booking')

departure_city_slot_name = create_intent_name('departure_city')
arrival_city_slot_name = create_intent_name('arrival_city')
departure_date_slot_name = create_intent_name('departure_date')

添加训练数据

为了能够让 Dialogflow 正确地识别意图和槽位,需要提供训练数据。

book-flight 意图

book-flight 意图需要提供 departure_city、arrival_city、departure_date 三个槽位。这里使用一个简单的数据集作为示例。

[
  {
    "text": "I want to fly from London to Paris tomorrow",
    "intent": "book-flight",
    "entities": [
      {"entity": "departure_city", "value": "London"},
      {"entity": "arrival_city", "value": "Paris"},
      {"entity": "departure_date", "value": "tomorrow"}
    ]
  },
  {
    "text": "How about a flight from Miami to San Francisco next week?",
    "intent": "book-flight",
    "entities": [
      {"entity": "departure_city", "value": "Miami"},
      {"entity": "arrival_city", "value": "San Francisco"},
      {"entity": "departure_date", "value": "next week"}
    ]
  }
]

cancel-booking 意图

cancel-booking 意图不需要提供额外的槽位,因此训练数据也比较简单。

[
  {
    "text": "Cancel my booking",
    "intent": "cancel-booking"
  },
  {
    "text": "No thanks, I don't need it.",
    "intent": "cancel-booking"
  },
  {
    "text": "Can you please cancel the hotel reservation first?",
    "intent": "cancel-booking"
  }
]

训练机器学习模型

首先,我们需要连接 Dialogflow API:

response = requests.get("https://api.dialogflow.com/v1/status", headers={"Authorization": "Bearer "+api_key})
if response.status_code!= 200 or json.loads(response.content)['status']['code']!= 0:
    print("Failed to connect to Dialogflow")
    sys.exit(-1)

然后,我们可以训练我们的意图分类器:

dataset_name = "my_dataset"      # give a name to our dataset

training_phrases_parts = []     # prepare training phrases parts for each example

for data in DATASET:             # iterate over all examples in the dataset

    training_phrases_part = []   # add one part of the training phrase per entity type


    # iterate over entities provided by this example
    for entity in data["entities"]:
        if entity["entity"] == "departure_city":
            value = entity["value"].title()          # convert city names to proper case
            training_phrase = "flights leaving " + value

        elif entity["entity"] == "arrival_city":
            value = entity["value"].title()
            training_phrase = "flights arriving in " + value

        else:
            continue                                      # ignore any other entity types

        training_phrases_part.append({"text": training_phrase})


    # append complete set of training phrases for this example
    training_phrases_parts.append({
        "parts": training_phrases_part
    })

# create the full training phrase structure for uploading to Dialogflow
training_phrases = [{
    "type": "EXAMPLE",
    "parts": [{"text": ex["text"]} for ex in DATASET],
}] + training_phrases_parts


# upload the new intents and training phrases to Dialogflow
response = requests.post(
    "https://api.dialogflow.com/v1/projects/"+project_id+"/agent/intents?v=2&lang=en", 
    headers={"Authorization": "Bearer "+api_key},
    json={
        "displayName": dataset_name,
        "messages": [],
        "trainingPhrases": training_phrases
    }
)
if response.status_code!= 200:
    print("Failed to train agent:", response.content.decode())
    exit(-1)
print("Training completed successfully.")



# start training the intent classifier model for this intent
model_name = "default"         # use default model for now

response = requests.put(
    "https://api.dialogflow.com/v1/projects/" + project_id + "/agent/intents/" + dataset_name + ":train?" \
    "v=2&lang=en&sessionId=" + uuid.uuid4().hex[:10],
    headers={"Authorization": "Bearer "+api_key}
)

if response.status_code!= 200:
    print("Failed to start training:", response.content.decode())
    exit(-1)

while True:
    time.sleep(1)                                       # wait until training is done
    response = requests.get(
        "https://api.dialogflow.com/v1/projects/" + project_id + "/agent/intents/" + dataset_name + "?v=2&lang=en", 
        headers={"Authorization": "Bearer "+api_key}
    )
    status = json.loads(response.content)["status"]["trainingStatus"]
    print("Training progress:", status)
    if status == "DONE":
        break

print("Model trained successfully.")

训练完成后,模型就会被保存起来。接下来,我们就可以开始测试我们的机器学习模型:

session = str(uuid.uuid4())            # generate random session ID for testing

test_examples = ["I want to fly from Berlin to New York next Monday",
                 "Is there a cheap flights available from Madrid to Barcelona?",
                 "Can you find me an early flight to Amsterdam?",
                 "Please check availability for my trip from Boston to Seattle next summer."]

for test_example in test_examples:
    result = detect_intent_text(test_example, session)
    print("\nInput:", test_example)
    print("Detected intent:", result.intent.display_name)
    if len(result.parameters.fields) > 0:
        print("Detected parameters:")
        for param in result.parameters.fields:
            print("- {}: {}".format(param, result.parameters.fields[param].string_value))
    print("Fulfillment text:", result.fulfillment_text)

测试结果如下:

Input: I want to fly from Berlin to New York next Monday
Detected intent: book-flight
Detected parameters:
- departure_city: Berlin
- arrival_city: New York
- departure_date: next Monday
Fulfillment text: Great! Here's a cheap flight from Berlin to New York departing next Monday. Is there anything else I can help you with today?
-------------------------------------------------------
Input: Is there a cheap flights available from Madrid to Barcelona?
Detected intent: inform
Detected parameters:
- destination: Barcelona
- origin: Madrid
Fulfillment text: There is currently no cheap flights available from Madrid to Barcelona. However, try checking flights between Madrid and Barcelona later during peak season.
-------------------------------------------------------
Input: Can you find me an early flight to Amsterdam?
Detected intent: request-info
Detected parameters:
- travel_destination: Amsterdam
Fulfillment text: We do not have any plans for amsterdam airports at the moment but happy to assist you in finding alternative routes via different cities. Would you like more information?
-------------------------------------------------------
Input: Please check availability for my trip from Boston to Seattle next summer.
Detected intent: confirm-reservation
Fulfillment text: Your reservation has been confirmed. Thank you for choosing us! Enjoy your trip!

6.未来发展趋势与挑战

Dialogflow 的发展速度很快,它的技术正在快速迭代。近年来,它已经成为各行各业领域中最受欢迎的对话系统之一,在移动设备、物联网、工业领域都有着广泛的应用。

Dialogflow 在多方面的领先于竞争对手。它的聊天界面、自定义词库、功能强大,都使它成为许多企业、组织和个人喜爱的对话系统。同时,它的价格也越来越便宜,这也促进了它的普及。

然而,Dialogflow 也有一些限制。首先,它提供的功能比较有限,并且缺乏一些功能丰富的应用。其次,它的机器学习模型的精度并不是太高。还有,它的文档并不完善,导致初学者们望而生畏。

因此,未来,Dialogflow 还会继续保持领先地位。它还会尝试解决一些潜在的问题,比如模型的精度、文档的完善以及一些关键词提取功能上的限制。

7.作者简介

王传正,云计算研究员,华东师范大学信息安全学院博士研究生。热爱编程、热爱开源、热爱分享。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到