
大家好!今天咱们手把手教你做一个能 “学习” 的 Python 聊天机器人 —— 它不只是死板地回复,还能记住你教它的内容,下次聊天直接用!关键是咱们用 GPT-4 辅助写核心代码,再靠 JSON 文件存对话记忆,哪怕关了程序,之前教的东西也不会丢。
不管你是刚学 Python 的新手,还是想练手小项目的同学,跟着做都能学会文件操作、函数设计、用户交互这些实用技能。最后还会给 GitHub 源码链接,拿过去就能用,咱们现在就开始!
普通聊天机器人要么只能答固定内容,要么得连大模型(比如 GPT)才能聪明点。咱们这个机器人不一样:
简单说:你教得越多,它越 “聪明”,而且是专属于你的聊天伙伴~
咱们不用复杂的环境,Python 自带的库就够了,步骤超简单:
json和difflib都是 Python 内置库,不用额外装!打开 Python 终端(VS Code 里按 Ctrl+调出终端,输入python回车),输import json和import difflib`,没报错就没问题咱们的机器人核心逻辑靠 4 个函数 + JSON 文件,我先把每个技术点拆开来,保证你能懂~
咱们要存的是 “问题 - 答案” 对(比如 “你好”→“嘿你好呀”),JSON 刚好适合存这种键值对数据,而且:
json库咱们会自动生成一个叫knowledge_base.json的文件,里面内容长这样:
{
"你好": "嘿你好呀",
"今天天气怎么样": "我还不会查天气呢,你可以教我呀~",
"再见": "拜拜~下次再聊!"
}左边的 “你好” 是用户可能问的问题(键),右边的 “嘿你好呀” 是对应的回复(值),新增的内容会自动加到这个文件里。
操作目的 | 用到的 | 核心作用 |
|---|---|---|
读 JSON 文件(加载记忆) |
| 把 JSON 文件里的内容读到 Python 的字典里,方便后续用 |
写 JSON 文件(保存记忆) |
| 把 Python 字典里的新内容(比如刚教的问答)写到 JSON 文件里 |
比如你教过 “你好” 的回复,用户输入 “你好呀”“嗨”“哈喽”,机器人怎么知道这些是类似的问题?
这里要用到 Python 内置的difflib库,里面的get_close_matches()函数专门干这事!
简单说:它会计算 “用户输入” 和 “知识库已有问题” 的相似度,返回最像的几个(默认最多 3 个)。
函数参数咱们要搞懂 3 个核心的:
word:用户当前输入的内容(比如 “你好呀”)possibilities:知识库所有的问题(比如 "你好","再见","今天天气怎么样")cutoff:相似度阈值(0-1 之间),值越高要求越像(比如 0.6 表示 “比较像” 就行,0.8 就要 “非常像”)举个例子:
如果知识库有 “你好”,用户输入 “你好呀”,get_close_matches("你好呀", ["你好","再见"], cutoff=0.6)会返回["你好"],机器人就知道该用 “你好” 的回复了。
用户输入 | 知识库已有问题 | cutoff=0.6 的匹配结果 | 机器人回复 |
|---|---|---|---|
你好呀 | 你好、再见 | "你好" | 嘿你好呀 |
嗨~ | 你好、再见 | "你好" | 嘿你好呀 |
拜拜 | 你好、再见 | "再见" | 拜拜~下次再聊! |
今天冷吗 | 你好、今天天气怎么样 | "今天天气怎么样" | 我还不会查天气呢,你可以教我呀~ |
咱们把机器人的逻辑拆成 4 个函数,每个函数干一件事,这样代码好懂、也好改。每个函数我都给完整代码 + 逐行解释,保证你能看懂!
作用:打开knowledge_base.json文件,把里面的 “问题 - 答案” 读到 Python 字典里,供机器人使用。
如果文件不存在(比如第一次运行),就自动创建一个空字典。
import json # 导入处理JSON的库
import difflib # 导入处理相似匹配的库
def load_knowledge_base(file_path: str) -> dict:
# file_path:JSON文件的路径(比如"knowledge_base.json")
# -> dict:表示这个函数最终返回一个字典
try:
# 尝试以“读”模式打开JSON文件,指定encoding='utf-8'避免中文乱码
with open(file_path, 'r', encoding='utf-8') as file:
# 把文件里的内容转成Python字典,返回这个字典
return json.load(file)
except FileNotFoundError:
# 如果文件不存在,就返回一个空字典(后续会自动创建文件)
return {}作用:把新教给机器人的 “问题 - 答案” 写到 JSON 文件里,实现 “记忆保存”。
def save_knowledge_base(file_path: str, knowledge_base: dict):
# file_path:JSON文件路径
# knowledge_base:要保存的字典(包含旧的+新的问答)
# 以“写”模式打开文件,如果文件不存在就创建;指定encoding='utf-8'防中文乱码
# indent=2:让JSON文件里的内容缩进2个空格,人类看起来更舒服
with open(file_path, 'w', encoding='utf-8') as file:
# 把Python字典转成JSON格式,写到文件里
json.dump(knowledge_base, file, indent=2, ensure_ascii=False)
# ensure_ascii=False:允许JSON里存中文(不然中文会变成uXXXX这种乱码)作用:根据用户输入,在知识库中找最像的问题,返回这个问题(如果没找到就返回 None)。
def find_best_match(user_input: str, knowledge_base: dict) -> str | None:
# user_input:用户输入的内容
# knowledge_base:知识库字典
# -> str | None:返回要么是找到的问题(字符串),要么是None(没找到)
# 先把知识库的所有问题(字典的键)取出来,存成列表
questions = list(knowledge_base.keys())
# 用difflib找相似问题,最多返回1个(因为我们只需要最像的)
matches = difflib.get_close_matches(
user_input, # 用户输入
questions, # 知识库所有问题
n=1, # 最多返回1个匹配结果
cutoff=0.6 # 相似度阈值,0.6是经验值,太低会匹配错,太高会找不到
)
# 如果有匹配结果,就返回第一个(也是唯一一个);没有就返回None
return matches[0] if matches else None作用:这是最核心的逻辑函数,负责:
def get_response(user_input: str, knowledge_base: dict, file_path: str) -> str:
# user_input:用户输入
# knowledge_base:知识库字典
# file_path:JSON文件路径
# -> str:返回机器人给用户的回复
# 第一步:找最佳匹配的问题
best_match = find_best_match(user_input, knowledge_base)
# 第二步:根据是否找到匹配,生成回复
if best_match:
# 如果找到匹配,就返回知识库中对应的答案
return knowledge_base[best_match]
else:
# 如果没找到,就让用户教机器人
print(f"我还不知道怎么回答“{user_input}”呢~")
# 让用户输入正确的回复
new_answer = input("你可以教我怎么回复吗?输入回复内容:")
# 把用户输入的“问题-回复”加到知识库字典里
knowledge_base[user_input] = new_answer
# 把更新后的知识库保存到JSON文件(这样下次打开还有)
save_knowledge_base(file_path, knowledge_base)
# 给用户反馈
return "谢谢!我记住啦~下次再问我这个问题,我就会回答了!"上面的 4 个函数是 “零件”,现在咱们把它们拼成完整的机器人程序,再加个用户交互循环(让用户能一直提问,直到输入 “退出”)。
# 导入需要的库
import json
import difflib
# ---------------------- 四大核心函数 ----------------------
def load_knowledge_base(file_path: str) -> dict:
try:
with open(file_path, 'r', encoding='utf-8') as file:
return json.load(file)
except FileNotFoundError:
return {}
def save_knowledge_base(file_path: str, knowledge_base: dict):
with open(file_path, 'w', encoding='utf-8') as file:
json.dump(knowledge_base, file, indent=2, ensure_ascii=False)
def find_best_match(user_input: str, knowledge_base: dict) -> str | None:
questions = list(knowledge_base.keys())
matches = difflib.get_close_matches(user_input, questions, n=1, cutoff=0.6)
return matches[0] if matches else None
def get_response(user_input: str, knowledge_base: dict, file_path: str) -> str:
best_match = find_best_match(user_input, knowledge_base)
if best_match:
return knowledge_base[best_match]
else:
print(f"我还不知道怎么回答“{user_input}”呢~")
new_answer = input("你可以教我怎么回复吗?输入回复内容:")
knowledge_base[user_input] = new_answer
save_knowledge_base(file_path, knowledge_base)
return "谢谢!我记住啦~下次再问我这个问题,我就会回答了!"
# ---------------------- 主程序(用户交互) ----------------------
def main():
# 知识库文件的路径(就存在当前文件夹,叫knowledge_base.json)
KNOWLEDGE_BASE_FILE = "knowledge_base.json"
# 第一步:加载已有的知识库(第一次运行是空字典)
knowledge_base = load_knowledge_base(KNOWLEDGE_BASE_FILE)
# 欢迎语
print("嗨!我是你的专属聊天机器人~你可以问我问题,输入“退出”就能结束聊天~")
# 循环:让用户一直提问
while True:
# 获取用户输入
user_input = input("n你:")
# 如果用户输入“退出”,就结束程序
if user_input.lower() == "退出":
print("机器人:拜拜~下次再聊!")
break
# 否则,获取机器人的回复并打印
response = get_response(user_input, knowledge_base, KNOWLEDGE_BASE_FILE)
print(f"机器人:{response}")
# 运行主程序(只有直接运行这个文件时才会执行)
if __name__ == "__main__":
main()chatbot.py(名字随便,但后缀必须是.py)open()函数都加了encoding='utf-8',避免中文乱码(新手最容易踩的坑!)KNOWLEDGE_BASE_FILE设为"knowledge_base.json",表示 JSON 文件和chatbot.py在同一个文件夹里,不用管复杂路径现在咱们跑代码,看看机器人怎么 “学习”,步骤超简单:
chatbot.py所在的文件夹(比如文件存在D:PythonProjects,终端输入cd D:PythonProjects回车)python chatbot.py回车,看到欢迎语就成功了!你好我还不知道怎么回答“你好”呢~你可以教我怎么回复吗?输入回复内容:嘿你好呀~很高兴和你聊天!谢谢!我记住啦~下次再问我这个问题,我就会回答了!python chatbot.py)你好嘿你好呀~很高兴和你聊天!(说明记忆保存成功了!)你好呀(和之前教的 “你好” 相似)嘿你好呀~很高兴和你聊天!(说明智能匹配生效了!)我整理了新手跑代码时最容易遇到的问题,每个问题都给解决办法,照着做就行!
常见问题 | 报错提示(大概) | 原因 & 解决办法 |
|---|---|---|
找不到 Python | “python 不是内部或外部命令” | 装 Python 时没勾 “Add Python to PATH”解决:重新装 Python,一定要勾这个选项;如果已经装了,百度 “Python 添加环境变量” 跟着做 |
JSON 文件乱码 | 打开 JSON 文件看到一堆 uXXXX | 没加 |
匹配不到相似问题 | 输入 “你好呀” 但机器人说不会 | cutoff 值太高(比如设成 0.8)解决:把 |
知识库没保存 | 教了问题后关闭程序,重新打开就没了 | 没调用 |
输入 “退出” 没反应 | 输入 “退出” 后机器人还让继续提问 | 主程序里判断条件错了解决:检查 |
如果你学完这个项目去面试 Python 岗,面试官可能会问这些问题,我给你大白话的回答思路,结合项目说更加分!
回答思路:分 “为什么不用 TXT”“为什么不用数据库”“为什么用 JSON” 三点说,结合项目场景:
“因为咱们的项目是轻量级的,只需要存‘问题 - 答案’这种键值对数据:
回答思路:不用讲太底层,说清楚 “计算相似度”“返回匹配结果” 就行,结合项目例子:
“这个函数主要是计算‘用户输入’和‘已有问题’之间的‘相似度分数’(用的是序列匹配算法,比如比较字符的重合度),然后根据咱们设的 cutoff 阈值筛选:
比如咱们项目里 cutoff=0.6,函数会把所有相似度≥0.6 的问题找出来,按相似度从高到低排,然后返回前 n 个(咱们设的 n=1,所以只返回最像的)。
比如用户输入‘你好呀’,和知识库的‘你好’相似度算出来是 0.7,超过 0.6,就返回‘你好’,机器人就能用对应的回复了。”
回答思路:讲 “模块化” 的好处,比如好懂、好改、好复用:
“主要是为了‘模块化’,每个函数干一件事,这样:
回答思路:从 “功能扩展”“体验优化” 两个方向说,结合实际场景:
“可以从几个方面优化:
回答思路:结合 JSON 的结构,新增 “用户信息” 字段:
“可以改 JSON 的结构,原来只存‘问题 - 答案’,现在加一个‘user_info’字段,存用户的信息,比如:
{
"questions": {
"你好": "嘿你好呀"
},
"user_info": {
"name": "小明",
"age": "20"
}
}
然后改 load 和 save 函数,读取的时候把 user_info 也读出来;加一个‘设置用户信息’的逻辑,比如用户输入‘我的名字是小明’,机器人就把‘name’:‘小明’加到 user_info 里,下次聊天时说‘嘿小明,你好呀’,这样就能记住用户信息了。”
只要跟着这个项目练下来,你不仅能学会 Python 文件操作、函数设计这些基础技能,还能理解 “持久化”“模块化” 这些编程思想,下次再做类似项目,就能举一反三啦!
如果运行代码时遇到其他问题,或者想扩展某个功能,随时回来讨论~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。