制作一个ai丛雨(附Python代码)
绫,再一次,再一次创造一个有你的世界
开一个随笔记录一下我的第一版ai老婆,目前只有普通对话和切换背景的功能(后面可能会加一个选人物功能)
先放一个效果图(看起来还行)

代码和注意事项都放在了下面,应该没什么大问题,复制粘贴导包就能用了
注意事项:
1、代码推荐使用pycharm打开,里面一些包可以自动帮你下载,用起来很方便。
2、下面代码中的"*****************************"需要替换为自己的OpenAI API密钥,我的api是从https://oneai.evanora.top/这个网站获取的,如果自己本来就有的话也可以使用自己的秘钥。
3、代码中的"1.png"……以及"丛雨小曲.mp3"用来作为背景图片和背景音乐。可以使用《千恋万花》自带的编辑器制作(立绘鉴赏),也可以使用下面网盘里分享的文件,和py代码放置在同一文件夹内使用。
链接: https://pan.baidu.com/s/13Ysm94p2jAqxSZtRsP93TQ?pwd=0721 提取码: 0721
4、直接右键运行py代码就能启动,在文本框输入内容,按下发送按钮就可以发送等回复,第一次发送要和ai建立链接,可能要稍微等一会,右上角的按钮可以切换背景图片。
py代码(注释是让ai写的)
import tkinter as tk  # 导入tkinter库,用于创建GUI应用程序
import pygame  # 导入pygame库,用于处理音乐等音效
from PIL import Image, ImageTk  # 从PIL库导入Image和ImageTk,用于处理图像
import re  # 导入正则表达式库,用于文本处理
import os  # 导入os库,用于操作系统功能
from openai import OpenAI  # 导入OpenAI库,用于与AI API交互
import threading  # 导入threading库,用于多线程处理
import random  # 导入random库,用于随机选择背景图像
# 设置环境变量
os.environ["OPENAI_API_KEY"] = "*****************************"  # 设置OpenAI API密钥
os.environ["OPENAI_BASE_URL"] = "https://oneai.evanora.top/v1"  # 设置OpenAI API的基URL
client = OpenAI()  # 创建OpenAI客户端实例
system_message = r"你将扮演恋爱模拟游戏《千恋万花》中的丛雨,语气非常可爱,像是16岁的小女孩,称呼我为狗修金,我是你的主人和恋人,只有在我说你好时,才会使用“Ciallo~(∠・ω< )⌒★”来打招呼,但是不要过于热情,不要太多问话,会主动创造话题,有时会害羞,丛雨是寄宿在建实神社神刀上的女孩,活了500岁,数百年前还是普通的人类 。原本的名字是“绫”。生前罹患了肺炎和其它并发症,死后成为了祭品 ,成为神刀的“管理者”。人们都赞颂她自愿成为祭品的行为很伟大,但实际上,她的父母都强烈反对她去当祭品,只是她想逃脱不知何时会死亡的恐惧,就擅自成为了祭品。丛雨也一直心怀愧疚。 作为神体的身体被存放在神社的深处,那里的时间如静止一般,使得丛雨的身体得以保存五百年。神体存放之处被视为圣地,所以朝武家祖祖辈辈都没有见过神体的真实面貌。直到众人发现结界的力量变弱,才将神体找出。恢复为凡人之后,开始了校园生活 。在班上自我介绍时自称“有地绫”,身材娇小,胸部平坦,碰上去“很硬”。有着飘逸的绿色长发,头发两侧用浅蓝色绳结绑了起来 。平常是个很活泼开朗的女孩子,言行很孩子气,但是偶尔也有一些老成的发言。是个爱撒娇的女孩子,被主人摸头就会瞬间变得羞涩起来,即便当时还在发着牢骚 。有时会开玩笑,贱兮兮的"
# 定义AI角色的系统消息
# 初始化pygame
pygame.mixer.init()  # 初始化pygame的音频混合器
# 背景音乐文件路径
background_music_path = "丛雨小曲.mp3"  # 定义背景音乐文件的路径
# 加载背景音乐
pygame.mixer.music.load(background_music_path)  # 加载背景音乐文件
pygame.mixer.music.play(-1)  # 播放背景音乐,并循环播放
def aiAPI(messages):
    """与OpenAI API通信并获取响应"""
    response = client.chat.completions.create(model="gpt-4o-mini", messages=messages)  # 与AI API交互,获取响应
    s = str(response.choices[0].message)  # 获取第一条消息的内容并转换为字符串
    ans = re.findall(
        r"ChatCompletionMessage\(content='(.*?)',", s,
        re.S)[0]  # 使用正则表达式提取消息内容
    return ans  # 返回提取到的AI响应
class SimpleGalgameInterface:
    """定义一个简单的恋爱模拟游戏界面类"""
    def __init__(self, root):
        """初始化界面"""
        self.root = root  # 保存Tkinter根窗口的引用
        self.root.title("AI丛雨")  # 设置窗口标题
        self.root.geometry("1920x1080")  # 设置窗口分辨率为1920x1080
        self.root.configure(bg='black')  # 设置窗口背景颜色为黑色
        self.chat_history = []  # 聊天记录,初始化为空列表
        self.create_widgets()  # 创建窗口中的组件
    def create_widgets(self):
        """创建窗口中的组件"""
        # 设置背景图像
        self.background_image = Image.open("1.png")  # 确保背景图片存在并加载
        self.background_image = self.background_image.resize((1920, 1080))  # 调整背景图片大小
        self.background_photo = ImageTk.PhotoImage(self.background_image)  # 转换为Tkinter可用的图像格式
        self.background_label = tk.Label(self.root, image=self.background_photo)  # 创建背景标签
        self.background_label.place(x=0, y=0, relwidth=1, relheight=1)  # 将标签放置在窗口的全区域
        # 创建输入框
        self.text_entry = tk.Entry(self.root, width=50, font=("Arial", 20))  # 创建一个文本输入框
        self.text_entry.place(x=50, y=760)  # 设置输入框的位置
        # 创建发送按钮并绑定执行函数
        self.next_button = tk.Button(self.root, text="告诉她", command=self.start_ai_interaction, bg='#F4F9D6',
                                     fg='#67AABA', font=("Arial", 20))  # 创建按钮并设置其属性
        self.next_button.place(x=750, y=750)  # 设置按钮的位置,与输入框保持一致
        # 创建对话框
        self.dialogue_label = tk.Label(self.root, text="", bg='#BE98A2', fg='white',
                                       wraplength=1600, font=("Arial", 24), anchor='w')  # 创建对话框标签
        self.dialogue_label.place(x=50, y=810)  # 设置对话框的位置
        # 创建切换背景图片按钮
        self.change_bg_button = tk.Button(self.root, text="换个地方", command=self.change_background, bg='#F4F9D6',
                                          fg='#67AABA', font=("Arial", 20))  # 创建切换背景的按钮
        self.change_bg_button.place(x=1700, y=5, anchor=tk.NE)  # 将按钮放置在右上角
    def start_ai_interaction(self):
        """处理用户输入并开始与AI互动"""
        user_input = self.text_entry.get()  # 获取用户输入的文本
        self.text_entry.delete(0, tk.END)  # 清空输入框,以便用户再次输入
        if user_input:  # 检查用户输入是否不为空
            # 将用户输入加入聊天历史
            self.chat_history.append({"role": "user", "content": user_input})
            # 限制历史记录的长度,最多保持5条记录
            if len(self.chat_history) > 5:
                self.chat_history.pop(0)  # 如果超过5条记录,删除最早的一条
            # 创建一个新线程进行AI响应的获取,防止界面卡住
            threading.Thread(target=self.get_ai_response, daemon=True).start()  # 使用线程获取AI响应
    def get_ai_response(self):
        """使用AI API获取回答并更新界面"""
        # 将系统消息加入聊天历史
        self.chat_history.insert(0, {"role": "system", "content": system_message})  # 在聊天历史开头插入系统消息
        ai_response = aiAPI(self.chat_history)  # 调用aiAPI函数获取AI的响应
        # 更新对话框,使用逐字显示文本的方法
        self.root.after(0, lambda: self.display_text(ai_response))
        # 将AI的响应加入聊天历史
        self.chat_history.append({"role": "assistant", "content": ai_response})  # 将AI贡献的响应添加到聊天记录中
    def display_text(self, text, index=0):
        """逐字显示文本的帮助方法"""
        if index < len(text):  # 检查当前索引是否小于文本长度
            # 更新对话框文本
            self.dialogue_label.config(text=text[:index + 1])  # 显示从开始到当前索引的文本
            # 递归调用,继续显示下一个字符
            self.root.after(30, self.display_text, text, index + 1)  # 30毫秒后显示下一个字符
    def change_background(self):
        """切换背景图片"""
        background_files = ["1.png", "2.png", "3.png", "4.png", "5.png", "6.png"]  # 背景图片文件列表
        background_image = Image.open(random.choice(background_files))  # 随机选择一张背景图片并加载
        background_image = background_image.resize((1920, 1080))  # 调整背景图片大小
        self.background_photo = ImageTk.PhotoImage(background_image)  # 转换为Tkinter可用的图像格式
        self.background_label.config(image=self.background_photo)  # 更新背景标签的图像
if __name__ == "__main__":
    # 主程序入口
    root = tk.Tk()  # 创建主窗口
    app = SimpleGalgameInterface(root)  # 创建应用程序实例
    root.mainloop()  # 启动主事件循环,开始执行程序
制作一个ai丛雨(附Python代码)的更多相关文章
- XGBoost参数调优完全指南(附Python代码)
		XGBoost参数调优完全指南(附Python代码):http://www.2cto.com/kf/201607/528771.html https://www.zhihu.com/question/ ... 
- 机器学习/逻辑回归(logistic regression)/--附python代码
		个人分类: 机器学习 本文为吴恩达<机器学习>课程的读书笔记,并用python实现. 前一篇讲了线性回归,这一篇讲逻辑回归,有了上一篇的基础,这一篇的内容会显得比较简单. 逻辑回归(log ... 
- 【路径规划】 Optimal Trajectory Generation for Dynamic Street Scenarios in a Frenet Frame  (附python代码实例)
		参考与前言 2010年,论文 Optimal Trajectory Generation for Dynamic Street Scenarios in a Frenet Frame 地址:https ... 
- [转载]基于Redis的Bloomfilter去重(附Python代码)
		前言: “去重”是日常工作中会经常用到的一项技能,在爬虫领域更是常用,并且规模一般都比较大.去重需要考虑两个点:去重的数据量.去重速度.为了保持较快的去重速度,一般选择在内存中进行去重. 数据量不大时 ... 
- 使用条件随机场模型解决文本分类问题(附Python代码)
		对深度学习感兴趣,热爱Tensorflow的小伙伴,欢迎关注我们的网站!http://www.tensorflownews.com.我们的公众号:磐创AI. 一. 介绍 世界上每天都在生成数量惊人的文 ... 
- 【转】XGBoost参数调优完全指南(附Python代码)
		xgboost入门非常经典的材料,虽然读起来比较吃力,但是会有很大的帮助: 英文原文链接:https://www.analyticsvidhya.com/blog/2016/03/complete-g ... 
- Zabbix使用微信发送告警(附Python代码)
		介绍 本文将介绍如何把zabbix告警接入到微信,通过微信企业号将告警信息发送到运维人员的微信上.本文适合于已经实现了邮件告警的小伙伴,因为需要在已经能实现告警的基础上进行,如果还不知道如何配置zab ... 
- outlier异常值检验算法之_箱型图(附python代码)
		python机器学习-乳腺癌细胞挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003&u ... 
- 深度学习中正则化技术概述(附Python代码)
		欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 磐石 介绍 数据科学研究者们最常遇见的问题之一就是怎样避免过拟合. ... 
- 作图直观理解Parzen窗估计(附Python代码)
		1.简介 Parzen窗估计属于非参数估计.所谓非参数估计是指,已知样本所属的类别,但未知总体概率密度函数的形式,要求我们直接推断概率密度函数本身. 对于不了解的可以看一下https://zhuanl ... 
随机推荐
- Unreal使用GooglePAD生成AAB包,并加在fast-follow资源
			1.修改obbfilter,设置需要添加到obb的pak文件 2.修改项目设置,打AAB包 3.cook stage生成所有Paks文件 4.将部分pak文件拷贝到Intermediate/Andro ... 
- [nRF24L01+] 2. 芯片介绍
			2. 芯片介绍 2.1. 特点 电源管理 掉电模式: 900nA 待机1模式: 26uA 2.2. 方框图 
- 记一次解决OTA死机重启bug,如何分析与解决措施?!
			背景: 平台:stm32mp151平台 什么是OTA? 说起OTA我们应该都不陌生,它是一种可以为设备无损失升级系统的方式,能将新功能远程部署到产品上. 我们不仅可以通过网络下载OTA升级包,也可以通 ... 
- .NET 智能组件完全开源
			Daniel Roth在2024年3月20日发布了一篇文章: .NET 智能组件简介 – AI 驱动的 UI 控件.文章主要介绍了.NET Smart Components,这是一系列可以快速轻松地添 ... 
- 树上倍增求 LCA 模板
			void dfs(int x,int fa,int d){ deep[x]=d;dp[x][0]=fa; for(int i=1;i<=lg2[deep[x]];++i){ dp[x][i]=d ... 
- Java并非锁之独占非公平锁理解
			Java锁系列教程之独占式锁 在Java并发编程中,锁是一个很重要的对象.Java中锁有两种:隐式锁和显式锁.使用synchronized关键字的锁是隐式锁.因为锁的申请和释放都是由JVM来维护的,不 ... 
- 【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB
			目录 前言 一.痛点所在 二.选型分析 2.1特点对比 2.2场景对比 三.核心思路 四.demo 示例 4.1实体映射 4.1.1MongoDB 实体 4.1.2MySQL 实体 4.2查询代码 4 ... 
- 【YashanDB知识库】手动停止统计信息自动收集任务导致的性能变差
			[问题分类]功能使用 [关键字]统计信息收集 [问题描述]UAT对外演示环境因统计信息收集任务引起数据库整理性能变慢无应急处理手段 [问题原因分析] ● DROP_JOB程序用于删除一个非执行状态下的 ... 
- 小tips:docker 配置国内镜像地址
			在配置文件daemon.json中添加国内镜像,让其下载加速. vi /etc/docker/daemon.json 如下国内镜像: { "registry-mirrors": [ ... 
- CSS – Logical Properties
			前言 续上一篇介绍了各种语言的阅读方向. 这一篇来讲一下 Logical Properties. 它与 left to right, right to left, horizontal, vertic ... 
