import jieba
import pandas as pd
# 尝试打开停用词文件并读取内容
try:
with open('stopwords.txt', 'r', encoding='utf-8') as f:
stop_words = {line.strip() for line in f}
except FileNotFoundError:
print('停用词文件不存在,将创建文件并写入默认停用词表。')
# 如果停用词文件不存在,创建新文件并写入默认的停用词表
stop_words = {'的', '了', '着', '在', '是', '我', '你', '他', '她', '我们', '你们', '他们', '她们', '它', '它们', '这',
'那', '这个', '那个', '一些', '些许', '有些', '能够', '可以', '可能', '应该', '必须', '需要', '……'}
with open('stopwords.txt', 'w', encoding='utf-8') as f:
for word in stop_words:
f.write(word + '\n')
# 尝试打开Excel文件并读取问题和答案
try:
qa_df = pd.read_excel('data.xlsx', header=None)
qa_pairs = list(zip(qa_df[0], qa_df[1]))
except pd.errors.EmptyDataError:
print('数据文件为空,请添加数据!')
qa_pairs = []
except FileNotFoundError:
print('数据文件不存在,将创建一个新的数据文件。')
qa_pairs = []
# 创建一个新的Excel文件并写入默认问题和答案
qa_df = pd.DataFrame({'问题': ['请问有什么可以帮助您的吗?'], '答案': ['暂时我还不知道怎样回答你']})
qa_df.to_excel('data.xlsx', index=False, header=True)
# 如果Excel表格中没有数据,添加默认问题和答案
if not qa_pairs:
qa_pairs.append(('请问有什么可以帮助您的吗?', '暂时我还不知道怎样回答你'))
# 从问题答案列表中获取所有问题,不包括第一行
questions = [pair[0] for i, pair in enumerate(qa_pairs) if i != 0]
# 从问题答案列表中获取所有答案,不包括第一行
answers = [pair[1] for i, pair in enumerate(qa_pairs) if i != 0]
# 初始化首次进入对话循环的标志
first_time = True
# 进入对话循环
while True:
# 获取用户输入
user_input = input('你好,请问有什么可以帮助你的吗?\n' if first_time else '')
# 更新首次进入对话循环的标志
first_time = False
# 初始化最大相似度和最相似的问题编号
max_similarity, max_index = 0, 0
# 遍历所有问题,计算用户输入与每个问题之间的 Jaccard 相似度
for i in range(len(questions)):
# 分词,使用中文精确分词模式,并去除停用词
question_words = set(jieba.lcut(questions[i].lower())) - stop_words
# 如果问题中只有停用词,则跳过
if not question_words:
continue
# 分词,使用中文精确分词模式,并去除停用词
user_words = set(jieba.lcut(user_input.lower())) - stop_words
# 如果用户输入中只有停用词,则跳过
if not user_words:
continue
# 计算 Jaccard 系数的分子和分母
numerator = len(user_words & question_words)
denominator = len(user_words | question_words)
similarity = numerator / denominator
# 如果相似度大于最大相似度,则更新最大相似度和最相似的问题编号
if similarity > max_similarity:
max_similarity = similarity
max_index = i
# 判断最大相似度是否大于指定阈值,如果大于则输出对应的答案;否则输出最接近的5个问题
similar_questions = []
for i in range(len(questions)):
# 分词,使用中文精确分词模式,并去除停用词
question_words = set(jieba.lcut(questions[i].lower())) - stop_words
# 如果问题中只有停用词,则跳过
if not question_words:
continue
# 分词,使用中文精确分词模式,并去除停用词
user_words = set(jieba.lcut(user_input.lower())) - stop_words
# 如果用户输入中只有停用词,则跳过
if not user_words:
continue
# 计算 Jaccard 系数的分子和分母
numerator = len(user_words & question_words)
denominator = len(user_words | question_words)
similarity = numerator / denominator
if similarity > 0:
similar_questions.append((similarity, i))
similar_questions = sorted(similar_questions, key=lambda x: x[0], reverse=True)
if max_similarity >= 0.5:
print(answers[max_index])
else:
if len(similar_questions) == 0:
print(f'抱歉,我不太理解你的问题,请重新表述您的问题。')
else:
top_5 = similar_questions[:5]
full_response = f"抱歉,我不太理解你的问题,以下是最接近的5个问题:\n\n"
for i, q in enumerate(top_5):
full_response += f"{i + 1}. {questions[q[1]]}\n"
full_response += "\n请输入所选问题的序号进行提问:"
print(full_response)
# 获取用户输入的序号,如果不是数字或者超出范围,输出错误提示
while True:
try:
choice = int(input())
if choice < 1 or choice > len(top_5):
print('请输入有效的序号!请重新输入:')
continue
break
except ValueError:
print('请输入数字!请重新输入:')
# 根据用户选择输出相应问题
print(f"您选择了问题'{questions[top_5[choice - 1][1]]},{answers[top_5[choice - 1][1]]}' 请继续提问:")
一、介绍
本代码实现一个基于 Jaccard 相似度的简易聊天机器人,旨在提供一个基础的思路和框架,为希望学习和实践聊天机器人的新手提供参考和学习资料。
二、使用的库
代码使用了 jieba 和 pandas 两个库:jieba 分词库用于将中文文本转换成有意义的词语,pandas 库用于数据处理和分析。
三、代码实现过程(按部分解释)
- 读取数据:代码首先尝试打开一个名为 data.xlsx 的 Excel 文件,并将其中的问题和答案读取到内存中。如果文件不存在,代码会创建一个名为 data.xlsx 的新 Excel 文件,并将默认问题和答案写入其中。
- 处理用户输入:将每个问题进行分词,并计算与用户输入之间的 Jaccard 相似度,然后找到相似度最高的问题。如果相似度达到一定阈值,则输出对应的答案;否则,输出最接近的5个问题,让用户选择一个问题,进而获得答案。
- 输出最终答案:根据用户选择,输出相应的问题和答案,等待下一轮用户输入。
四、停用词
代码使用停用词表过滤一些无关紧要的词汇,从而提高匹配效率。
五、扩展功能
可以加入语义理解和对话记忆等功能来提升聊天机器人的交互性能和用户体验。
六、总结
本代码提供了一个基础的思路和框架,为希望学习和实践聊天机器人的新手提供了很好的参考和学习资料。同时,也提醒在实际使用过程中,还需要考虑数据安全和隐私保护等问题。