功能说明

模型选择:

支持 DeepSeek-V3、DeepSeek-R1 和 DeepSeek-R1-0528 三种模型
通过下拉菜单选择模型

打包请使用如下工具:

【推荐】

【Python 原创】Python智能打包工具V4.6高级版(安装+单文件)
【Python 原创】Python打包单文件程序使用PyQt6开发的图形化工具

调试使用如下工具 :

截图 软件群内免费获取:561116458
【Python 源码】DeepSeek AI助手-语音功能科技之星关闭接口停止不可用

核心功能:

文本输入框输入问题
发送问题到API接口获取回答
语音播报AI回复内容
完整对话历史记录

界面特点:

响应式布局,可调整窗口大小
清晰的输入/输出分区
滚动文本区域显示完整对话历史
状态禁用防止重复提交

语音系统:

使用 pyttsx3 文本转语音引擎
可调节语速和音量
独立线程执行语音播报

【Python 源码】DeepSeek AI助手-语音功能科技之星关闭接口停止不可用

使用说明

安装依赖:

pip install requests pyttsx3 tkinter

操作流程:

选择模型(默认DeepSeek-V3)
在输入框输入问题
点击"发送问题"或按Enter键提交
查看AI回复内容
点击"语音播报"听取回复

技术要点

多线程处理:API请求和语音播报在独立线程执行,避免界面卡顿
错误处理:完善的异常捕获和错误提示机制
历史管理:完整记录对话历史和交互时间
响应式设计:使用ScrolledText处理长文本内容

修复方案

语音引擎初始化问题:

添加更健壮的语音引擎初始化逻辑
提供备选语音引擎方案
添加详细的错误处理
使用win32com.client替代方案:
对于Windows系统,直接使用win32com.client作为备选方案

修复和改进内容

语音引擎重构:

创建了VoiceEngine类封装语音功能
支持多种语音引擎(pyttsx3 和 Windows SAPI)
详细的错误处理和回退机制

增强的错误处理:

添加了详细的异常捕获和错误报告
语音引擎初始化失败时提供明确的状态提示
所有网络请求和语音操作都进行了异常处理
用户界面改进:
添加了状态栏显示当前操作状态
显示语音引擎初始化状态
自动语音播报AI回复(可配置)

多线程优化:

使用daemon=True确保线程正确退出
避免线程阻塞主界面

其他改进:

更清晰的日志输出
更健壮的历史记录管理
更好的用户反馈机制

安装说明
如果使用Windows SAPI语音引擎,需要安装pywin32库:
【Python 源码】DeepSeek AI助手-语音功能科技之星关闭接口停止不可用

pip install requests pywin32

以下是科技之星修正可用源码(声明:只为研究学习,禁止使用非法用途)

import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import threading
import requests
import json
import sys
import os
from datetime import datetime

# 语音引擎封装类
class VoiceEngine:
    def __init__(self):
        self.engine = None
        self.voice_enabled = False
        self.init_voice_engine()

    def init_voice_engine(self):
        try:
            # 尝试使用pyttsx3
            import pyttsx3
            self.engine = pyttsx3.init()
            self.engine.setProperty('rate', 180)
            self.engine.setProperty('volume', 0.9)
            self.voice_enabled = True
            print("语音引擎初始化成功 (pyttsx3)")
        except Exception as e:
            print(f"pyttsx3初始化失败: {e}")
            try:
                # 备选方案:Windows系统使用SAPI.SpVoice
                if sys.platform == 'win32':
                    import win32com.client
                    self.engine = win32com.client.Dispatch("SAPI.SpVoice")
                    self.voice_enabled = True
                    print("语音引擎初始化成功 (SAPI.SpVoice)")
                else:
                    print("非Windows系统,语音功能不可用")
            except Exception as win_err:
                print(f"备选语音引擎初始化失败: {win_err}")
                self.voice_enabled = False

    def speak(self, text):
        if not self.voice_enabled or not self.engine:
            return False

        try:
            if hasattr(self.engine, 'say'):
                # pyttsx3引擎
                self.engine.say(text)
                self.engine.runAndWait()
                return True
            elif hasattr(self.engine, 'Speak'):
                # SAPI.SpVoice引擎
                self.engine.Speak(text)
                return True
        except Exception as e:
            print(f"语音播报失败: {e}")
            return False

    def is_available(self):
        return self.voice_enabled

class DeepSeekVoiceAssistant:
    def __init__(self, root):
        self.root = root
        self.root.title("DeepSeek 语音助手 v1.2")
        self.root.geometry("800x600")
        self.root.resizable(True, True)
        self.api_url = "https://api.milorapart.top/apis/AIchat"

        # 模型列表
        self.models = ["DeepSeek-V3", "DeepSeek-R1", "DeepSeek-R1-0528"]
        self.current_model = self.models[0]

        # 历史记录
        self.history = []

        # 创建UI
        self.create_widgets()

        # 初始化语音引擎
        self.voice_engine = VoiceEngine()

        # 显示语音状态
        self.update_output(f"系统状态: {'语音功能已启用' if self.voice_engine.is_available() else '语音功能不可用'}\n")
        self.update_output("-" * 80 + "\n")

        # 设置状态栏初始状态
        self.status_var.set("就绪 | 请在上方输入您的问题")

    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 模型选择
        model_frame = ttk.LabelFrame(main_frame, text="模型选择", padding=10)
        model_frame.pack(fill=tk.X, pady=(0, 10))

        self.model_var = tk.StringVar()
        self.model_combo = ttk.Combobox(model_frame, textvariable=self.model_var, state="readonly")
        self.model_combo['values'] = self.models
        self.model_combo.current(0)
        self.model_combo.pack(fill=tk.X, padx=5, pady=5)

        # 输入区域
        input_frame = ttk.LabelFrame(main_frame, text="输入问题", padding=10)
        input_frame.pack(fill=tk.X, pady=(0, 10))

        self.input_text = tk.Text(input_frame, height=4, font=("微软雅黑", 10))
        self.input_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.input_text.bind("<Return>", self.on_enter_pressed)

        # 按钮区域
        btn_frame = ttk.Frame(main_frame)
        btn_frame.pack(fill=tk.X, pady=(0, 10))

        self.send_btn = ttk.Button(btn_frame, text="发送问题", command=self.send_question)
        self.send_btn.pack(side=tk.LEFT, padx=5)

        self.clear_btn = ttk.Button(btn_frame, text="清空记录", command=self.clear_history)
        self.clear_btn.pack(side=tk.LEFT, padx=5)

        self.voice_btn = ttk.Button(btn_frame, text="语音播报", command=self.text_to_speech)
        self.voice_btn.pack(side=tk.RIGHT, padx=5)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("初始化中...")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        # 输出区域
        output_frame = ttk.LabelFrame(main_frame, text="AI回复", padding=10)
        output_frame.pack(fill=tk.BOTH, expand=True)

        self.output_text = scrolledtext.ScrolledText(output_frame, font=("微软雅黑", 10))
        self.output_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.output_text.config(state=tk.DISABLED)

        # 设置焦点到输入框
        self.input_text.focus_set()

    def on_enter_pressed(self, event):
        # 处理回车键按下事件
        if not event.state & 0x1:  # 检查是否按下了Shift键
            self.send_question()
            return "break"  # 阻止默认的回车行为
        return None

    def send_question(self):
        question = self.input_text.get("1.0", tk.END).strip()
        if not question:
            messagebox.showwarning("输入错误", "请输入问题内容")
            return

        model = self.model_var.get() or self.models[0]
        self.current_model = model

        # 添加到历史
        self.history.append({
            "role": "user",
            "content": question,
            "time": datetime.now().strftime("%H:%M:%S")
        })

        # 禁用按钮
        self.send_btn.config(state=tk.DISABLED)
        self.model_combo.config(state=tk.DISABLED)
        self.voice_btn.config(state=tk.DISABLED)
        self.status_var.set(f"正在获取AI回复... ({model})")

        # 显示用户问题
        self.update_output(f">>> 用户 [{model}]: {question}\n\n")

        # 清空输入框
        self.input_text.delete("1.0", tk.END)

        # 在新线程中发送请求
        threading.Thread(target=self.get_ai_response, args=(question, model), daemon=True).start()

    def get_ai_response(self, question, model):
        try:
            payload = {
                "messages": [{"role": "user", "content": question}],
                "model": model
            }

            headers = {
                "Content-Type": "application/json",
                "Accept": "application/json"
            }

            self.root.after(0, lambda: self.status_var.set(f"正在连接AI服务器({model})..."))
            response = requests.post(
                self.api_url,
                data=json.dumps(payload),
                headers=headers,
                timeout=60
            )

            if response.status_code == 200:
                result = response.json()
                reply = result['choices'][0]['message']['content']

                # 添加到历史
                self.history.append({
                    "role": "assistant",
                    "content": reply,
                    "time": datetime.now().strftime("%H:%M:%S")
                })

                # 更新界面
                self.root.after(0, self.show_response, reply)
            else:
                error_msg = f"API错误: {response.status_code}\n{response.text}"
                self.root.after(0, self.show_error, error_msg)

        except Exception as e:
            self.root.after(0, self.show_error, f"请求异常: {str(e)}")

        finally:
            self.root.after(0, self.enable_buttons)
            self.root.after(0, lambda: self.status_var.set("就绪 | 请在上方输入您的问题"))

    def show_response(self, reply):
        self.update_output(f"<<< AI回复: \n{reply}\n")
        self.update_output("-" * 80 + "\n")

        # 自动语音播报
        if self.voice_engine.is_available():
            self.root.after(0, lambda: self.status_var.set("正在语音播报AI回复..."))
            threading.Thread(target=self.voice_engine.speak, args=(reply,), daemon=True).start()

    def show_error(self, error_msg):
        self.update_output(f"错误: {error_msg}\n")
        self.update_output("-" * 80 + "\n")
        messagebox.showerror("API错误", error_msg)

    def enable_buttons(self):
        self.send_btn.config(state=tk.NORMAL)
        self.model_combo.config(state="readonly")
        self.voice_btn.config(state=tk.NORMAL)

    def update_output(self, text):
        self.output_text.config(state=tk.NORMAL)
        self.output_text.insert(tk.END, text)
        self.output_text.see(tk.END)
        self.output_text.config(state=tk.DISABLED)

    def text_to_speech(self):
        if not self.history:
            messagebox.showinfo("提示", "没有可播报的内容")
            return

        # 获取最后一条AI回复
        last_reply = next((msg['content'] for msg in reversed(self.history) if msg['role'] == 'assistant'), None)

        if last_reply:
            if not self.voice_engine.is_available():
                messagebox.showinfo("提示", "语音功能不可用")
                return

            self.status_var.set("正在语音播报...")
            threading.Thread(target=self.speak_text, args=(last_reply,), daemon=True).start()
        else:
            messagebox.showinfo("提示", "没有AI回复内容")

    def speak_text(self, text):
        try:
            success = self.voice_engine.speak(text)
            self.root.after(0, lambda: self.status_var.set("语音播报完成" if success else "语音播报失败"))
        except Exception as e:
            self.root.after(0, lambda: self.status_var.set(f"语音错误: {str(e)}"))

    def clear_history(self):
        self.history = []
        self.input_text.delete("1.0", tk.END)
        self.output_text.config(state=tk.NORMAL)
        self.output_text.delete("1.0", tk.END)
        self.output_text.config(state=tk.DISABLED)
        self.update_output("历史记录已清除\n" + "-" * 80 + "\n")
        self.status_var.set("历史记录已清除 | 请在上方输入您的问题")

if __name__ == "__main__":
    root = tk.Tk()
    app = DeepSeekVoiceAssistant(root)
    root.mainloop()