Python案例##基于Coze的智能体语音聊天机器人

项目需求:

  • Coze中设计一个多agent模式的Bots,用于实现与用户智能对答
  • 调用cozeAPI,实现Bots机器人与用户聊天
  • 调用百度智能云API,实现识别用户的语音输入及机器人语音回复用户
  • 使用SQLite数据库,保存数据到数据库中,提供查看历史记录功能
  • 使用Pyside6设计一个简洁干净的Qt界面

设计思路:

  • 仿照QQ聊天界面设计一个聊天界面,实现用户输入等基本功能
  • 设计一个心理咨询机器人,调用API智能回复用户的问题
  • 调用百度智能云API,实现识别用户的语音输入及机器人语音回复用户
  • 设计自然语言的提示词(Promots),引导用户如何与机器人交流,制定回复逻辑,确保机器人能够理解用户意图并给出恰当回应。

界面展示:

1.Qt设计界面:

2.表情发送功能:

3.图片发送功能:

4.界面截屏功能:

 5.用户交互功能:

6.语音聊天功能:

 7.语音聊天功能:

功能代码:

1.用户交互代码:

    def sendTextMessage(self):
        # 获取当前时间并格式化
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 获取用户输入的消息
        message = self.textEdit.toPlainText()
        # 如果消息不为空
        if message:
            # 将消息添加到聊天记录中,并格式化显示发送时间和内容
            self.textBrowser.append(f"我:[{now}]\n"
                                    f"{message}\n")

            # 调用回复消息函数,传递用户消息作为参数
            self.replyTextMessage(message)
            # 清空消息输入框
            self.textEdit.clear()
            # 调用外部API处理消息,这里假设返回值为chat_response
            chat_response = self.coze_api(str)

    def replyTextMessage(self, message):
        # 获取当前时间并格式化
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 调用外部API处理消息,并获取响应结果
        res = self.coze_api(message)
        # 插入消息和响应结果到数据库或其他存储中
        insert_data(message, res)

2.语音对话代码:

    def start_recording(self):
        # 检查是否已经开始录音,如果没有,则开始录音
        if not self.recording:
            self.recording = True  # 将录音状态设置为True

            # 使用上下文管理器来确保线程安全,清除现有的帧数据
            with self.frames_lock:
                 self.frames.clear()

            # 更新按钮文本和样式,以指示正在录音
            self.pushButton.setText("录音中...")
            self.pushButton.setStyleSheet(u"background-color: rgb(255, 0, 0);\n"
                                          "color: rgb(255, 255, 255);\n"
                                          "font-size:20px;\n"
                                          "border-radius:5px")

            print("录音中...")  # 打印录音开始的消息

            # 创建并启动一个新的线程来处理音频录制,以避免阻塞主线程
            self.record_audio_thread = threading.Thread(target=self.record_audio)
            self.record_audio_thread.start()

    def stop_recording(self):
        """
        停止录音功能的方法。

        本方法通过改变对象的状态来停止录音,同时更新用户界面的按钮文本和样式,
        并尝试保存录音文件。确保录音线程安全结束是其核心功能之一。
        """
        # 检查是否正在录音,是则停止录音
        if self.recording:
            self.recording = False

            # 更新按钮文本和样式,以反映录音停止的状态
            self.pushButton.setText("按住话筒说话")
            self.pushButton.setStyleSheet(u"background-color: rgb(85, 170, 0);\n"
                                          "color: rgb(255, 255, 255);\n"
                                          "font-size:20px;\n"
                                          "border-radius:5px")

            # 打印停止录音的消息,用于日志记录
            print("停止录音...")

            # 确保录音线程结束
            self.record_audio_thread.join()
            # 尝试保存录音文件
            success = self.save_audio()
            if success:
                # 如果文件保存成功,打印确认消息
                print("录音文件保存成功!")
                self.speech_recognition() # 调用语音识别方法

            else:
                # 如果文件保存失败,打印错误消息
                print("录音文件保存失败!")

    def record_audio(self):
        """
        录音方法。尝试打开音频流并开始录音,直到停止录音或发生异常。
        """
        try:
            # 初始化音频流,设置格式、通道、采样率和输入模式
            stream = self.audio.open(format=self.FORMAT,
                                     channels=self.CHANNELS,
                                     rate=self.RATE,
                                     input=True,
                                     frames_per_buffer=self.CHUNK)

            # 主循环:持续录音直到停止
            while self.recording:
                # 读取指定数量的音频数据
                data = stream.read(self.CHUNK)
                # 使用上下文管理器来确保线程安全地添加数据到录音帧中
                with self.frames_lock:
                    self.frames.append(data)

            # 停止并关闭音频流
            stream.stop_stream()
            stream.close()
        except Exception as e:
            # 打印录音过程中发生的任何异常
            print(f"Error during recording: {e}")

    def save_audio(self):

        try:
            # 定义文件名
            filename = 'medium/user.wav'
            # 打开WAV文件以二进制格式写入
            wf = wave.open(filename, 'wb')
            # 设置声道数
            wf.setnchannels(self.CHANNELS)
            # 设置采样宽度
            wf.setsampwidth(self.audio.get_sample_size(self.FORMAT))
            # 设置帧率
            wf.setframerate(self.RATE)
            # 使用锁保护frames列表,确保线程安全地写入音频数据
            with self.frames_lock:
                wf.writeframes(b''.join(self.frames))
            # 关闭文件
            wf.close()
            # 打印保存成功消息
            print(f"录音文件已保存为 {filename}")
            # 返回成功标志
            return True
        except Exception as e:
            # 打印错误消息
            print(f"Error saving audio file: {e}")
            # 返回失败标志
            return False

    def speech_recognition(self):
        #语音识别功能
        # 初始化BaiduVoice对象,用于后续的语音识别和合成操作
        voice = BaiduVoice()
        # 识别语音文件并打印识别结果
        recognition_result = voice.recognize_speech('medium/user.wav')
        print("已识别的文本:", recognition_result)
        self.textBrowser.append(f"用户:{recognition_result}--{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        if recognition_result:
            #调用cozeapi接口
            self.coze_api(recognition_result)
            threading.Thread(target=insert_data, args=('用户',recognition_result)).start()
        else:
            print("识别失败")

    def speech_synthesis(self,kword):
        # 语音合成功能
        # 初始化BaiduVoice对象,用于后续的语音识别和合成操作
        voice = BaiduVoice()
        # 合成文本并保存为音频文件
        voice.synthesize_text(kword, 'medium/bot.mp3')
        # self.textBrowser.append(f"机器人:{kword}--{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("已合成的语音文本:", kword)
        # 播放合成的音频文件
        # 初始化Pygame,这是运行Pygame功能的必要步骤
        pygame.init()
        # 加载背景音乐文件
        pygame.mixer.music.load('medium/bot.mp3')
        # 播放背景音乐
        pygame.mixer.music.play()
        # 等待音乐播放完毕,避免程序提前退出
        while pygame.mixer.music.get_busy():
            # 控制循环帧率为10帧/秒,以节省资源
            pygame.time.Clock().tick(10)
        # 音乐播放结束后,释放Pygame资源
        pygame.quit()

 3.发送表情代码:

    def sendEmojis(self, emoji):
        """
        向文本框发送表情并进行语音合成。

        此函数用于构建一条包含当前时间和表情的消息,并将该消息添加到文本框中。
        同时,它还会对消息进行语音合成,以便通过语音输出。

        参数:
        emoji -- 要发送的表情字符串

        返回值:
        无
        """
        # 获取当前时间并格式化,以便在消息中显示
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 构建包含发送者、时间和表情的消息字符串
        message = f"我:[{now}]\n{emoji}\n"

        # 将消息添加到文本框中显示
        self.textBrowser.append(message)
        # 对消息进行语音合成,实现语音输出
        self.speech_synthesis(message)

    def openEmoji(self):
        """
        打开表情选择器的方法。

        该方法负责实例化一个Emoji对象,将其发送文本信号连接到sendEmojis方法,然后显示表情选择器。
        这种设计模式展示了如何在需要时初始化和交互UI组件,以及如何使用信号和槽机制来处理事件。
        """
        # 实例化一个Emoji对象
        self.emoji = Emoji()

        # 将emoji对象的sendTextSignal连接到sendEmojis方法
        self.emoji.sendTextSignal.connect(self.sendEmojis)

        # 显示emoji对象
        self.emoji.show()

4.图片发送代码:

    def sendImage(self):
        # 使用QFileDialog打开文件选择对话框
        file_path, _ = QFileDialog.getOpenFileName(None ,"选择图片", "",
                                                   "图片文件 (*.png *.jpg *.jpeg *.bmp)")
        try:
            if file_path:
                # 更新图片路径到文本行
                if file_path:
                    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    html_image = f"""
                               <div style="text-align: left; margin-bottom: 10px;">
                                   <span style="font-size: 10px; color: gray;">我:{now}</span>
                                   <br/>
                                   <img src="{file_path}" style="width: 150px; height: 150px; object-fit: cover;"/><br/>

                               </div>
                               """
                    print(f"Selected file path: {file_path}")  # 调试输出
                    self.textBrowser.append(html_image)
        except Exception as e:
            print(f"Error: {str(e)}")

5.聊天记录代码:

class History_Window(QMainWindow, Ui_HistoryWindow):
    """
    历史记录窗口类,继承自QMainWindow和Ui_HistoryWindow。
    该类负责显示历史记录窗口,并提供加载历史记录的功能。
    """
    def __init__(self):
        """
        初始化方法,用于初始化窗口及其组件。
        """
        super().__init__()
        self.setupUi(self)
        self.setFixedSize(433, 348)  # 设置窗口固定大小

    def load_history(self):
        """
        加载历史记录的方法。
        通过调用query_data方法获取历史记录数据,并将其显示在文本浏览器中。
        """
        self.textBrowser.setText(query_data())  # 设置文本浏览器内容为查询到的历史数据

    def show(self):
        """
        重写的显示方法,在显示窗口之前加载最新的历史记录。
        """
        self.load_history()  # 加载最新历史记录
        super().show()  # 调用父类的显示方法

6.窗口截屏代码:

    def initUI(self):
        """
        初始化用户界面,包括窗口设置、标签和布局的创建。
        """
        self.setWindowTitle('屏幕截图示例')
        self.setGeometry(100, 100, 800, 600)

        # 创建一个标签,用于显示截图
        self.screenshotLabel = QLabel(self)
        self.screenshotLabel.setAlignment(Qt.AlignCenter)

        # 创建一个垂直布局管理器
        layout = QVBoxLayout()
        # 将截图标签添加到布局中
        layout.addWidget(self.screenshotLabel)

        # 创建一个中心小部件,并设置布局
        central_widget = QWidget()
        central_widget.setLayout(layout)
        # 将中心小部件设置为主窗口的中心小部件
        self.setCentralWidget(central_widget)

    def takeScreenshot(self):
        """
        获取屏幕截图并显示在标签上。
        """
        # 获取主屏幕
        screen = QApplication.primaryScreen()
        if screen is not None:
            # 获取整个屏幕的截图
            screenshot = screen.grabWindow(0)
            # 将截图设置到标签上,并保持纵横比
            self.screenshotLabel.setPixmap(
                screenshot.scaled(self.screenshotLabel.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
            # 显示窗口
            self.show()

在设计智能体语音聊天机器人时,可能会遇到以下一些常见问题以及相应的解决方案:

  1. 理解用户意图的准确性问题

    • 问题:智能体可能无法准确理解用户的自然语言输入,导致回答不相关或不准确。
    • 解决方案:使用更先进的自然语言处理(NLP)技术,如上下文理解、意图识别和实体抽取。此外,可以通过机器学习不断训练和优化模型。
  2. 多轮对话管理

    • 问题:在多轮对话中,智能体可能会丢失上下文信息,导致回答不连贯。
    • 解决方案:实现上下文管理功能,让智能体能够跟踪对话历史,维持对话的连贯性。
  3. 知识库的局限性

    • 问题:智能体的知识库可能不全面,无法回答某些问题。
    • 解决方案:定期更新和扩充知识库,或者集成外部知识源,如Wikipedia、专业数据库等。
  4. 个性化服务的挑战

    • 问题:智能体可能无法提供个性化的用户体验。
    • 解决方案:通过用户画像和历史交互数据来个性化对话策略,提供定制化服务。
  5. 处理复杂问题的能力

    • 问题:智能体可能难以处理复杂或含糊的问题。
    • 解决方案:设计更复杂的对话流程和逻辑,或者集成专家系统来处理特定领域的复杂问题。
  6. 语音识别和合成的准确性

    • 问题:语音识别可能不准确,导致智能体误解用户的指令;语音合成可能不够自然。
    • 解决方案:使用高质量的语音识别和合成技术,如深度学习驱动的ASR(自动语音识别)和TTS(文本到语音)系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值