Build Your Own Mobile Chatbot With Dialogflow
作者:禅与计算机程序设计艺术
1.简介
Chatbot(智能交流工具)是一种前沿的人工智能技术,在当前社会中逐渐占据重要地位。这种系统通过模拟人类对话的方式执行特定任务,在过去几年里迅速发展成熟并得到广泛应用。目前Chatbot已经渗透到多个行业领域,并展现出强大的适应能力以及高效的运行水平。它的优势不仅体现在提高工作效率上,还能够降低通信成本并显著提升人机协作体验。然而自建一个有效的Chatbot系统对技术人员来说仍具挑战性
基于 Dialogflow 的 Chatbot 可以做到以下四点:
以满足业务需求为目标,并避免对技术实现的过多关注。
通过简单直观的界面完成配置操作。
涵盖包括文本、图像、视频、音频等多种类型的消息。
提供丰富多样的插件库和第三方服务支持,并能够快速接入各种业务场景。
本文旨在深入解析Dialogflow框架,并教会您构建自己的聊天机器人服务系统。文章末尾将呈现一个实用的实践案例,为新手用户提供一个可参考的实践方向。
2.基本概念和术语
2.1 Dialogflow 概念
Dialogflow 是由 Google 提供的机器即服务(RaaS)产品。
它不仅帮助开发者迅速搭建具备智能交互能力的聊天机器人,并且能够整合到移动应用或网站中。
通过设定规则和语句来确定对话流程并识别用户的输入信息,则可自行设计定制化的聊天机器人。
其主要特性如下:
- 聊天机器人的目标受众覆盖范围广,涵盖公共群组至私密社交平台.
- 通过对话训练(对话学习),仅需少量示例对话即可使Dialogflow理解用户意图及反馈.
- 建立多个聊天机器人时可共用相同的对话机制.
- 该系统可集成第三方服务与API:例如Google Assistant及Google Cloud Platform.
- 该系统能够快速部署并在短时间内投入运行.
2.2 术语表
| 术语 | 描述 |
|---|---|
| Agent | Dialogflow 的核心组件之一,用来管理对话模型,管理不同会话的状态及参数。 |
| Intent | 对话中的用户期望,即用户想要完成什么样的任务。 |
| Entity | 用户所说的内容中明显的特征,如姓名、地址、日期等。 |
| Slot filling | 在对话过程中,对 Entity 的值进行填充,类似于问答系统中的槽位填充。 |
| Rich message | 基于结构化数据的一种消息类型,可呈现更丰富的信息,如卡片、按钮、列表、图片、链接等。 |
| Context | 对话上下文环境,记录当前会话的所有信息。 |
| Parameters | 参数可以定义在 Intents 或 Entities 上,用作决策条件。 |
| Webhook | 外部服务器用于响应 Dialogflow 发出的请求,向用户返回信息或者触发其他动作。 |
| Integration | 将 Dialogflow Agent 与第三方服务集成,例如 Google Calendar 和 Google Maps。 |
3. 核心算法原理和具体操作步骤
3.1 创建 agent
首先必须搭建一个agent,在Dialogflow系统中,默认情况下都是不可或缺的关键部分。该agent需配置名称与工作语言参数。随后系统将根据所选语言自动生成一系列标准对话模式,在这些模式中涵盖了各种场景下的预设对话框架及操作指令。对于每个定制化的对话模块来说,默认的数据集可以被用户任意补充或调整。
3.2 创建 intents
Intent 是对话模型的核心要素之一,并且也是对话的主要目的。设计者通过设定 Intents 来完成对话系统架构的规划。
每个 Intent都需要明确其目的或任务,并设定相应的参数。这些参数将成为识别用户输入的基础依据。当对话模型接收到一条符合特定参数要求的输入时,从而触发相应的Action,并执行特定的任务。
举例来说, 假设有一个叫做'拨打固定电话'的Intent, 其参数可能包括电话号码. 当用户在对话中输入:'请给我打个电话'时, 系统会根据输入识别并触发相应的Action. 该Action将导致系统调用预设好的拨号功能进行通话. 类似地, 开发者还可以创建其他类型的Intent来实现更多功能, 如用于问候、查询天气、设置提醒等.
创建 Intent 时,需要注意以下几点:
- 每个意图对应特定的动词或短语。
- 当用户的输入无法匹配现有意图时,则会执行fallback操作。
- 为定义意图时需为其设定相关参数。
- 每个意图可能与多个训练数据集相关联。
- 当某个意图被触发后,则可以通过不同的回复策略或动作来响应用户的需求。
3.3 为实体创建 entities
在Dialogflow系统中设置了‘Entity’这一高级功能。该系统能够通过‘Entity’模块准确解析和辨识各种语义信息。包括但不限于人名、地名以及时间段等特定信息内容。当系统接收到包含特定信息内容的指令时,在内部进行数据处理与分析操作后会自动生成相应的响应结果。该系统能够自动解析并提取指令中所需的关键信息内容
创建 Entity 时,需要注意以下几点:
- 每个Entity都由一个名称标识,在命名时可以选择单一词或短语的形式。
- 在系统设计中,Entities和Intents通常协同创建以满足复杂需求;然而它们也可以独立存在以便于实现灵活的功能扩展。
- 关系体系设计上实现了Entities与Intents之间的多元关联机制;这种设计模式支持了一个Entity能够同时服务于多个Intent的需求,并且也能满足一个Intent对应多个Entities的需求。
- 每个Entity可能包含多个synonym属性来丰富其命名空间并提高信息表达的灵活性;
- 在层级化管理架构下;Entities被分配至特定层级从而明确了其在对话流程中的作用定位。
3.4 添加对话流程
训练完成后, 下一步就是对 agent 进行对话流程的配置. Dialogflow 基于对话记录、历史记录以及已知的知识, 结合自然语言处理能力和上下文理解能力, 具备识别用户意图并提供相应回答的能力. 其对话流程具有明确顺序特征, 一系列特定意图按照预定顺序进行匹配与执行, 形成完整路径. 每个会话开始时应包含问候条目或欢迎条目, 从而确保用户体验友好.
每一个 Intent 需要关联至少两个触发条件:
- Fulfillment triggers are mechanisms used to determine whether a user's utterance matches the criteria for triggering an intent.
- User inputs refer to the data provided by the user that is evaluated against intent matching criteria.
触发机制通常依赖于正则表达式模式匹配Regex以便识别特定的关键词如"我的行程"或"预订晚餐"。对于用户的输入我们通常通过自然语言理解技术进行分析以获取其内容和意图。
当某个意图被激活时, Dialogflow系统会识别符合条件的响应内容或操作步骤,随后执行相应的处理流程.用户随后给出的回答会引导系统进入下一阶段意图识别过程,这一循环将持续进行直至对话结束或是发生fallback操作.
3.5 使用 rich messages
丰富类型的消息建立在严格的结构化数据基础之上,并能够以多种多样的形式呈现到网页界面中。开发人员可以根据具体需求设计预设的框架,并注入具体的数据内容以实现动态更新。
目前 Dialogflow 支持的 rich messages 包括:
Text-based responses: 纯文本回答.
3.6 设置定时对话
在聊天机器人的开发过程中,除了提供预定义的回复之外还有一种常见的做法即定时对话这种机制能够定期发送信息以维持与用户的互动并促进用户持续参与交流
开发人员可以根据需求为某些意图设定特定的时间段有效性运行机制;例如,在节假日上班时段允许机器人执行愉快聊天功能。此系统会基于时区和偏移时间进行相应调整以确保正常运作。此外该系统还支持设置成持续循环模式让用户体验能够享受无休止的互动交流
4. 具体代码实例和解释说明
当前我们已经深入研究过Dialogflow的各种组件,并且对具体的代码实例进行了详细分析
4.1 安装 SDK
首先要安装 Dialogflow 的 Python SDK。命令如下:
pip install dialogflow_v2beta1
代码解读
4.2 导入依赖包
在代码中引入依赖包:
import os
import sys
import uuid
from google.api_core import retry
from google.cloud import dialogflow_v2beta1 as dialogflow
from google.protobuf import struct_pb2
PROJECT_ID = "your-project-id"
SESSION_ID = str(uuid.uuid4()) # generate a unique id for each user session
LANGUAGE_CODE = 'en' # set to your preferred language code (default is English)
代码解读
4.3 初始化 agent
初始化 agent 对象:
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "<path-to-service-account>"
session_client = dialogflow.SessionsClient()
session = session_client.session_path(PROJECT_ID, SESSION_ID)
agent_client = dialogflow.AgentsClient()
agents = agent_client.list_agents(parent=f"projects/{PROJECT_ID}")
if agents and len(agents) > 0:
my_agent = agents[0]
else:
raise Exception("No Dialogflow Agents found")
代码解读
4.4 创建 intent
创建 intent:
intent_client = dialogflow.IntentsClient()
intent = {
"display_name": "Test",
"training_phrases": [{"parts": [{"text": "hello"}]}],
"message_texts": [{"text": ["Hello!"]}]
}
response = intent_client.create_intent(request={"parent": my_agent.parent,
"intent": intent})
print(response)
代码解读
创建完成后,会得到类似如下输出:
name: "projects/<YOUR PROJECT ID>/locations/<LOCATION>/agents/<AGENT NAME>/intents/<INTENT NAME>"
displayName: "Test"
webhookState: RUNNING
代码解读
4.5 创建 entity
创建 entity:
entity_client = dialogflow.EntityTypesClient()
entity_type = {"display_name": "test"}
response = entity_client.create_entity_type(request={"parent": my_agent.parent,
"entity_type": entity_type})
print(response)
代码解读
创建完成后,会得到类似如下输出:
name: "projects/<YOUR PROJECT ID>/locations/<LOCATION>/agents/<AGENT NAME>/entityTypes/<ENTITY TYPE NAME>"
displayName: "test"
enableFuzzyExtraction: false
entities: []
代码解读
4.6 为 intent 添加 parameter
为 intent 添加 parameter:
param = {'display_name': 'number',
'value': struct_pb2.Value(number_value=5)}
params = [param]
intent['parameters'] = params
update_mask = {"paths": ['parameters']}
response = intent_client.update_intent(request={"intent": intent,
"language_code": LANGUAGE_CODE,
"update_mask": update_mask})
print(response)
代码解读
4.7 训练 agent
训练 agent:
response = agent_client.train_agent(request={"parent": my_agent.parent})
print('Training operation name:', response.operation.name)
try:
response.result(timeout=120)
except ValueError:
print("Operation timed out.")
代码解读
4.8 设置 fallback action
如果找不到相应的回复,可以使用 fallback action 设置默认回复:
intent['default_response_platforms'].append('PLATFORM_UNSPECIFIED')
intent['fallback_intent'] = True
update_mask = {"paths": ['default_response_platforms', 'fallback_intent']}
response = intent_client.update_intent(request={"intent": intent,
"language_code": LANGUAGE_CODE,
"update_mask": update_mask})
print(response)
代码解读
4.9 设置 context
Context 作为一种工具,在对话流程中被用来存储与管理状态信息。它能够被用来传递状态数据于多个对话节点之间,并且能够在后续对话过程中恢复之前所保存的状态信息。
这里,我们可以设置初始 context,并在后续对话中维护其状态:
contexts_client = dialogflow.ContextsClient()
context = {"name": f"{session}/contexts/__system_counters__",
"lifespan_count": -1,
"parameters": {"no-input-counter": 0}}
response = contexts_client.create_context(request={"parent": my_agent.parent,
"context": context})
print(response)
代码解读
4.10 获取对话结果
当一条消息被发送时,Dialogflow会响应,并生成相应的回复内容。在对话结束后, 获取最终回复内容及原始输入信息。
text_inputs = dialogflow.types.TextInput(text='hello', language_code=LANGUAGE_CODE)
query_input = dialogflow.types.QueryInput(text=text_inputs)
response = session_client.detect_intent(request={"session": session,
"query_input": query_input,
"output_audio_config": output_audio_config})
print(response)
代码解读
4.11 实践
接下来我们将运用 Dialogflow 技术平台来开发一个简单的 Chatbot 应用。该 Chatbot 具备完整的对话功能,并能够处理来自用户的文字消息。同时能够响应用户的消息输入,并支持接收音频文件作为输入。
接下来我们将运用 Dialogflow 技术平台来开发一个简单的 Chatbot 应用。该 Chatbot 具备完整的对话功能,并能够处理来自用户的文字消息。同时能够响应用户的消息输入,并支持接收音频文件作为输入。
4.11.1 安装依赖包
为了达成该聊天机器人的开发目标, 我们需要先安装必要的依赖库. 此智能对话系统可以通过pip命令进行部署.
pip install flask requests pydub simpleaudio pyyaml
代码解读
- Flask:这是一个用Python编写的高效轻量级web框架,并且它主要用于提供HTTP服务。
- Requests:这是一个主要功能是发送HTTP请求的Python库,并且它主要用于从Dialogflow接口接收响应数据。
- Pydub:这是一段专注于音频处理的Python代码,并且它主要用于对音频文件进行转码处理和转换。
- Simpleaudio:这是一段Python代码,并且它专门用于在运行时直接播放audio文件。
- PyYAML:这是一段用来解析YAML格式数据的Python模块,并且它主要用于读取并解析配置文件中的数据信息及其结构关系等信息。
4.11.2 配置环境变量
为了能够正确的运行脚本,需要先配置一些环境变量:
import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "./dialogflow-keys.json" # 你的密钥文件的路径
os.environ["DIALOGFLOW_PROJECT_ID"] = "your-project-id" # 你的 Dialogflow 项目 ID
os.environ["DIALOGFLOW_LANGUAGE_CODE"] = "zh-CN" # 语言代码
代码解读
4.11.3 初始化 Dialogflow client
通过调用 google.cloud 和 requests 等库来实现与Dialogflow的交互。由于Dialogflow无需身份验证的需求,因此无需向其提供任何认证信息。仅需指定我们的项目ID即可完成操作。
import os
import requests
import json
project_id = os.getenv("DIALOGFLOW_PROJECT_ID")
language_code = os.getenv("DIALOGFLOW_LANGUAGE_CODE")
def call_dialogflow_api(message):
url = "https://dialogflow.googleapis.com/v2beta1/projects/{}/agent/sessions/{}".format(project_id, session_id)
headers = {
"Content-Type": "application/json; charset=utf-8",
"Authorization": "Bearer {}".format(access_token),
}
data = {
"queryResult": {
"queryText": message,
"languageCode": language_code,
"action": "input.unknown"
},
"originalDetectIntentRequest": {}
}
try:
response = requests.post(url, headers=headers, data=json.dumps(data))
return json.loads(response.content)
except Exception as e:
print(str(e))
return None
代码解读
4.11.4 创建 Flask app
我们基于 Flask 创建了一个 HTTP 服务,并将消息传输至 Dialogflow。该服务通过配置为响应消息传输的方式运行。其中的 / 路由映射用于响应来自用户的消息请求,“/audio”的路由则用于接收并处理用户上传的音频文件。
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
message = request.args.get('q')
if not message:
return ''
result = call_dialogflow_api(message)
if result and 'fulfillmentText' in result.get('payload'):
answer = result['payload']['fulfillmentText']
else:
answer = "对不起,我不太明白您的意思。"
return answer
@app.route('/audio', methods=['POST'])
def audio():
with open("./example.wav", "wb+") as fp:
fp.write(request.stream.read())
text = speech_to_text("example.wav")
result = call_dialogflow_api(text)
if result and 'fulfillmentText' in result.get('payload'):
answer = result['payload']['fulfillmentText']
else:
answer = "对不起,我不太明白您的意思。"
play_mp3_file("answer.mp3")
return "", 204
代码解读
4.11.5 启动 Flask app
if __name__ == '__main__':
app.run(debug=True)
代码解读
