[Python 原创] 从零开始构建简易AI问答C h a t G P T系统

[Python] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 导入需要用到的库
import requests
from bs4 import BeautifulSoup
import jieba
from gensim.models.word2vec import Word2Vec
import numpy as np
import pandas as pd
from sklearn.svm import SVC
from sklearn.metrics.pairwise import cosine_similarity
 
# 爬虫部分:爬取百度百科的网页内容,并进行数据清洗和预处理
def get_wiki_content(keyword):
    url = 'https://baike.baidu.com/item/' + keyword
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    content = soup.find_all(class_="para")
    content_list = []
    for para in content:
        para = para.get_text().strip()
        if para:
            content_list.append(para)
    full_content = ''.join(content_list)
    return full_content
 
# 分词和向量化部分:使用jieba对爬取的数据进行分词,然后使用Word2Vec模型将分词结果转化为词向量
class Word2VecVectorizer:
    def __init__(self):
        self.word2vec = None
 
    def fit(self, sentences):
        w2v = Word2Vec(sentences=sentences, size=256, min_count=5, workers=4)
        self.word2vec = dict(zip(w2v.wv.index2word, w2v.wv.vectors))
 
    def transform(self, sentences):
        vectors = []
        for sentence in sentences:
            sentence_vec = []
            for word in sentence:
                if word in self.word2vec:
                    sentence_vec.append(self.word2vec[word])
            if len(sentence_vec) > 0:
                sentence_vec = np.mean(sentence_vec, axis=0)
            else:
                sentence_vec = np.zeros(256)
            vectors.append(sentence_vec)
        return np.array(vectors)
 
# 机器学习部分:使用SVM算法对文本向量训练模型,并使用余弦相似度计算输入问题与已知问题的相似度
class QuestionAnswerSystem:
    def __init__(self):
        self.vectorizer = None
        self.clf = None
        self.question_vectors = None
        self.answer_vectors = None
        self.df = None
 
    def fit(self, questions, answers):
        self.vectorizer = Word2VecVectorizer()
        self.vectorizer.fit(questions)
        self.question_vectors = self.vectorizer.transform(questions)
        self.answer_vectors = self.vectorizer.transform(answers)
        self.clf = SVC(kernel='linear', probability=True)
        self.clf.fit(self.question_vectors, range(len(questions)))
 
    def ask(self, question, n=5):
        question = list(jieba.cut(question))
        question_vec = self.vectorizer.transform([question])[0]
        probas = self.clf.predict_proba([question_vec])[0]
        top_n = np.argsort(probas)[-n:]
        sims = cosine_similarity([question_vec], self.question_vectors[top_n])[0]
        best_match = np.argmax(sims)
        return self.df.iloc[top_n[best_match]]['answer']
 
# 主程序部分:调用以上函数完成问答系统的搭建
if __name__ == '__main__':
    # 爬取需要用到的数据
    wiki_content = get_wiki_content('会计')
    # 对数据进行预处理
    questions = ['什么是会计''什么是账户''什么是分录''什么是财务报表']
    answers = ['会计是什么''账户是什么''分录是什么''财务报表是什么']
    # 训练问答系统
    qas = QuestionAnswerSystem()
    qas.fit(questions, answers)
    qas.df = pd.DataFrame({'question': questions, 'answer': answers})
    # 进行测试
    while True:
        question = input('请输入你的问题:')
        if question == 'bye':
            break
        answer = qas.ask(question)
        print('答案为:', answer)


3.2 加入神经网络模型
   我们可以发现他只能回答一些基础的问题。然后我们在此基础上加入神经网络模型进一步完善它。于是我使用预训练的语言模型(如BERT)来对问题和答案进行编码,然后将编码后的结果输入到一个神经网络中进行分类。代码如下,其中使用Hugging Face库来加载BERT模型。

[Python] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
#  导入需要用到的库
import requests
from bs4 import BeautifulSoup
import jieba
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
import torch
from transformers import BertTokenizer, BertModel
from torch.utils.data import TensorDataset, DataLoader
import torch.nn.functional as F
 
# 爬虫部分:爬取百度百科的网页内容,并进行数据清洗和预处理
def get_wiki_content(keyword):
    url = 'https://baike.baidu.com/item/' + keyword
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    content = soup.find_all(class_="para")
    content_list = []
    for para in content:
        para = para.get_text().strip()
        if para:
            content_list.append(para)
    full_content = ''.join(content_list)
    return full_content
 
# 编码器部分:使用预训练的BERT模型来对文本进行编码
class BertEncoder:
    def __init__(self):
        self.tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
        self.model = BertModel.from_pretrained('bert-base-chinese')
        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
 
    def encode(self, sentence):
        input_ids = torch.tensor([self.tokenizer.encode(sentence, add_special_tokens=True)], dtype=torch.long).to(self.device)
        with torch.no_grad():
            outputs = self.model(input_ids)
            encoded = outputs[0][:, 0, :].cpu().numpy()
        return encoded
 
# 神经网络部分:使用全连接层对文本向量训练模型,并使用余弦相似度计算输入问题与已知问题的相似度
class QuestionAnswerSystem:
    def __init__(self):
        self.encoder = None
        self.clf = None
        self.question_vectors = None
        self.answer_vectors = None
        self.df = None
 
    def fit(self, questions, answers):
        self.encoder = BertEncoder()
        self.question_vectors = self.encoder.encode(questions)
        self.answer_vectors = self.encoder.encode(answers)
        self.clf = torch.nn.Sequential(torch.nn.Linear(768256),
                                        torch.nn.ReLU(),
                                        torch.nn.Linear(256len(questions)),
                                        torch.nn.Softmax())
        self.clf.to(self.encoder.device)
        train_data = TensorDataset(torch.tensor(self.answer_vectors, dtype=torch.float32), torch.tensor(range(len(questions)), dtype=torch.long))
        train_loader = DataLoader(train_data, batch_size=32)
        criterion = torch.nn.CrossEntropyLoss()
        optimizer = torch.optim.Adam(self.clf.parameters(), lr=1e-3)
        num_epochs = 5
        for epoch in range(num_epochs):
            for inputs, labels in train_loader:
                inputs, labels = inputs.to(self.encoder.device), labels.to(self.encoder.device)
                outputs = self.clf(inputs)
                loss = criterion(outputs, labels)
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
 
    def ask(self, question, n=5):
        question_vec = self.encoder.encode(question)
        inputs = torch.tensor(question_vec, dtype=torch.float32).to(self.encoder.device)
        outputs = self.clf(inputs)
        probas = F.softmax(outputs, dim=1).detach().cpu().numpy()[0]
        top_n = np.argsort(probas)[-n:]
        sims = cosine_similarity([question_vec], self.question_vectors[top_n])[0]
        best_match = np.argmax(sims)
        return self.df.iloc[top_n[best_match]]['answer']
 
# 主程序部分:调用以上函数完成问答系统的搭建
if __name__ == '__main__':
    # 爬取需要用到的数据
    wiki_content = get_wiki_content('会计')
    # 对数据进行预处理
    questions = ['什么是会计''什么是账户''什么是分录''什么是财务报表']
    answers = ['会计是什么''账户是什么''分录是什么''财务报表是什么']
    # 训练问答系统
    qas = QuestionAnswerSystem()
    qas.fit(questions, answers)
    qas.df = pd.DataFrame({'question': questions, 'answer': answers})
    # 进行测试
    while True:
        question = input('请输入你的问题:')
        if question == 'bye':
            break
        answer = qas.ask(question)
        print('答案为:', answer)


    我们利用BERT模型来对问题和答案进行编码,然后使用全连接层对编码后的文本向量进行分类。这样的神经网络效果较好,可以更准确地回答问题。但是,由于BERT模型比较复杂,因此训练和推断速度都比较慢,需要耐心等待。
 添加将训练结果保存到excel文件中的功能
   为了实现将训练结果保存到Excel文件中的功能,我们可以使用pandas库。在下面的代码中,我们对问答系统类(QuestionAnswerSystem)进行一些改进,添加了一个新的方法 save_result_to_excel。这个方法接受一个Excel文件名作为参数,并将问题和答案保存到该文件中。在方法中,我们将DataFrame类型的数据转换为Excel文件,并将其保存在指定的文件名中。下面是修改后的代码:

[Python] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
# 导入需要用到的库
import requests
from bs4 import BeautifulSoup
import jieba
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
import torch
from transformers import BertTokenizer, BertModel
from torch.utils.data import TensorDataset, DataLoader
import torch.nn.functional as F
 
# 爬虫部分:爬取百度百科的网页内容,并进行数据清洗和预处理
def get_wiki_content(keyword):
    url = 'https://baike.baidu.com/item/' + keyword
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    content = soup.find_all(class_="para")
    content_list = []
    for para in content:
        para = para.get_text().strip()
        if para:
            content_list.append(para)
    full_content = ''.join(content_list)
    return full_content
 
# 编码器部分:使用预训练的BERT模型来对文本进行编码
class BertEncoder:
    def __init__(self):
        self.tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
        self.model = BertModel.from_pretrained('bert-base-chinese')
        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
 
    def encode(self, sentence):
        input_ids = torch.tensor([self.tokenizer.encode(sentence, add_special_tokens=True)], dtype=torch.long).to(self.device)
        with torch.no_grad():
            outputs = self.model(input_ids)
            encoded = outputs[0][:, 0, :].cpu().numpy()
        return encoded
 
# 神经网络部分:使用全连接层对文本向量训练模型,并使用余弦相似度计算输入问题与已知问题的相似度
class QuestionAnswerSystem:
    def __init__(self):
        self.encoder = None
        self.clf = None
        self.question_vectors = None
        self.answer_vectors = None
        self.df = None
 
    def fit(self, questions, answers):
        self.encoder = BertEncoder()
        self.question_vectors = self.encoder.encode(questions)
        self.answer_vectors = self.encoder.encode(answers)
        self.clf = torch.nn.Sequential(torch.nn.Linear(768256),
                                        torch.nn.ReLU(),
                                        torch.nn.Linear(256len(questions)),
                                        torch.nn.Softmax())
        self.clf.to(self.encoder.device)
        train_data = TensorDataset(torch.tensor(self.answer_vectors, dtype=torch.float32), torch.tensor(range(len(questions)), dtype=torch.long))
        train_loader = DataLoader(train_data, batch_size=32)
        criterion = torch.nn.CrossEntropyLoss()
        optimizer = torch.optim.Adam(self.clf.parameters(), lr=1e-3)
        num_epochs = 5
        for epoch in range(num_epochs):
            for inputs, labels in train_loader:
                inputs, labels = inputs.to(self.encoder.device), labels.to(self.encoder.device)
                outputs = self.clf(inputs)
                loss = criterion(outputs, labels)
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
 
    def ask(self, question, n=5):
        question_vec = self.encoder.encode(question)
        inputs = torch.tensor(question_vec, dtype=torch.float32).to(self.encoder.device)
        outputs = self.clf(inputs)
        probas = F.softmax(outputs, dim=1).detach().cpu().numpy()[0]
        top_n = np.argsort(probas)[-n:]
        sims = cosine_similarity([question_vec], self.question_vectors[top_n])[0]
        best_match = np.argmax(sims)
        return self.df.iloc[top_n[best_match]]['answer']
 
    # 新增方法:将问答结果保存到Excel文件中
    def save_result_to_excel(self, filename='qa_result.xlsx'):
        df_result = self.df.copy()
        df_result.columns = ['Question''Answer']
        df_result.to_excel(filename, index=False)
 
# 主程序部分:调用以上函数完成问答系统的搭建
if __name__ == '__main__':
    # 爬取需要用到的数据
    wiki_content = get_wiki_content('会计')
    # 对数据进行预处理
    questions = ['什么是会计''什么是账户''什么是分录''什么是财务报表']
    answers = ['会计是什么''账户是什么''分录是什么''财务报表是什么']
    # 训练问答系统
    qas = QuestionAnswerSystem()
    qas.fit(questions, answers)
    qas.df = pd.DataFrame({'question': questions, 'answer': answers})
    # 将结果保存到Excel文件中
    qas.save_result_to_excel('qa_result.xlsx')
    # 进行测试
    while True:
        question = input('请输入你的问题:')
        if question == 'bye':
            break
        answer = qas.ask(question)
        print('答案为:', answer)


在主程序部分中,新增了一行代码 qas.save_result_to_excel('qa_result.xlsx'),将问答结果保存到Excel文件中。可以将文件名设置为自己喜欢的名称,并在文件保存位置执行该代码。执行完毕后,在指定的文件夹中会生成一个名为 qa_result.xlsx 的文件,其中包含了训练结果的问题和答案。
 想要更好的学习,我们需要对该程序在对话过程中就对数据进行数据标注和检验
   实现问答系统的数据标注和检验功能,我们需要对 QuestionAnswerSystem 进行一些改进。
   首先,为了方便用户对答案进行标注,我们需要在 ask 方法中添加一个新参数 is_correct,用于接收用户对答案是否正确的标注。我们还需要将问题、答案和标注组成的列表存储到 df 属性中,以便后续使用。
   其次,我们可以新增一个方法 check_accuracy,用于计算问答系统的准确率。该方法会基于已标注数据计算平均准确率,并将准确率打印出来。同时,我们也可以通过 save_result_to_excel 方法保存标注后的结果到Excel文件中。下面是修改后的代码:

[Python] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 导入需要用到的库
import requests  # 发送网络请求的模块
from bs4 import BeautifulSoup  # 从bs4模块中导入BeautifulSoup类,用于解析HTML文档
import jieba  # 中文分词库
import numpy as np  # 用于科学计算的库
import pandas as pd  # 用于数据处理和分析的库
from sklearn.metrics.pairwise import cosine_similarity  # 余弦相似度计算函数
import torch  # PyTorch深度学习框架
from transformers import BertTokenizer, BertModel  # 预训练的BERT模型和分词器
from torch.utils.data import TensorDataset, DataLoader  # 数据集和数据加载器
import torch.nn.functional as F  # 神经网络相关的函数和工具
 
# 爬虫部分:爬取百度百科的网页内容,并进行数据清洗和预处理
def get_wiki_content(keyword):
    url = 'https://baike.baidu.com/item/' + keyword  # 构造百度百科的URL链接
    response = requests.get(url)  # 发送GET请求并获取响应对象
    soup = BeautifulSoup(response.text, 'html.parser')  # 用html.parser解析HTML文档
    content = soup.find_all(class_="para")  # 查找class属性为"para"的标签
    content_list = []
    for para in content:
        para = para.get_text().strip()  # 获取标签中的文本内容
        if para: # 如果文本内容非空
            content_list.append(para)  # 将其添加到列表中
    full_content = ''.join(content_list)  # 将列表中的所有段落合并成一个完整的字符串
    return full_content  # 返回完整的百科内容
 
# 编码器部分:使用预训练的BERT模型来对文本进行编码
class BertEncoder:
    def __init__(self):
        self.tokenizer = BertTokenizer.from_pretrained('bert-base-chinese'# 调用BERT分词器
        self.model = BertModel.from_pretrained('bert-base-chinese')  # 调用BERT模型
        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  # 判断是否可用GPU
 
    def encode(self, sentence):  # 对句子进行编码
        input_ids = torch.tensor([self.tokenizer.encode(sentence, add_special_tokens=True)], dtype=torch.long).to(self.device)  # 将句子转换成ID序列,并放到GPU上
        with torch.no_grad(): # 关闭梯度计算,以节省内存和加速计算
            outputs = self.model(input_ids)  # 输入句子,得到BERT模型输出
            encoded = outputs[0][:, 0, :].cpu().numpy()  # 取第1个输出,取第1行,即CLS对应的向量,将其从GPU上取回并转换为NumPy数组
        return encoded
 
# 神经网络部分:使用全连接层对文本向量训练模型,并使用余弦相似度计算输入问题与已知问题的相似度
class QuestionAnswerSystem:
    def __init__(self):
        self.encoder = None
        self.clf = None
        self.question_vectors = None
        self.answer_vectors = None
        self.df = None  # 保存问答结果的DataFrame
 
    def fit(self, questions, answers): # 训练神经网络模型
        self.encoder = BertEncoder()  # 初始化编码器
        self.question_vectors = self.encoder.encode(questions)  # 编码所有问题
        self.answer_vectors = self.encoder.encode(answers)  # 编码所有答案
        self.clf = torch.nn.Sequential(torch.nn.Linear(768256), # 全连接层1,输入大小为768,输出大小为256
                                        torch.nn.ReLU(),  # ReLU激活函数
                                        torch.nn.Linear(256len(questions)),  # 全连接层2,输入大小为256,输出大小为问题数量
                                        torch.nn.Softmax()) # Softmax函数,用于分类
        self.clf.to(self.encoder.device)  # 将模型放到GPU上
        train_data = TensorDataset(torch.tensor(self.answer_vectors, dtype=torch.float32), torch.tensor(range(len(questions)), dtype=torch.long))  # 构造训练数据集
        train_loader = DataLoader(train_data, batch_size=32)  # 构造数据加载器,每次读取32个样本
        criterion = torch.nn.CrossEntropyLoss() # 定义损失函数为交叉熵
        optimizer = torch.optim.Adam(self.clf.parameters(), lr=1e-3)  # 使用Adam优化器,并设置学习率为0.001
        num_epochs = 5  # 训练轮数为5轮
        for epoch in range(num_epochs):  # 进行多轮训练
            for inputs, labels in train_loader: # 按批次读取数据
                inputs, labels = inputs.to(self.encoder.device), labels.to(self.encoder.device)  # 将数据放到GPU上
                outputs = self.clf(inputs) # 输入数据,得到模型输出结果
                loss = criterion(outputs, labels) # 计算损失值
                optimizer.zero_grad() # 将梯度清零,以免累加影响下一次更新
                loss.backward()  # 反向传播计算梯度
                optimizer.step() # 更新权重
 
    def ask(self, question, n=5, is_correct=None): # 回答问题
        question_vec = self.encoder.encode(question)  # 对输入问题进行编码
        inputs = torch.tensor(question_vec, dtype=torch.float32).to(self.encoder.device)  # 将编码后的问题放到GPU上
        outputs = self.clf(inputs)  # 输入问题向量,得到模型输出结果
        probas = F.softmax(outputs, dim=1).detach().cpu().numpy()[0]  # 对输出结果进行softmax处理,并将其从GPU上取回并转换为NumPy数组
        top_n = np.argsort(probas)[-n:]  # 取最大的n个概率对应的下标
        sims = cosine_similarity([question_vec], self.question_vectors[top_n])[0]  # 计算输入问题与已知问题的相似度
        best_match = np.argmax(sims)  # 找到最相似的问题
        if is_correct is not None:   # 如果需要记录问答结果
            self.df = self.df.append({'question': question, 'answer'self.df.iloc[top_n[best_match]]['answer'], 'is_correct'bool(is_correct)}, ignore_index=True)  # 将记录添加到DataFrame中
        return self.df.iloc[top_n[best_match]]['answer']  # 返回最匹配的答案
 
    # 新增方法:将问答结果保存到Excel文件中
    def save_result_to_excel(self, filename='qa_result.xlsx'):
        df_result = self.df.copy() # 复制一份问答结果
        df_result.columns = ['Question''Answer''Is Correct']  # 重命名列名
        df_result.to_excel(filename, index=False)  # 将结果保存到Excel文件中,不保存索引
 
    # 新增方法:检验问答系统的准确率
    def check_accuracy(self):
        accuracy = self.df['is_correct'].mean() # 计算平均准确率
        print('问答系统的准确率为: {:.2f}%'.format(accuracy*100))  # 输出准确率
 
# 主程序部分:调用以上函数完成问答系统的搭建
if __name__ == '__main__':
    # 爬取需要用到的数据
    wiki_content = get_wiki_content('会计')
    # 对数据进行预处理
    questions = ['什么是会计''什么是账户''什么是分录''什么是财务报表']
    answers = ['会计是什么''账户是什么''分录是什么''财务报表是什么']
    # 训练问答系统
    qas = QuestionAnswerSystem()
    qas.fit(questions, answers)
    qas.df = pd.DataFrame({'question': questions, 'answer': answers})
    # 进行测试
    while True:
        question = input('请输入你的问题:')
        if question == 'bye':
            break
        is_correct = input('答案是否正确?(y/n)')
        if is_correct.lower() == 'y':
            is_correct = True
        elif is_correct.lower() == 'n':
            is_correct = False
        else:
            is_correct = None
        answer = qas.ask(question, is_correct=is_correct)
        print('答案为:', answer['answer'])
    # 检验准确率并保存标注后的数据到Excel文件中
    qas.check_accuracy()
    qas.save_result_to_excel('qa_result.xlsx')


    在主程序部分中,我们新增了两个输入提示,以便用户标注答案是否正确,同时也新增了两行代码来调用 check_accuracy 和 save_result_to_excel 方法,以检验问答系统的准确率,并将标注后的结果保存到Excel文件中。现在,当运行程序并回答每个问题时,程序会提示你输入答案是否正确,你可以输入 "y" 或 "n" 来对答案进行标注。程序会将问题、答案和标注组成的记录存储到 df 属性中,并在每次执行 ask 方法时更新 df。执行 check_accuracy 方法时,程序将基于已标注数据计算准确率,并将其打印出来。执行 save_result_to_excel 方法时,程序将标注后的数据写入到Excel文件中以便后续使用。到此为止,我们的程序的一些功能也就基本实现了。当然还存在许多的问题,希望大家可以一起学习,一起进步。
四、最后的最后
   为了更好的让他学习方便,于是最后增加一个适配的Webj界面。要将该程序适配为web界面,需要使用web框架来搭建一个网站,并将问答系统集成到网站中。可以使用Python中的Flask框架。以下是实现步骤:
1、导入Flask和其他需要用到的库:

[Python] 纯文本查看 复制代码
?
1
2
3
from flask import Flask, render_template, request
import pandas as pd
from qa_system import QuestionAnswerSystem


其中qa_system.py文件是之前所提到的问答系统代码。
2、创建Flask应用:

[Python] 纯文本查看 复制代码
?
1
app = Flask(__name__)


3、加载问答系统:

[Python] 纯文本查看 复制代码
?
1
2
3
qas = QuestionAnswerSystem()
qas.fit(questions, answers)
qas.df = pd.DataFrame({'question': questions, 'answer': answers})


其中,questions和answers是之前已经定义过的问题列表和答案列表。
4、创建路由函数:

[Python] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
@app.route('/', methods=['GET''POST'])
def index():
    if request.method == 'POST':
        question = request.form.get('question')
        is_correct = request.form.get('is_correct')
        if is_correct.lower() == 'y':
            is_correct = True
        elif is_correct.lower() == 'n':
            is_correct = False
        else:
            is_correct = None
        answer = qas.ask(question, is_correct=is_correct)
        return render_template('index.html', answer=answer['answer'])
    return render_template('index.html')


这个路由函数包含了两个请求方法:GET和POST。当用户访问网页时,会发送一个GET请求,会渲染index.html页面;当用户提交问题时,会发送一个POST请求,会通过问答系统获取答案,并将答案渲染到页面中。question和is_correct是从表单中获取的参数。
编写HTML模板:
  这里写了一个简单的模板作为参考,可以根据需求进行修改。

[HTML] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>问答系统</title>
</head>
<body>
    <form method="post">
        <input type="text" name="question" placeholder="请输入你的问题" required>
        <input type="radio" name="is_correct" value="y" required>
        <label for="y">正确</label>
        <input type="radio" name="is_correct" value="n" required>
        <label for="n">错误</label>
        <button type="submit">提交</button>
    </form>
    {% if answer %}
    <p>{{ answer }}</p >
    {% endif %}
</body>
</html>


这个模板包含了一个表单,用户可以在这里输入问题。表单中还包含了两个单选框,用户在回答问题后可以选择是否正确。如果问答系统能够成功获取到答案,就会将答案渲染到页面中。
运行Flask应用:

[Python] 纯文本查看 复制代码
?
1
2
if __name__ == '__main__':
    app.run()


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要用 Python 写一个前端页面,你需要使用 Python 的 Web 框架来构建 Web 应用。在这里,我会以 Flask 为例,介绍如何实现一个简单的问答系统。 首先,你需要安装 Flask: ``` pip install Flask ``` 然后,在你的项目目录下创建一个 `app.py` 文件,编写以下代码: ```python from flask import Flask, request, render_template app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': question = request.form['question'] # TODO: 调用问答系统获取答案 answer = '暂时无法回答该问题' return render_template('index.html', question=question, answer=answer) else: return render_template('index.html') if __name__ == '__main__': app.run() ``` 这段代码中定义了一个 `/` 路由,当用户访问首页时会显示一个表单,用户可以在表单中输入问题提交给服务器。在表单提交时,服务器会调用一个问答系统来获取答案,然后将答案显示在页面上。 接下来,你需要在项目目录下创建一个 `templates` 文件夹,在该文件夹下创建一个 `index.html` 文件,编写以下代码: ```html <!DOCTYPE html> <html> <head> <title>问答系统</title> </head> <body> <h1>问答系统</h1> <form method="post"> <input type="text" name="question" placeholder="请输入问题"> <button type="submit">提交</button> </form> {% if question %} <h2>问题:{{ question }}</h2> <h2>答案:{{ answer }}</h2> {% endif %} </body> </html> ``` 这段代码定义了一个包含一个文本框和一个提交按钮的表单,在用户提交表单后,会显示问题和答案。答案通过 Flask 的模板引擎来渲染,模板引擎使用的是 Jinja2,语法类似于 Django 的模板语言。 最后,你需要实现一个问答系统来获取答案。在这里,我会使用一个简单的规则引擎来实现问答系统代码如下: ```python import re rules = { '你好': '你好,我是问答机器人!', '你叫什么名字': '我叫问答机器人,很高兴为您服务!', '你多大了': '我已经很久没有过生日了,不知道算不算年龄...', '天气怎么样': '请问您在哪个城市?', } def get_answer(question): for key, value in rules.items(): if re.search(key, question): return value return '暂时无法回答该问题' ``` 这段代码定义了一个简单的规则引擎,根据问题匹配相应的答案。如果问题无法匹配任何规则,则返回一个默认的回答。 现在你可以运行应用程序,打开浏览器访问 http://localhost:5000,就可以看到一个简单的问答系统了!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大飞哥软件自习室

希望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值