开发者

Python使用PyQt5实现与DeepSeek聊天的图形化小软件

目录
  • 1. 导入依赖库
  • 2. DeepSeek API 配置
  • 3. ChatThread 类
  • 4. ChatApp 类
  • 5. 核心功能方法
    • 5.1 send_message 方法
    • 5.2 update_chat_display_stream 方法
    • 5.3 upload_image 方法
  • 6. 主程序入口
    • 7、完整代码如下:
      • 8. 总结

        1. 导入依赖库

        import sys
        import requests
        import json
        from PyQt5.QtWidgets import QApplication, QWidget, QvboxLayout, QTextEdit, QLineEdit, QPushButton, QLabel, QFileDialog
        from PyQt5.QtCore import QThread, pyqtSignal
        from PyQt5.QtGui import QPixmap
        
        • sys: 用于处理 python 的系统相关功能,例如退出程序。
        • requests: 用于发送 HTTP 请求,与 DeepSeek API 进行通信。
        • json: 用于处理 JSON 格式的数据。
        • PyQt5: 用于创建图形用户界面(GUI)。
          • QApplication: 管理应用程序的控制流和主要设置。
          • QWidget: 所有用户界面对象的基类。
          • QVBoxLayout: 垂直布局管理器,用于排列控件。
          • QTextEdit: 多行文本输入框,用于显示聊天记录。
          • QLineEdit: 单行文本输入框,用于用户输入消息。
          • QPushButton: 按钮控件,用于触发事件。
          • QLabel: 标签控件,用于显示文本或图像。
          • QFileDialog: 文件选择对话框,用于上传图像。
        • QThread: 用于创建多线程,避免阻塞主线程。
        • pyqtSignal: 用于在线程和主线程之间传递信号。
        • QPixmap: 用于加载和显示图像。

        2. DeepSeek API 配置

        DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions"
        DEEPSEEK_API_KEY = "your_deepseek_api_key"  # 替换为自己的 DeepSeek API Key
        
        • DEEPSEEK_API_URL: DeepSeek API 的端点 URL。
        • DEEPSEEK_API_KEY: DeepSeek API 密钥,用于身份验证。

        3. ChatThread 类

        class ChatThread(QThread):
            response_received = pyqtSignal(str)
            stream_response_received = pyqtSignal(str)
        
            def __init__(self, messages, stream=False):
                super().__init__()
                self.messages = messages
                self.stream = stream
        
            def run(self):
                headers = {
                    "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
                    "Content-Type": "applicatwww.devze.comion/json"
                }
        
                data = {
                    "model": "deepseek-chat",
                    "messages": self.messages,
                    "stream": self.stream
                }
        
                if self.stream:
                    response = requests.post(DEEPSEEK_API_URL, headers=headers, json=data, stream=True)
                    for line in response.iter_lines():
                        if line:
                            decoded_line = line.decode('utf-8')
                            if decoded_line.startswith("data:"):
                                json_data = json.loads(decoded_line[5:])
                                if "choices" in json_data:
                                    content = json_data["choices"][0]["delta"].get("content", "")
                                    self.stream_response_received.emit(content)
                else:
                    response = requests.post(DEEPSEEK_API_URL, headers=headers, json=data)
                    if response.status_code == 200:
                        json_data = response.json()
                        content = json_data["choices"][0]["message"]["content"]
                        self.response_received.emit(content)
                    else:
                        self.response_received.emit("Error: 无法从DeepSeekAPI获得响应.")
        

        功能说明

        • ChatThread 是一个继承自 QThread 的类,用于在后台与 DeepSeek API 进行通信。
        • response_received 和 stream_response_received: 这两个信号用于将 API 的响应传递回主线程。
        • __init__ 方法:
          • 接受 messages(聊天记录)和 stream(是否启用流式输出)作为参数。
        • run 方法:
          • 发送 HTTP POST 请求到 DeepSeek API。
          • 如果启用流式输出(stream=True),则逐行读取响应并发送信号。
          • 如果禁用流式输出,则等待完整响应后发送信号。

        4. ChatApp 类

        class ChatApp(QWidget):
            def __init__(self):
                super().__init__()
                self.initUI()
                self.messages = []
        
            def initUI(self):
                self.setWindowTitle('DeepSeek Chat')
                self.setGeometry(100, 100, 600, 400)
        
                layout = QVBoxLayout()
        
                self.chat_display = QTextEdit()
                self.chat_display.setReadOnly(True)
                layout.addwidget(self.chat_display)
        
                self.input_box = QLineEdit()
                self.input_box.setPlaceholderText("在此留下你的千言万语...")
                layoujavascriptt.addWidget(self.input_box)
        
                self.send_button = QPushButton('发送')
                self.send_button.clicked.connect(self.send_message)
                layout.addWidget(self.send_button)
        
                self.image_label = QLabel()
                layout.addWidget(self.image_label)
        
                self.upload_image_button = QPushButton('上传图片')
                self.upload_image_button.clicked.connect(self.upload_image)
                layout.addWidget(self.upload_image_button)
        
                self.setLayout(layout)
        

        功能说明

        • ChatApp 是主应用程序类,继承自 QWidget
        • __init__ 方法:
          • 初始化界面并创建一个空的消息列表 self.messages
        • initUI 方法:
          • 设置窗口标题和大小。
          • 使用 QVBoxLayout 垂直排列控件。
          • chat_display: 用于显示聊天记录的多行文本框。
          • input_box: 用于用户输入消息的单行文本框。
          • send_button:www.devze.com 发送消息的按钮,点击后触发 send_message 方法。
          • image_label: 用于显示上传的图像。
          • upload_image_button: 上传图像的按钮,点击后触发 upload_image 方法。

        5. 核心功能方法

        5.1 send_message 方法

        def send_message(self):
            user_input = self.input_box.text()
            if user_input:
                self.messages.append({"role": "user", "content": user_input})
                self.chat_display.append(f"You: {user_input}")
                self.input_box.clear()
        
            编程客栈    self.chat_thread = ChatThread(self.messages, stream=True)
                self.chat_thread.stream_response_received.connect(self.update_chat_display_stream)
                self.chat_thread.start()
        
        • 获取用户输入的消息。
        • 将消息添加到 self.messages 列表中。
        • 在聊天显示区域显示用户的消息。
        • 清空输入框。
        • 启动 ChatThread 线程与 DeepSeek API 通信,并启用流式输出。

        5.2 update_chat_display_stream 方法

        def update_chat_display_stream(self, content):
            self.chat_display.moveCursor(self.chat_display.textCursor().End)
            self.chatjs_display.insertPlainText(content)
            self.chat_display.moveCursor(self.chat_display.textCursor().End)
        
        • 将 DeepSeek API 的流式响应逐字添加到聊天显示区域。
        • 确保光标始终在文本末尾,以便用户可以看到最新的内容。

        5.3 upload_image 方法

        def upload_image(self):
            options = QFileDialog.Options()
            file_name, _ = QFileDialog.getOpenFileName(self, "上传图片", "", "Images (*.png *.jpg *.jpeg)", options=options)
            if file_name:
                pixmap = QPixmap(file_name)
                self.image_label.setPixmap(pixmap.scaled(200, 200))
                self.messages.append({"role": "user", "content": f"Image: {file_name}"})
        
        • 打开文件选择对话框,允许用户选择图像文件。
        • 加载图像并显示在 image_label 中。
        • 将图像路径添加到 self.messages 列表中。

        6. 主程序入口

        if __name__ == '__main__':
            app = QApplication(sys.argv)
            chat_app = ChatApp()
            chat_app.show()
            sys.exit(app.exec_())
        
        • 创建 QApplication 实例。
        • 创建 ChatApp 实例并显示窗口。
        • 进入主事件循环,等待用户交互。

        7、完整代码如下:

        需要安装PyQt5和requests

        pip install PyQt5 requests
        
        import sys
        import requests
        import json
        from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QLineEdit, QPushButton, QLabel, QFileDialog
        from PyQt5.QtCore import QThread, pyqtSignal
        from PyQt5.QtGui import QPixmap
        
        # DeepSeek API 配置
        DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions"
        DEEPSEEK_API_KEY = "your_deepseek_api_key"  # 替换为自己的 DeepSeek API Key,去DeepSeek注册获取
        
        class ChatThread(QThread):
            response_received = pyqtSignal(str)
            stream_response_received = pyqtSignal(str)
        
            def __init__(self, messages, stream=False):
                super().__init__()
                self.messages = messages
                self.stream = stream
        
            def run(self):
                headers = {
                    "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
                    "Content-Type": "application/json"
                }
        
                data = {
                    "model": "deepseek-chat",
                    "messages": self.messages,
                    "stream": self.stream
                }
        
                if self.stream:
                    response = requests.post(DEEPSEEK_API_URL, headers=headers, json=data, stream=True)
                    for line in response.iter_lines():
                        if line:
                            decoded_line = line.decode('utf-8')
                            if decoded_line.startswith("data:"):
                                json_data = json.loads(decoded_line[5:])
                                if "choices" in json_data:
                                    content = json_data["choices"][0]["delta"].get("content", "")
                                    self.stream_response_received.emit(content)
                else:
                    response = requests.post(DEEPSEEK_API_URL, headers=headers, json=data)
                    if response.status_code == 200:
                        json_data = response.json()
                        content = json_data["choices"][0]["message"]["content"]
                        self.response_received.emit(content)
                    else:
                        self.response_received.emit("Error: 无法从DeepSeekAPI获得响应.")
        
        class ChatApp(QWidget):
            def __init__(self):
                super().__init__()
                self.initUI()
                self.messages = []
        
            def initUI(self):
                self.setWindowTitle('DeepSeek Chat')
                self.setGeometry(100, 100, 600, 400)
        
                layout = QVBoxLayout()
        
                self.chat_display = QTextEdit()
                self.chat_display.setReadOnly(True)
                layout.addWidget(self.chat_display)
        
                self.input_box = QLineEdit()
                self.input_box.setPlaceholderText("在此留下你的千言万语...")
                layout.addWidget(self.input_box)
        
                self.send_button = QPushButton('发送')
                self.send_button.clicked.connect(self.send_message)
                layout.addWidget(self.send_button)
        
                self.image_label = QLabel()
                layout.addWidget(self.image_label)
        
                self.upload_image_button = QPushButton('上传图片')
                self.upload_image_button.clicked.connect(self.upload_image)
                layout.addWidget(self.upload_image_button)
        
                self.setLayout(layout)
        
            def send_message(self):
                user_input = self.input_box.text()
                if user_input:
                    self.messages.append({"role": "user", "content": user_input})
                    self.chat_display.append(f"You: {user_input}")
                    self.input_box.clear()
        
                    self.chat_thread = ChatThread(self.messages, stream=True)
                    self.chat_thread.stream_response_received.connect(self.update_chat_display_stream)
                    self.chat_thread.start()
        
            def update_chat_display_stream(self, content):
                self.chat_display.moveCursor(self.chat_display.textCursor().End)
                self.chat_display.insertPlainText(content)
                self.chat_display.moveCursor(self.chat_display.textCursor().End)
        
            def upload_image(self):
                options = QFileDialog.Options()
                file_name, _ = QFileDialog.getOpenFileName(self, "上传图片", "", "Images (*.png *.jpg *.jpeg)", options=options)
                if file_name:
                    pixmap = QPixmap(file_name)
                    self.image_label.setPixmap(pixmap.scaled(200, 200))
                    self.messages.append({"role": "user", "content": f"Image: {file_name}"})
        
        if __name__ == '__main__':
            app = QApplication(sys.argv)
            chat_app = ChatApp()
            chat_app.show()
            sys.exit(app.exec_())
        

        8. 总结

        • 使用 PyQt5 创建了一个简单的图形化聊天界面。
        • 通过 ChatThread 实现了与 DeepSeek API 的异步通信,支持流式和非流式输出。
        • 支持多轮对话和多模态输入(如图像上传)。
        • 代码结构清晰,易于扩展和优化。

        以上就是Python使用PyQt5实现与DeepSeek聊天的图形化小软件的详细内容,更多关于Python PyQt5与DeepSeek聊天软件的资料请关注编程客栈(www.devze.com)其它相关文章!

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜