首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

手把手教你使用PySide6搭建AI聊天界面,使用DeepSeek大模型接口

  • 25-02-18 12:41
  • 2481
  • 7919
blog.csdn.net

目录

  • 前言
  • 一、DeepSeek注册与使用
  • 二、安装环境
  • 三、界面设计
  • 四、后端实现
    • 1.QTextEdit 输入控件实现
    • 2.API 请求与响应处理
    • 3.消息显示与时间显示
    • 4.实现头像绘制和文本的绘制
    • 5.更换头像
  • 五、完整源码下载和使用方法
  • 总结


前言

随着深度学习和自然语言处理技术的不断进步,问答系统进入了一个新的发展阶段,能够更加精准地理解复杂问题,支持多种知识形式的表达与多轮对话,从而实现更智能的问答体验。传统的问答方法主要依赖规则库、信息检索技术和浅层机器学习模型,尽管在特定领域中表现较为出色且系统具有较好的解释性,但在处理复杂语义和多轮对话时却显得力不从心。近年来,随着人工智能技术的快速发展,特别是大规模模型的出现,如 chatgpt、DeepSeek 等,迅速火爆整个 AI 圈。本文将使用 PySide6 搭建 AI 聊天界面,模仿 chatgpt 聊天,能实现与 AI 对话,使用 DeepSeek 大模型接口,功能:实现实时聊天,支持流式输出,下文也会教你怎么使用源码,界面如下:

在这里插入图片描述

一、DeepSeek注册与使用

官网地址:
DeepSeek | 深度求索
api接口改到这里了,点击开发平台
在这里插入图片描述
下图应该是旧版本的网页,官网应该更新了
在这里插入图片描述
自行注册
在这里插入图片描述

登录后的样子,有免费的额度,演示应该够用了
在这里插入图片描述

参考官网文档,python 代码感觉没啥用,又不是流式输出,对于新手不是很友好,后面我通过这个接口搭建一个界面:
在这里插入图片描述

二、安装环境

安装 openai 库,命令如下:

pip install openai
  • 1

在这里插入图片描述
安装 pyside6,在自己创建的虚拟环境安装即可,命令如下

pip install pyside6==6.4.2
  • 1

在这里插入图片描述

三、界面设计

搭建界面前需要完成 QtDesigner 配置,参考下面的教程:

手把手教你在PyCharm配置PySide6和QtDesigner,实现python程序快速搭建可视化界面

设计好的界面如下:
在这里插入图片描述

之后转成 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.API 请求与响应处理

将通过一个自定义的线程类 ApiThread 来实现与后端 API 的交互。用户输入的消息会通过这个线程发送请求,获取响应后再更新到界面上。on_pushButton_Submit_clicked 方法是获取用户输入的消息并启动 API 请求线程。on_api_response 方法会将响应数据显示在聊天窗口中,并根据时间戳处理消息的时间显示。核心代码如下:

    def on_pushButton_Submit_clicked(self):

        message = self.textEdit_input.toPlainText()
        self.textEdit_input.clear()
        time = str(int(QDateTime.currentDateTime().toSecsSinceEpoch()))  # 获取时间戳
        if message != "":  # 确保消息不为空
            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)

        self.current_message_window = AIChatMessageWindow(self.listWidget_out.parentWidget())
        self.current_item = QListWidgetItem(self.listWidget_out)
        # 启动API请求线程
        self.api_thread = ApiThread(message)
        self.api_thread.response_signal.connect(self.on_api_response)
        self.api_thread.start()

        self.listWidget_out.setCurrentRow(self.listWidget_out.count() - 1)

    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.setCurrentRow(self.listWidget_out.count() - 1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

4.实现头像绘制和文本的绘制

重点是这些代码实现,每个聊天作为一个QWidget窗口,简单来说 QListWidget 可以加载多个QWidget窗口,不过也可以通过其他组件实现,讲一下绘制代码 paintEvent ,paintEvent 是 Qt 框架中窗口和控件的自带方法,它是 QWidget 类的一个事件处理函数。所有继承自 QWidget 的控件(如 QMainWindow、QDialog、QLabel 等)都具有 paintEvent 方法,并且当需要重绘时,Qt 会自动调用这个方法。
在代码中每次窗口重绘时,会根据消息类型绘制不同的内容:

  • RoleType.system:绘制系统消息,包含左侧头像、消息框和文本。
  • RoleType.user:绘制用户消息,包含右侧头像、消息框和文本。
  • RoleType.current_time:绘制时间消息,显示当前时间。

绘制过程中,QPainter 用于绘制图形、文本等,QRect 用于定义矩形区域,QPen 设置画笔颜色。绘制步骤:

  1. 绘制头像:首先根据消息类型选择左侧或右侧的头像,确保其大小与设备的像素比例一致。
  2. 绘制消息框:为每条消息绘制一个背景框,左侧系统消息框背景为浅灰色,右侧用户消息框为蓝色。
  3. 绘制文本:根据消息内容绘制文本,如果有换行,文本会自动换行并适应消息框的宽度。
  4. 绘制时间消息:时间消息居中显示,字体较小且灰色。

paintEvent 方法全部代码如下:

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)

        # 获取 QWidget 的设备像素比(DPI 比例)
        device_pixel_ratio = self.devicePixelRatio()

        if self.message_userType == RoleType.system:  # openai信息
            # 确保头像与设备像素比一致
            pixmap = self.leftPixmap
            if pixmap.devicePixelRatio() != device_pixel_ratio:
                # 将 QPixmap 缩放为正确的 DPI 比例
                pixmap = self.leftPixmap.scaled(self.left_icon_rect.size() * device_pixel_ratio,
                                                Qt.KeepAspectRatio, Qt.SmoothTransformation)
                pixmap.setDevicePixelRatio(device_pixel_ratio)

            # 绘制左侧头像
            painter.drawPixmap(self.left_icon_rect, pixmap)

            # 绘制消息框
            col_KuangB = QColor(234, 234, 234)
            painter.setBrush(col_KuangB)
            painter.drawRoundedRect(self.left_frame_rect.adjusted(-1, -1, 1, 1), 4, 4)

            # 绘制消息框的实际背景
            col_Kuang = QColor(255, 255, 255)
            painter.setBrush(col_Kuang)
            painter.drawRoundedRect(self.left_frame_rect, 4, 4)

            # 绘制文本
            penText = QPen(QColor(51, 51, 51))  # 设置文本颜色
            painter.setPen(penText)
            option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter)
            option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)  # 设置自动换行
            painter.drawText(self.left_text_rect, self.message_text, option)

        elif self.message_userType == RoleType.user:  # 用户的消息,右侧头像
            # 确保头像与设备像素比一致
            pixmap = self.rightPixmap
            if pixmap.devicePixelRatio() != device_pixel_ratio:
                # 将 QPixmap 缩放为正确的 DPI 比例
                pixmap = self.rightPixmap.scaled(self.right_icon_rect.size() * device_pixel_ratio,
                                                 Qt.KeepAspectRatio, Qt.SmoothTransformation)
                pixmap.setDevicePixelRatio(device_pixel_ratio)  # 设置设备像素比

            # 绘制右侧头像
            painter.drawPixmap(self.right_icon_rect, pixmap)

            # 绘制消息框
            col_Kuang = QColor(75, 164, 242)
            painter.setBrush(col_Kuang)
            painter.drawRoundedRect(self.right_frame_rect, 4, 4)

            # 绘制文本
            penText = QPen(Qt.white)  # 设置文本颜色为白色
            painter.setPen(penText)
            option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter)
            option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
            painter.drawText(self.right_text_rect, self.message_text, option)




        elif self.message_userType == RoleType.current_time:  # 时间消息
            penText = QPen(QColor(153, 153, 153))  # 设置时间文本的颜色
            painter.setPen(penText)
            option = QTextOption(Qt.AlignCenter)  # 时间居中显示
            option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
            # 设置时间文本的字体
            te_font = self.font()
            te_font.setFamily("Microsoft YaHei")
            te_font.setPointSize(10)
            painter.setFont(te_font)
            painter.drawText(self.rect(), self.current_time, option)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 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

在代码实现过程出现绘制的头像模糊,我电脑设备高分辨率会出现模糊,为了确保在不同显示设备上,使用 devicePixelRatio 方法获取当前显示设备的像素比(DPI比例)之后通过 pixmap.scaled 方法调整图像的大小,这样就可以使图像能够按照正确的设备像素比(DPI)进行缩放和显示,因此能在高分辨率显示器上显示清晰,且不会模糊。核心代码如下:

        # 获取 QWidget 的设备像素比(DPI 比例)
        device_pixel_ratio = self.devicePixelRatio()

        if self.message_userType == RoleType.system:  # openai信息
            # 确保头像与设备像素比一致
            pixmap = self.leftPixmap
            if pixmap.devicePixelRatio() != device_pixel_ratio:
                # 将 QPixmap 缩放为正确的 DPI 比例
                pixmap = self.leftPixmap.scaled(self.left_icon_rect.size() * device_pixel_ratio,
                                                Qt.KeepAspectRatio, Qt.SmoothTransformation)
                pixmap.setDevicePixelRatio(device_pixel_ratio)

            # 绘制左侧头像
            painter.drawPixmap(self.left_icon_rect, pixmap)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5.更换头像

如需更换自己头像也是很简单的,在 leftPixmap 和 rightPixmap 填入图片路径即可。
在这里插入图片描述

五、完整源码下载和使用方法

完整源码发送 AI聊天界面 关键字即可获取,自己配置一下环境即可运行起来,代码需要更换自己的 API keys,在 DeepSeek 平台创建即可,创建时候记住 keys 值,它只会出现一次
在这里插入图片描述

之后在 deepseek.py 文件中的 api_key 处的单引号里面填入你的 keys 就行
在这里插入图片描述


总结

本文到此结束,对你有帮助帮忙点个小爱心呗,完整源码发送 AI聊天界面 关键字即可获取

参考文章: Qt 学习之路】Qt5气泡式聊天框——QListWidget+QPainter实现

目标检测与AI深度学习
微信公众号
技术合作、分享等更多源码请关注公众号
注:本文转载自blog.csdn.net的挂科边缘的文章"https://blog.csdn.net/weixin_44779079/article/details/145226517"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top