作者选择了COVID-19 救济基金来接受捐赠,作为Write for DOnations计划的一部分。
介绍
在有很多功能的情况下,与软件交互可能是一项艰巨的任务。在某些情况下,执行类似操作需要重复步骤,例如每次执行操作时导航菜单或填写表单。聊天机器人是一种虚拟助手,可帮助软件系统的用户访问信息或执行操作,而无需经过漫长的过程。这些助手中的许多都是对话式的,这提供了一种更自然的与系统交互的方式。
要创建对话式聊天机器人,您可以使用Dialogflow 等平台来帮助您在高层次上设计聊天机器人。或者,您可以使用spaCy 之类的库自己构建一个,它是一种快速且强大的基于 Python 的自然语言处理 (NLP) 库。spaCy 提供了有用的功能,例如确定单词在语句中所属的词性、查找两个语句在含义上的相似程度等。
在本教程中,您将创建一个聊天机器人,它不仅可以帮助用户简化与软件系统的交互,而且还足够智能,可以用自然语言(本教程中的美式英语)与用户进行交流。聊天机器人将使用OpenWeather API告诉用户世界上任何一个城市的当前天气情况,但您可以实现聊天机器人以使用另一个 API 处理用例。
先决条件
在开始之前,您将需要以下内容:
- 安装了 Python 3 并设置了编程环境。您可以使用如何安装 Python 3 和设置本地编程环境教程之一为您的机器完成此操作。
- OpenWeather 的 API 密钥。访问OpenWeather 网站以创建一个帐户。请务必确认您的电子邮件地址。注册成功后,访问API 密钥页面,查看自动为您的账户创建的 API 密钥。此键应为字母数字字符序列。
本教程假设您已经熟悉Python — 如果您想提高对 Python 的了解,请查看我们的How To Code in Python 3系列。本教程不需要自然语言处理的先见之明。
第 1 步 – 设置您的环境
在这一步中,您将安装spaCy
帮助您的聊天机器人理解用户句子的库。
按照先决条件设置 Python 后,您将拥有一个虚拟环境。让我们激活那个环境。
确保您位于设置环境的目录中,然后运行以下命令:
- source my_env/bin/activate
现在安装 spaCy:
- pip install -U spacy
最后,您将下载一个语言模型。spaCy 的语言模型是经过预训练的 NLP 模型,可用于处理语句以提取含义。您将使用英语语言模型,因此您将下载该模型。
运行以下命令:
- python -m spacy download en_core_web_md
如果您遇到如下错误:
OutputERROR: Failed building wheel for en-core-web-md
您需要安装wheel
:
- pip install -U wheel
然后再次下载英文模型。
要确认您已正确安装 spaCy,请打开 Python 解释器:
- python
接下来,导入 spaCy 并加载英语模型:
>>> import spacy
>>> nlp = spacy.load("en_core_web_md")
如果这两个语句执行时没有任何错误,那么您已经安装了 spaCy。
现在关闭 Python 解释器:
>>> exit()
您现在拥有开始使用聊天机器人所需的一切。在下一部分中,您将创建一个脚本来查询 OpenWeather API 以获取城市的当前天气。
第 2 步 — 创建城市天气计划
在本节中,您将创建一个脚本,该脚本接受来自用户的城市名称,查询 OpenWeather API 以获取该城市的当前天气,并显示响应。
首先,创建并打开一个weather_bot.py
用你喜欢的编辑器调用的 Python 文件:
- nano weather_bot.py
接下来,您将创建一个函数以从 OpenWeather API 获取城市的当前天气。该函数将城市名称作为参数,并返回城市的天气描述。
将以下代码添加到您的weather_bot.py
文件中:
import requests
api_key = "your_api_key"
def get_weather(city_name):
api_url = "http://api.openweathermap.org/data/2.5/weather?q={}&appid={}".format(city_name, api_key)
response = requests.get(api_url)
response_dict = response.json()
weather = response_dict["weather"][0]["description"]
if response.status_code == 200:
return weather
else:
print('[!] HTTP {0} calling [{1}]'.format(response.status_code, api_url))
return None
首先,您导入requests
库,以便您能够使用和发出 HTTP 请求。确保替换your_api_key
为您自己的 API 密钥。下一行开始定义get_weather()
检索指定城市天气的函数。
在此函数中,您将构建 OpenWeather API 的 URL。此 URL 返回城市的天气信息(温度、天气描述、湿度等)并以 JSON 格式提供结果。之后,您向 API 端点发出 GET 请求,将结果存储在response
变量中,然后将响应转换为 Python字典以便于访问。
在下一行,您只将天气描述提取到一个weather
变量中,然后确保 API 响应的状态代码是200
(意味着请求没有问题)。最后,您返回天气描述。
如果请求有问题,状态码会打印到控制台,然后返回None
.
要测试脚本,请get_weather()
使用您选择的城市(例如伦敦)调用该函数并打印结果。在您的函数后面添加突出显示的代码:
import requests
def get_weather(city_name):
...
return weather
weather = get_weather("London")
print(weather)
保存并运行脚本:
- python weather_bot.py
您将收到如下结果:
Outputscattered clouds
成功完成后,您现在可以从脚本中删除最后两行。
打开它:
- nano weather_bot.py
然后删除文件末尾突出显示的两行:
import requests
def get_weather(city_name):
...
return weather
weather = get_weather("London")
print(weather)
保存并关闭文件。
您现在有一个返回特定城市的天气描述的函数。
在下一步中,您将创建一个聊天机器人,该机器人能够确定用户是否想要获取某个城市的当前天气,如果是,聊天机器人将使用该get_weather()
功能做出适当的响应。
第 3 步 – 创建聊天机器人
在前两个步骤中,您安装了 spaCy 并创建了一个用于获取特定城市天气的函数。现在,您将创建一个聊天机器人,使用weather_bot.py
脚本以自然语言与用户进行交互。
您将编写一个chatbot()
函数,将用户的语句与表示检查城市天气的语句进行比较。为了进行这种比较,您将使用 spaCysimilarity()
方法。该方法计算两个语句的语义相似度,即它们在含义上的相似程度。这将帮助您确定用户是否正在尝试查看天气。
首先,打开脚本:
- nano weather_bot.py
然后,导入 spaCy 并加载英语语言模型:
import spacy
import requests
nlp = spacy.load("en_core_web_md")
. . .
在get_weather()
文件中的函数之后,创建一个chatbot()
表示聊天机器人的函数,该函数将接受用户的陈述并返回响应。
按照您的定义,添加突出显示的代码,为您要比较的两个语句创建标记。标记是语句中不同的有意义的部分,如单词和标点符号。这对于允许 spaCy 计算语义相似度是必要的:
import spacy
. . .
def chatbot(statement):
weather = nlp("Current weather in a city")
statement = nlp(statement)
这里weather
和statement
变量包含 spaCy 标记,作为将每个相应的字符串传递给nlp()
函数的结果。
保存并关闭您的文件。
接下来,您将在函数中引入 spaCysimilarity()
方法chatbot()
。该similarity()
方法将两个语句的语义相似度计算为0
和之间的值1
,其中数字越大表示相似度越大。您需要指定相似度必须具有的最小值,以确保用户想要查看天气。
例如,如果您检查语句 2 和 3 与以下语句 1 的相似性,您将得到:
- 一个城市的当前天气
- 伦敦的天气如何?(相似度 = 0.86)
- 花生酱和果冻(相似度 = 0.31)
要自己尝试,请打开 Python 解释器:
- python
接下来,导入 spaCy 并加载英语模型:
>>> import spacy
>>> nlp = spacy.load("en_core_web_md")
现在让我们从语句 1 和 2 创建令牌:
>>> statement1 = nlp("Current weather in a city")
>>> statement2 = nlp("What is the weather in London?")
最后,让我们获得两个语句的语义相似度:
>>> print(statement1.similarity(statement2))
你会收到这样的结果:
Output0.8557684354027663
设置较低的最小值(例如 0.1)将导致聊天机器人通过将语句(如语句 3)视为与语句 1 类似的语句来误解用户,这是错误的。设置太高的最小值(如 0.9)将排除一些实际上与语句 1 类似的语句,例如语句 2。
为了本教程,我们将任意选择 0.75,但您可能希望在处理项目时测试不同的值。
让我们将此值添加到脚本中。首先,打开文件:
- nano weather_bot.py
然后添加以下突出显示的代码以引入最小值:
import spacy
. . .
def chatbot(statement):
weather = nlp("Current weather in a city")
statement = nlp(statement)
min_similarity = 0.75
现在检查用户陈述与天气陈述的相似度是否大于或等于您指定的最小相似度值。添加以下突出显示的if
语句来检查这一点:
import spacy
. . .
def chatbot(statement):
weather = nlp("Current weather in a city")
statement = nlp(statement)
min_similarity = 0.75
if weather.similarity(statement) >= min_similarity:
pass
最后一步是从用户的语句中提取城市,以便您可以将其传递给get_weather()
函数以从 API 调用中检索天气。添加以下突出显示的for
循环来实现这一点:
import spacy
...
def chatbot(statement):
weather = nlp("Current weather in a city")
statement = nlp(statement)
min_similarity = 0.75
if weather.similarity(statement) >= min_similarity:
for ent in statement.ents:
if ent.label_ == "GPE": # GeoPolitical Entity
city = ent.text
break
为此,您将使用 spaCy 的命名实体识别功能。一个命名实体是真实世界的名词,有一个名字,喜欢一个人,或在我们的情况下,一个城市。您想从用户的语句中提取城市名称。
要提取城市名称,您需要获取用户语句中的所有命名实体并检查其中哪个是地缘政治实体(国家、州、城市)。为此,您循环遍历 spaCy 从ents
属性中的语句中提取的所有实体,然后检查实体标签(或类)是否是代表地缘政治实体的“GPE”。如果是,则将实体的名称(其文本)保存在名为 的变量中city
。
您还需要通过添加else
块来捕获未输入城市的情况:
import spacy
...
def chatbot(statement):
weather = nlp("Current weather in a city")
statement = nlp(statement)
min_similarity = 0.75
if weather.similarity(statement) >= min_similarity:
for ent in statement.ents:
if ent.label_ == "GPE": # GeoPolitical Entity
city = ent.text
break
else:
return "You need to tell me a city to check."
现在你有了城市,你可以调用get_weather()
函数:
import spacy
...
def chatbot(statement):
weather = nlp("Current weather in a city")
statement = nlp(statement)
min_similarity = 0.75
if weather.similarity(statement) >= min_similarity:
for ent in statement.ents:
if ent.label_ == "GPE": # GeoPolitical Entity
city = ent.text
break
else:
return "You need to tell me a city to check."
city_weather = get_weather(city)
if city_weather is not None:
return "In " + city + ", the current weather is: " + city_weather
else:
return "Something went wrong."
else:
return "Sorry I don't understand that. Please rephrase your statement."
回想一下,如果 OpenWeather API 返回错误,您将错误代码打印到终端,然后get_weather()
函数返回None
. 在此代码中,您首先检查get_weather()
函数是否返回None
。如果没有,则返回城市的天气,但如果有,则返回一个字符串,表示出现问题。最后else
一块是处理用户语句的相似度值没有达到阈值的情况。在这种情况下,您要求用户重新表述他们的陈述。
完成所有这些之后,您现在拥有了一个聊天机器人,能够以对话的方式告诉用户一个城市的天气情况。此机器人与基于规则的聊天机器人之间的区别在于,用户不必每次都输入相同的语句。相反,他们可以用不同的方式表达他们的请求,甚至打错字,但由于 spaCy 的 NLP 功能,聊天机器人仍然能够理解他们。
让我们测试机器人。调用该chatbot()
函数并传入一条语句,询问城市的天气情况,例如:
import spacy
. . .
def chatbot(statement):
. . .
response = chatbot("Is it going to rain in Rome today?")
print(response)
保存并关闭文件,然后在终端中运行脚本:
- python3 weather_bot.py
您将收到类似于以下内容的输出:
OutputIn Rome, the current weather is: clear sky
您已成功创建了一个能够响应动态用户请求的智能聊天机器人。您可以尝试更多示例以发现机器人的全部功能。为此,您可以从 OpenWeather 和其他来源获取其他 API 端点。扩展聊天机器人的另一种方法是使其能够响应更多用户请求。为此,您可以将用户的陈述与多个选项进行比较,并找出语义相似度最高的选项。
结论
您已经创建了一个足够智能的聊天机器人来响应用户的陈述——即使用户以不同的方式表达他们的陈述。聊天机器人使用 OpenWeather API 获取用户指定城市的当前天气。
要进一步改进聊天机器人,您可以:
- 查看OpenWeather API 指南,了解您可以添加的其他天气功能。
- 访问spaCy 网站,查看您可以实施的其他功能,以使聊天机器人更加智能。
- 通过我们关于如何使用自然语言工具包 (NLTK) 在 Python 3 中处理语言数据的教程,提高您对自然语言处理的了解,或者在如何使用自然语言工具包 (NLTK) 在 Python 3 中执行情感分析中尝试情感分析。
您可以在这个DigitalOcean 存储库中找到本教程的最终代码。