手把手教你使用PySide6搭建AI聊天界面,使用DeepSeek大模型接口
随着深度学习和自然语言处理技术的不断进步,问答系统进入了一个新的发展阶段,能够更加精准地理解复杂问题,支持多种知识形式的表达与多轮对话,从而实现更智能的问答体验。传统的问答方法主要依赖规则库、信息检索技术和浅层机器学习模型,尽管在特定领域中表现较为出色且系统具有较好的解释性,但在处理复杂语义和多轮对话时却显得力不从心。近年来,随着人工智能技术的快速发展,特别是大规模模型的出现,如 chatgpt、
目录
前言
随着深度学习和自然语言处理技术的不断进步,问答系统进入了一个新的发展阶段,能够更加精准地理解复杂问题,支持多种知识形式的表达与多轮对话,从而实现更智能的问答体验。传统的问答方法主要依赖规则库、信息检索技术和浅层机器学习模型,尽管在特定领域中表现较为出色且系统具有较好的解释性,但在处理复杂语义和多轮对话时却显得力不从心。近年来,随着人工智能技术的快速发展,特别是大规模模型的出现,如 chatgpt、DeepSeek 等,迅速火爆整个 AI 圈。本文将使用 PySide6 搭建 AI 聊天界面,模仿 chatgpt 聊天,能实现与 AI 对话,使用 DeepSeek 大模型接口,功能:实现实时聊天,支持流式输出,下文也会教你怎么使用源码,界面如下:
一、DeepSeek注册与使用
官网地址:
DeepSeek | 深度求索
api接口改到这里了,点击开发平台
下图应该是旧版本的网页,官网应该更新了
自行注册
登录后的样子,有免费的额度,演示应该够用了
参考官网文档,python 代码感觉没啥用,又不是流式输出,对于新手不是很友好,后面我通过这个接口搭建一个界面:
二、安装环境
安装 openai 库,命令如下:
pip install openai

安装 pyside6,在自己创建的虚拟环境安装即可,命令如下
pip install pyside6==6.4.2

三、界面设计
搭建界面前需要完成 QtDesigner 配置,参考下面的教程:
设计好的界面如下:
之后转成 python 文件即可
四、后端实现
接下来,将重点介绍如何实现后端逻辑,包括如何处理用户输入、发送 API 请求并响应、以及如何更新 UI 界面。本文的代码实现了一个多轮对话的聊天界面,并结合 API 实现了智能回复功能。
1.QTextEdit 输入控件实现
先说一下用户输入的控件,使用的是 QTextEdit ,原本 QTextEdit 控件键盘回车键是换行,我将其修改成发送信息了,如果按下的是 Shift+Enter,则是换行;如果仅按下 Enter,提交用户输入的消息。
核心代码如下:
def eventFilter(self, obj, event):
if obj == self.textEdit_input and event.type() == QEvent.KeyPress:
if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
if event.modifiers() & Qt.ShiftModifier:
# 按下 Shift+Enter 插入换行
cursor = self.textEdit_input.textCursor()
cursor.insertText("\n")
return True # 事件被处理,避免传递到其他控件
else:
# 按下 Enter 键发送消息
self.on_pushButton_Submit_clicked()
return True
return super().eventFilter(obj, event)
2.API 请求与响应处理
将通过一个自定义的线程类 ApiThread 来实现与后端 API 的交互。用户输入的消息会通过这个线程发送请求,获取响应后再更新到界面上。on_pushButton_Submit_clicked 方法是获取用户输入的消息并启动 API 请求线程。on_api_response 方法会将响应数据显示在聊天窗口中,并根据时间戳处理消息的时间显示。核心代码如下:
def on_pushButton_Submit_clicked(self):
if self.is_generating:
if self.api_thread and self.api_thread.isRunning():
self.api_thread.stop()
return
message = self.textEdit_input.toPlainText().strip()
if not message:
return
self.textEdit_input.clear()
self.toggle_generating_state(True)
time = str(int(QDateTime.currentDateTime().toSecsSinceEpoch()))
self.updateMessageTimeDisplay(time)
user_window = AIChatMessageWindow(self.listWidget_out.parentWidget())
user_item = QListWidgetItem(self.listWidget_out)
self.updateMessageDisplay(user_window, user_item, message, time, RoleType.user)
# 3. 准备系统回复框
self.current_message_window = AIChatMessageWindow(self.listWidget_out.parentWidget())
self.current_item = QListWidgetItem(self.listWidget_out)
# 4. 启动线程
self.api_thread = ApiThread(message)
self.api_thread.response_signal.connect(self.on_api_response)
self.api_thread.complete_signal.connect(self.on_api_finished) # 绑定结束信号
self.api_thread.start()
self.listWidget_out.scrollToBottom()
def on_api_response(self, response):
time = str(int(QDateTime.currentDateTime().toSecsSinceEpoch()))
if hasattr(self, 'current_item') and self.current_item:
current_message_window = self.current_message_window
current_text = current_message_window.message_text
current_text += response
# 更新消息显示
self.updateMessageDisplay(current_message_window, self.current_item, current_text, time, RoleType.system)
# 滚动到底部
self.listWidget_out.scrollToBottom()
3.消息显示与时间显示
动态地显示消息,并根据消息的时间间隔决定是否显示时间戳。每当一条消息发送或接收到响应时,都会更新消息显示,并在合适的时机显示时间戳。updateMessageDisplay 方法根据消息的文本内容调整消息项的高度,并将消息显示在聊天窗口中。updateMessageTimeDisplay 方法用来显示时间戳,当两条消息的时间间隔超过 60 秒时,会显示时间戳。核心代码如下:
def updateMessageDisplay(self, message_window, current_item, text, time, userType):
message_window.setFixedWidth(self.width()) # 设置消息窗口的宽度为主窗口的宽度
size = message_window.font_rect(text) # 获取文本的矩形区域
current_item.setSizeHint(QSize(self.width(), size.height())) # 设置列表项的高度为文本高度
message_window.setText(text, time, size, userType)
self.listWidget_out.setItemWidget(current_item, message_window) # 将消息添加到消息列表中
# 处理消息的时间显示
def updateMessageTimeDisplay(self, curMsgTime):
if self.listWidget_out.count() > 0:
lastItem = self.listWidget_out.item(self.listWidget_out.count() - 1)
message_window = self.listWidget_out.itemWidget(lastItem)
lastTime = int(message_window.message_time) # 获取最后一条消息的时间戳
curTime = int(curMsgTime) # 获取当前时间戳
show_time = (curTime - lastTime) > 60 # 如果两条消息相差超过60秒,显示时间
else:
show_time = True
if show_time:
messageTime = AIChatMessageWindow(self.listWidget_out.parentWidget())
itemTime = QListWidgetItem(self.listWidget_out)
size = QSize(self.width(), 40)
messageTime.resize(size)
itemTime.setSizeHint(size)
messageTime.setText(curMsgTime, curMsgTime, size, RoleType.current_time)
self.listWidget_out.setItemWidget(itemTime, messageTime)
4.实现头像绘制和文本的绘制
重点是这些代码实现,每个聊天作为一个QWidget窗口,简单来说 QListWidget 可以加载多个QWidget窗口,不过也可以通过其他组件实现,讲一下绘制代码 paintEvent ,paintEvent 是 Qt 框架中窗口和控件的自带方法,它是 QWidget 类的一个事件处理函数。所有继承自 QWidget 的控件(如 QMainWindow、QDialog、QLabel 等)都具有 paintEvent 方法,并且当需要重绘时,Qt 会自动调用这个方法。
在代码中每次窗口重绘时,会根据消息类型绘制不同的内容:
- RoleType.system:绘制系统消息,包含左侧头像、消息框和文本。
- RoleType.user:绘制用户消息,包含右侧头像、消息框和文本。
- RoleType.current_time:绘制时间消息,显示当前时间。
绘制过程中,QPainter 用于绘制图形、文本等,QRect 用于定义矩形区域,QPen 设置画笔颜色。绘制步骤:
- 绘制头像:首先根据消息类型选择左侧或右侧的头像,确保其大小与设备的像素比例一致。
- 绘制消息框:为每条消息绘制一个背景框,左侧系统消息框背景为浅灰色,右侧用户消息框为蓝色。
- 绘制文本:根据消息内容绘制文本,如果有换行,文本会自动换行并适应消息框的宽度。
- 绘制时间消息:时间消息居中显示,字体较小且灰色。
paintEvent 方法全部代码如下:
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
dpr = self.devicePixelRatio()
if self.message_userType == RoleType.system:
self._draw_avatar(painter, self.leftPixmap, self.left_icon_rect, dpr)
painter.setBrush(QColor(255, 255, 255))
painter.setPen(QColor(230, 230, 230))
painter.drawRoundedRect(self.left_frame_rect, 6, 6)
path = QPainterPath()
tip_x = self.left_frame_rect.x() - self.triangleW
tip_y = self.left_frame_rect.y() + 20
path.moveTo(self.left_frame_rect.x(), tip_y - 6)
path.lineTo(tip_x, tip_y)
path.lineTo(self.left_frame_rect.x(), tip_y + 6)
painter.drawPath(path)
elif self.message_userType == RoleType.user:
self._draw_avatar(painter, self.rightPixmap, self.right_icon_rect, dpr)
painter.setBrush(QColor(75, 164, 242))
painter.setPen(Qt.NoPen)
painter.drawRoundedRect(self.right_frame_rect, 6, 6)
path = QPainterPath()
# 右侧三角的位置也要基于 right_frame_rect 动态计算
tip_x = self.right_frame_rect.x() + self.right_frame_rect.width() + self.triangleW
tip_y = self.right_frame_rect.y() + 20
path.moveTo(self.right_frame_rect.right(), tip_y - 6)
path.lineTo(tip_x, tip_y)
path.lineTo(self.right_frame_rect.right(), tip_y + 6)
painter.drawPath(path)
elif self.message_userType == RoleType.current_time:
painter.setPen(QColor(153, 153, 153))
painter.setFont(QFont("Microsoft YaHei", 10))
painter.drawText(self.rect(), Qt.AlignCenter, self.current_time)
self.text_edit.hide()
在代码实现过程出现绘制的头像模糊,我电脑设备高分辨率会出现模糊,为了确保在不同显示设备上,使用 devicePixelRatio 方法获取当前显示设备的像素比(DPI比例)之后通过 pixmap.scaled 方法调整图像的大小,这样就可以使图像能够按照正确的设备像素比(DPI)进行缩放和显示,因此能在高分辨率显示器上显示清晰,且不会模糊。核心代码如下:
def _draw_avatar(self, painter, pixmap, rect, dpr):
if pixmap.devicePixelRatio() != dpr:
pixmap = pixmap.scaled(rect.size() * dpr, Qt.KeepAspectRatio, Qt.SmoothTransformation)
pixmap.setDevicePixelRatio(dpr)
painter.drawPixmap(rect, pixmap)
5.更换头像
如需更换自己头像也是很简单的,在 leftPixmap 和 rightPixmap 填入图片路径即可。
五、完整源码下载和使用方法
完整源码公众号后台发送 AI聊天界面 关键字即可获取,自己配置一下环境即可运行起来,代码需要更换自己的 API keys,在 DeepSeek 平台创建即可,创建时候记住 keys 值,它只会出现一次
之后在 deepseek.py 文件中的 api_key 处的单引号里面填入你的 keys 就行
总结
本文到此结束,对你有帮助帮忙点个小爱心呗,完整源码公众号发送 AI聊天界面 关键字即可获取
更多推荐


所有评论(0)