对话机器人:使用 Python TensorFlow 训练 Chatbot 聊天机器人

这篇具有很好参考价值的文章主要介绍了对话机器人:使用 Python TensorFlow 训练 Chatbot 聊天机器人。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

1.简介

为了能够在Facebook Messenger上与用户进行实时的沟通,开发者需要自行构建聊天机器人。然而,构建聊天机器人的过程却很复杂,需要掌握众多的技术、技能和知识。本文通过详细地阐述了如何用Python语言构建一个Facebook Messenger聊天机器人,并分享一些创建聊天机器人的过程中可能遇到的问题,希望可以帮助读者更好地理解和应用聊天机器人技术。

2.技术选型及环境准备

Python编程语言

首先,需要安装Python编程语言。如果您还没有安装过Python,可以从https://www.python.org/downloads/下载安装包安装。本文使用Python 3版本。

技术栈

这里我们主要基于以下两个技术栈进行讨论:

  1. Natural Language Processing(NLP)
  2. Dialogflow API
Natural Language Processing(NLP)

自然语言处理(NLP)是指计算机从文本或语音中提取出有意义的信息的能力,也是信息搜索、分析和决策的基础。其涉及的技术领域包括分词、词性标注、命名实体识别、句法分析等。相关的工具和库包括 NLTK、SpaCy、TextBlob等。

Dialogflow API

Dialogflow是Google推出的开源对话系统,它可以通过API调用的方式跟业务人员进行聊天。其中,Dialogflow提供了一个用于构建聊天机器人的界面,方便非技术人员创建自己的对话模型,实现自动回复功能。

安装依赖库

本文中,我们将使用以下三个Python库来构建我们的聊天机器人:

  1. pip install nltk:NLTK是一个强大的自然语言处理库。
  2. pip install spacy:SpaCy是一个用于处理文本的高效NLP库。
  3. pip install dialogflow_fulfillment:dialogflow_fulfillment模块可以轻松地创建Dialogflow聊天机器人的Fullfilment响应函数,它会根据请求的内容进行自动回复。

构建环境

除了安装Python编程语言和依赖库外,还需创建一个虚拟环境。以下命令可创建一个名为“chatbot”的虚拟环境:

python -m venv chatbot

激活虚拟环境后,即可安装所需的第三方库:

cd chatbot
source bin/activate
pip install nltk spacy dialogflow_fulfillment

示例数据集

为了方便了解我们要建模的对话场景,我们可以使用一个开源的数据集——Stanford Question Answering Dataset(SQuAD)。该数据集包含超过50,000个提问-回答对,其中每个问题都与一段对应的答案相对应。SQuAD数据集适合于训练和测试聊天机器人的性能,可以让我们更加了解这个领域。

下载数据集后,解压到当前目录下:

wget https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json
wget https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json

3.数据预处理

数据概览

首先,加载并检查数据集中的第一个样本:

import json

with open('train-v1.1.json', 'r') as f:
    data = json.load(f)['data']
    
sample = data[0]
print(sample['title']) # print the title of the first sample
print(len(sample['paragraphs'])) # number of paragraphs in this sample

输出结果如下:

"Super_Bowl_50:_The_Final_Four_(2018)"
17

由数据集名称和第一个样本的标题可以看出,这是一份关于超级碗比赛的问答数据集。数据集中共含有17个不同的段落(paragraph),每一段包含若干个QA对。

paragraph = sample['paragraphs'][0]
print(paragraph['context']) # the context for this paragraph
for qa in paragraph['qas']:
    question = qa['question']
    answer_text = qa['answers'][0]['text']
    print("Q:", question)
    print("A:", answer_text)
    print()

输出结果如下:

In Super Bowl 50, France defeated United States and became the new champions with a score of 78-75. The American team achieved this by holding on to their lead after being beaten during the opening game. However, they were not able to replicate that success when facing off against the Italian side at Wimbledon, where they lost three straight games. With only seven minutes left before the match ended, it is clear that there is still much work to be done for the French side.

Q: When did the American players gain control of the ball?
A: After the two minute violation, it was down to Aaron Ball himself who moved the ball from the hands of <NAME> to his feet. 

Q: How many points did the United States lose?
A: Two scores out of five allowed them to hold onto the winning start and keep playing the last minute. They eventually won over the Italians and beat them 75-78. 

... more QA pairs...

注意到,每一QA对的前面都有一个“Q:”,后面跟着的问题,然后有一个“A:”,最后才是相应的答案。每个段落的上下文都用一个长字符串表示。

预处理步骤

数据预处理通常包含以下几个步骤:

  1. 分词:将文档切分成词组。
  2. 词形还原:将所有词汇转换为标准形式,例如将动词“play”还原为现在时态。
  3. 词性标注:给每个词赋予一个词性标签,如名词、动词、副词等。
  4. 命名实体识别:识别出文档中的人名、地名、机构名等专有名词。
  5. 句法分析:对文本中的词句结构进行分析,分析语法关系和语义。

在本文中,由于NLTK提供了相当全面的分词功能,所以不再重复。但是,由于SpaCy可以进行更多的处理,所以我们使用SpaCy代替NLTK进行预处理。另外,我们将使用spaCy中的命名实体识别器(NER)来识别问题、实体和答案中的专有名词。因此,需要安装并导入以下模块:

import os
from collections import defaultdict
import json
import random

import numpy as np
import tensorflow as tf

import spacy
from spacy.lang.en import English
from spacy.tokenizer import Tokenizer

nlp = English()
ner = nlp.create_pipe("ner")
nlp.add_pipe(ner)

接下来,定义一个函数来读取数据集并进行预处理:

def read_data(filename):
    """Read JSON file and process into list of examples"""
    
    data = []
    with open(filename, "r") as f:
        dataset = json.load(f)["data"]
        for article in dataset:
            for paragraph in article["paragraphs"]:
                context = paragraph["context"].lower().strip()
                
                doc = nlp(context)
                
                entities = [(ent.text, ent.label_) for ent in doc.ents if len(ent)>1]

                qas = paragraph["qas"]
                
                for qa in qas:
                    id_ = qa["id"]
                    
                    question = qa["question"].lower().strip()

                    ans = qa["answers"][0]["text"].lower().strip()

                    example = {"id": id_,
                               "context": context,
                               "entities": entities,
                               "question": question,
                               "answer": ans}

                    data.append(example)

    return data

此处,我们先将所有文字转化为小写并删除空白符,然后用spaCy对文档进行解析。我们只保留那些长度超过1的实体(即专有名词),并将它们存储在“entities”列表里。我们还对问题和答案也做同样的处理。

接下来,我们需要定义实体分类器(entity classifier)来区分这些专有名词。我们使用TensorFlow来训练一个简单卷积神经网络(CNN),用来判断输入文本是否包含某个实体类型。我们把它保存在一个JSON文件里,这样就可以直接加载它来进行预测了。

模型构建

接下来,我们将定义一个模型,用来训练和预测。

数据准备

首先,读取数据集并进行预处理:

train_data = read_data('train-v1.1.json')
dev_data = read_data('dev-v1.1.json')

接下来,我们随机打乱数据集:

random.shuffle(train_data)

然后,我们将数据集划分为训练集和验证集:

split_idx = int(len(train_data)*0.9)
train_set = train_data[:split_idx]
dev_set = train_data[split_idx:]
情感分析

在训练之前,我们还需要定义情感分析模型,用来将问题和答案的情感标签标注出来。比如,“你真棒!”和“恭喜你获得奖励”的情感标签应该是正向的,而“你不是好人”和“我很生气”的情感标签应该是负向的。

我们将使用TextBlob库来实现情感分析模型:

from textblob import TextBlob

polarity_tags = {'pos': 1, 'neg': -1, 'neu': 0}

def analyze_sentiment(sentence):
    blob = TextBlob(sentence).sentiment.polarity
    tag = polarity_tags[blob.classification]
    intensity = abs(blob.polsby_popper())
    return tag*intensity

对于每个语句,我们通过TextBlob的sentiment方法计算其情感得分,并且根据得分的分类结果确定它的情感标签。我们还计算了每条语句的Polsby-Popper指数,该指数衡量了一个句子的复杂程度,用于调整语句的情感得分。

生成器

我们将使用生成器(generator)函数来为训练集生成批次数据。生成器接收训练集作为输入,生成训练样本的一个批量。

def generate_batch(data, batch_size=32):
    while True:
        batches = [data[i: i+batch_size] for i in range(0, len(data), batch_size)]
        
        for batch in batches:
            
            context_arr = []
            entity_arr = []
            question_arr = []
            answer_arr = []

            sentiment_arr = []

            for example in batch:
                context_arr.append(example['context'])

                e_spans = [[span.start, span.end, label] for label, span in zip([ent[1] for ent in example['entities']],
                                                                                 [doc.char_span(*ent[:2]) for doc, ent in zip([nlp(c) for c in example['contexts']],
                                                                                                             example['entities'])])]
                
                e_labels = [' '.join([str(l) for l in labels]) for _, _, labels in e_spans]
                
                entity_arr.append([''.join([(t if i==j else '') for j, t in enumerate(e)]) for i, e in enumerate(e_labels)])

                question_arr.append(example['question'])
                answer_arr.append(example['answer'])

                sentiment_arr.append(analyze_sentiment(example['question']))
                sentiment_arr.append(analyze_sentiment(example['answer']))

            yield ({'context': context_arr,
                    'entities': entity_arr},
                   {'answer_output': answer_arr})

生成器返回的是一个元组,包含两个字典:一个包含问题、实体和上下文信息的字典,另一个包含答案的字典。

编码器

接下来,我们将定义编码器(encoder)函数。编码器函数接收训练样本的输入,对它们进行编码,并将它们作为模型的输入。

class Encoder(tf.keras.Model):
    def __init__(self, vocab_size, embedding_dim, max_length, num_filters, filter_sizes):
        super(Encoder, self).__init__()

        self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length)

        self.convs = tf.keras.layers.TimeDistributed(tf.keras.layers.Conv2D(num_filters, kernel_size=(filter_size, embedding_dim)))

        self.flatten = tf.keras.layers.Flatten()
        
    def call(self, inputs):
        x = self.embedding(inputs)
        x = tf.expand_dims(x, axis=-1)
        x = self.convs(x)
        x = self.flatten(x)
        return x

编码器采用嵌入层将词汇映射到低维空间,并将每个单词表示成固定大小的时间序列,再用多个卷积核进行特征抽取。最后,我们将每个时间步的特征拼接起来,得到整个文档的整体表示。

实体分类器

实体分类器(entity classifier)函数接受文档表示作为输入,输出每种类型的实体的概率分布。

class EntityClassifier(tf.keras.Model):
    def __init__(self, num_classes):
        super(EntityClassifier, self).__init__()

        self.dense1 = tf.keras.layers.Dense(256, activation='relu')
        self.dropout1 = tf.keras.layers.Dropout(0.5)
        self.dense2 = tf.keras.layers.Dense(num_classes, activation='softmax')

    def call(self, inputs):
        x = self.dense1(inputs)
        x = self.dropout1(x)
        output = self.dense2(x)
        return output

实体分类器采用一个两层神经网络,第一层神经元数量为256,第二层神经元数量为实体类别个数,输出每个实体的概率分布。

模型构建

最后,我们将构造整个模型:

class ChatBot(tf.keras.Model):
    def __init__(self, encoder, entity_classifier, max_length, max_entities):
        super(ChatBot, self).__init__()

        self.encoder = encoder
        self.entity_classifier = entity_classifier

        self.max_length = max_length
        self.max_entities = max_entities
        
    @staticmethod
    def _pad_sequences(sequence_list, max_length):
        sequence_lengths = [len(seq) for seq in sequence_list]
        padded_seqs = pad_sequences(sequence_list, padding='post', maxlen=max_length)
        return padded_seqs, sequence_lengths
    
    def call(self, inputs):
        contexts, entities = inputs

        context_padded, context_lengths = self._pad_sequences(contexts, self.max_length)
        entity_padded, entity_lengths = self._pad_sequences([[""]] * len(contexts), self.max_entities)
        
        encoded_docs = self.encoder(context_padded)

        entity_vectors = tf.reduce_sum(encoded_docs[:, :, None,:] * 
                                        self.entity_classifier.embedding(np.array(entities)),
                                        axis=2) / np.sqrt(self.encoder.embedding_dim)

        entity_logits = self.entity_classifier(entity_vectors)

        outputs = {
            "entity_logits": entity_logits,
            "context_lengths": context_lengths,
            "entity_lengths": entity_lengths
        }

        return outputs

模型由三部分组成:编码器、实体分类器和ChatBot主体。编码器和实体分类器分别对输入数据进行编码和分类。

ChatBot主体函数的作用是在已编码的文档和实体向量上进行实体分类。它还将原始数据进行padding,保证输入数据具有相同长度。

创建模型对象

最后一步,我们将创建一个模型对象,传入配置参数,并编译它。

model = ChatBot(encoder=Encoder(vocab_size=len(nlp.vocab)+1, embedding_dim=300, max_length=100,
                                num_filters=100, filter_sizes=[3]),
                entity_classifier=EntityClassifier(num_classes=len(set(entity_types))),
                max_length=100,
                max_entities=20)

optimizer = tf.keras.optimizers.Adam()

loss_fn = tf.keras.losses.CategoricalCrossentropy()

metrics = {'accuracy'}

model.compile(optimizer=optimizer,
              loss={'answer_output': loss_fn},
              metrics=metrics)

模型对象是一个Keras模型,包含Encoder、实体分类器和ChatBot主体。我们设定了损失函数和优化器。文章来源地址https://www.toymoban.com/news/detail-714887.html

到了这里,关于对话机器人:使用 Python TensorFlow 训练 Chatbot 聊天机器人的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 搭建一个AI对话机器人——前端ChatUI使用纪录

    最近在使用 OpenAI 的 gpt api 搞着玩玩,然后就遇上了前端对话交互实现的需求场景,如何快速实现 CUI(Chat User Interface)成了问题。最后选择了来自阿里达摩院的ChatUI,本人便用于整理其使用经验。 服务于对话领域的设计和开发体系,助力智能对话机器人的搭建。——ChatUI 聊

    2024年02月07日
    浏览(43)
  • 使用langchain与你自己的数据对话(五):聊天机器人

    之前我已经完成了使用langchain与你自己的数据对话的前四篇博客,还没有阅读这四篇博客的朋友可以先阅读一下: 使用langchain与你自己的数据对话(一):文档加载与切割 使用langchain与你自己的数据对话(二):向量存储与嵌入 使用langchain与你自己的数据对话(三):检索(Retrieva

    2024年02月13日
    浏览(36)
  • Elasticsearch:使用 LangChain 对话链和 OpenAI 的聊天机器人

    在此笔记本中,我们将构建一个聊天机器人,它可以回答有关自定义数据的问题,例如雇主的政策。 聊天机器人使用 LangChain 的 ConversationalRetrievalChain,具有以下功能: 用自然语言回答问题 在 Elasticsearch 中运行混合搜索以查找回答问题的文档 使用 OpenAI LLM 提取并总结答案 保

    2024年02月03日
    浏览(41)
  • LangChain入门(九)-使用Memory实现一个带记忆的对话机器人

    目录 一、说明 二、案例 一、说明 在第五章中我们使用的是通过自定义一个列表来存储对话的方式来保存历史的。 当然,你也可以使用自带的 memory 对象来实现这一点。 二、案例 结尾、扫一扫下方微信名片即可+博主徽信哦  ↓↓ ↓↓ ↓↓ ↓↓ ↓↓ ↓↓ ↓↓ ↓↓  ↓↓

    2024年02月16日
    浏览(38)
  • 强化学习:用Python训练一个简单的机器人

            强化学习(RL)是一个令人兴奋的研究领域,它使机器能够通过与环境的交互来学习。在这篇博客中,我们将深入到RL的世界,并探索如何使用Python训练一个简单的机器人。在本文结束时,您将对 RL 概念有基本的了解,并能够实现自己的 RL 代理。         设置

    2024年02月12日
    浏览(51)
  • 17行代码用python对接openai的api实现chatgpt微信对话机器人

    itchat python依赖下载 这里推荐这个。链接:衡天云

    2024年02月01日
    浏览(55)
  • 使用Langchain+GPT+向量数据库chromadb 来创建文档对话机器人

    使用Langchain+GPT+向量数据库chromadb 来创建文档对话机器人 文件存放地址 参考: https://python.langchain.com/docs/use_cases/chatbots https://python.langchain.com/docs/integrations/vectorstores/chroma https://blog.csdn.net/v_JULY_v/article/details/131552592?ops_request_misc=%257B%2522request%255Fid%2522%253A%252216945020581680022659096

    2024年02月03日
    浏览(40)
  • 【对话机器人】开源机器人项目介绍

    目录 1. 闲聊机器人介绍 2. 青云客平台 3. 思知项目 闲聊机器人是一种基于人工智能和自然语言处理技术的智能对话系统,旨在模拟人类的语言交流能力,与用户进行自然、连贯的对话。闲聊机器人能够理解用户的问题或指令,通过分析和处理文本,生成符合语法和语义规则的

    2024年02月11日
    浏览(52)
  • 最新ChatGPT GPT-4 NLU实战之智能多轮对话机器人(附ipynb与python源码及视频)——开源DataWhale发布入门ChatGPT技术新手从0到1必备使用指南手册(七)

    智能多轮对话机器人 是一种可以自主进行多轮对话的机器人系统,具有高度的交互性和可用性。智能多轮对话机器人旨在通过模拟人类对话方法来实现与用户之间更加自然和有效的沟通。然而,由于自然语言的复杂性和多变性,使得该技术面临巨大的挑战。 当前,基于大预

    2024年02月12日
    浏览(55)
  • transformers生成式对话机器人

    生成式对话机器人是一种人工智能技术,它通过学习大量自然语言数据,模拟人类进行开放、连贯和创造性的对话。这种类型的对话系统并不局限于预定义的回答集,而是能够根据上下文动态生成新的回复内容。其核心组件和技术包括: 1、神经网络架构:现代生成式对话机

    2024年03月10日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包