如何使用 spaCy NLP 库在 Python 中创建智能聊天机器人

作者选择了COVID-19 救济基金来接受捐赠,作为Write for DOnations计划的一部分。

介绍

在有很多功能的情况下,与软件交互可能是一项艰巨的任务。在某些情况下,执行类似操作需要重复步骤,例如每次执行操作时导航菜单或填写表单。聊天机器人是一种虚拟助手,可帮助软件系统的用户访问信息或执行操作,而无需经过漫长的过程。这些助手中的许多都是对话式的,这提供了一种更自然的与系统交互的方式。

要创建对话式聊天机器人,您可以使用Dialogflow 等平台来帮助您在高层次上设计聊天机器人或者,您可以使用spaCy 之类的库自己构建一个,它是一种快速且强大的基于 Python 的自然语言处理 (NLP) 库。spaCy 提供了有用的功能,例如确定单词在语句中所属的词性、查找两个语句在含义上的相似程度等。

在本教程中,您将创建一个聊天机器人,它不仅可以帮助用户简化与软件系统的交互,而且还足够智能,可以用自然语言(本教程中的美式英语)与用户进行交流聊天机器人将使用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

如果您遇到如下错误:

Output
ERROR: 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文件中:

天气机器人.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()使用您选择的城市(例如伦敦)调用该函数并打印结果。在您的函数后面添加突出显示的代码:

~/weather_bot.py
import requests

def get_weather(city_name):

  ...

  return weather

weather = get_weather("London")
print(weather)

保存并运行脚本:

  • python weather_bot.py

您将收到如下结果:

Output
scattered clouds

成功完成后,您现在可以从脚本中删除最后两行。

打开它:

  • nano weather_bot.py

然后删除文件末尾突出显示的两行:

~/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 并加载英语语言模型:

~/weather_bot.py
import spacy
import requests

nlp = spacy.load("en_core_web_md")

. . .

get_weather()文件中函数之后,创建一个chatbot()表示聊天机器人函数,该函数将接受用户的陈述并返回响应。

按照您的定义,添加突出显示的代码,为您要比较的两个语句创建标记标记是语句中不同的有意义的部分,如单词和标点符号。这对于允许 spaCy 计算语义相似度是必要的:

~/weather_bot.py
import spacy

. . .

def chatbot(statement):
  weather = nlp("Current weather in a city")
  statement = nlp(statement)

这里weatherstatement变量包含 spaCy 标记,作为将每个相应的字符串传递给nlp()函数的结果。

保存并关闭您的文件。

接下来,您将在函数中引入 spaCysimilarity()方法chatbot()similarity()方法将两个语句的语义相似度计算为0之间的值1,其中数字越大表示相似度越大。您需要指定相似度必须具有的最小值,以确保用户想要查看天气。

例如,如果您检查语句 2 和 3 与以下语句 1 的相似性,您将得到:

  1. 一个城市的当前天气
  2. 伦敦的天气如何?(相似度 = 0.86)
  3. 花生酱和果冻(相似度 = 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))

你会收到这样的结果:

Output
0.8557684354027663

设置较低的最小值(例如 0.1)将导致聊天机器人通过将语句(如语句 3)视为与语句 1 类似的语句来误解用户,这是错误的。设置太高的最小值(如 0.9)将排除一些实际上与语句 1 类似的语句,例如语句 2。

为了本教程,我们将任意选择 0.75,但您可能希望在处理项目时测试不同的值。

让我们将此值添加到脚本中。首先,打开文件:

  • nano weather_bot.py

然后添加以下突出显示的代码以引入最小值:

~/weather_bot.py
import spacy

. . .

def chatbot(statement):
  weather = nlp("Current weather in a city")
  statement = nlp(statement)
  min_similarity = 0.75

现在检查用户陈述与天气陈述的相似度是否大于或等于您指定的最小相似度值。添加以下突出显示的if语句来检查这一点:

~/weather_bot.py
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循环来实现这一点:

~/weather_bot.py
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来捕获未输入城市的情况

~/weather_bot.py
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()函数:

~/weather_bot.py
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()函数并传入一条语句,询问城市的天气情况,例如:

~/weather_bot.py
import spacy

. . .

def chatbot(statement):

. . .

response = chatbot("Is it going to rain in Rome today?")
print(response)

保存并关闭文件,然后在终端中运行脚本:

  • python3 weather_bot.py

您将收到类似于以下内容的输出:

Output
In Rome, the current weather is: clear sky

您已成功创建了一个能够响应动态用户请求的智能聊天机器人。您可以尝试更多示例以发现机器人的全部功能。为此,您可以从 OpenWeather 和其他来源获取其他 API 端点。扩展聊天机器人的另一种方法是使其能够响应更多用户请求。为此,您可以将用户的陈述与多个选项进行比较,并找出语义相似度最高的选项。

结论

您已经创建了一个足够智能的聊天机器人来响应用户的陈述——即使用户以不同的方式表达他们的陈述。聊天机器人使用 OpenWeather API 获取用户指定城市的当前天气。

要进一步改进聊天机器人,您可以:

您可以在这个DigitalOcean 存储库中找到本教程的最终代码

觉得文章有用?

点个广告表达一下你的爱意吧 !😁