功能说明
模型选择:
支持 DeepSeek-V3、DeepSeek-R1 和 DeepSeek-R1-0528 三种模型
通过下拉菜单选择模型
打包请使用如下工具:
【推荐】
【Python 原创】Python智能打包工具V4.6高级版(安装+单文件)
【Python 原创】Python打包单文件程序使用PyQt6开发的图形化工具
调试使用如下工具 :
核心功能:
文本输入框输入问题
发送问题到API接口获取回答
语音播报AI回复内容
完整对话历史记录
界面特点:
响应式布局,可调整窗口大小
清晰的输入/输出分区
滚动文本区域显示完整对话历史
状态禁用防止重复提交
语音系统:
使用 pyttsx3 文本转语音引擎
可调节语速和音量
独立线程执行语音播报
使用说明
安装依赖:
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库:
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()
GRUD6 个月前
通告声明: 关于回帖问题 由于本站长要求,禁止刷1234等!存在恶意灌水回复,已开启自动审核制,自动封闭IP,禁止再次注册!请知晓!
有什么问题群内咨询 561116458
System7 个月前
网络技术QQ:561116458
科技之星①群:669812887
软件共享群:34008xxxx【因为是VIP软件不公开】
视频教程 短视频平台搜索:科技之星网络