""" DeepSeek Chat - 图形界面问答程序 使用 tkinter 构建 GUI,调用 DeepSeek API 进行问答 """ import tkinter as tk from tkinter import scrolledtext, messagebox, ttk import threading import json from datetime import datetime from openai import OpenAI import config class DeepSeekChatApp: """DeepSeek 问答图形界面程序""" def __init__(self, root): self.root = root self.root.title("DeepSeek 智能问答助手") self.root.geometry("800x600") self.root.minsize(600, 400) # 设置窗口图标和背景色 self.root.configure(bg="#f0f0f0") # 初始化 API 客户端 self.client = None self.conversation_history = [] self.is_loading = False # 创建界面组件 self._create_widgets() # 初始化 API 连接 self._init_api() def _init_api(self): """初始化 DeepSeek API 客户端""" try: self.client = OpenAI( api_key=config.API_KEY, base_url=config.API_BASE ) self.status_var.set("✓ API 连接已就绪") except Exception as e: self.status_var.set(f"✗ API 初始化失败: {str(e)}") def _create_widgets(self): """创建界面组件""" # 顶部标题栏 header = tk.Frame(self.root, bg="#4a90d9", height=50) header.pack(fill=tk.X) header.pack_propagate(False) title_label = tk.Label( header, text="💬 DeepSeek 智能问答助手", font=("Microsoft YaHei", 14, "bold"), bg="#4a90d9", fg="white" ) title_label.pack(side=tk.LEFT, padx=15, pady=10) # 清空对话按钮 clear_btn = tk.Button( header, text="清空对话", font=("Microsoft YaHei", 9), bg="#e74c3c", fg="white", relief=tk.FLAT, cursor="hand2", command=self.clear_conversation ) clear_btn.pack(side=tk.RIGHT, padx=15, pady=10) # 主内容区域 main_frame = tk.Frame(self.root, bg="#f0f0f0") main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 对话显示区域 self.chat_display = scrolledtext.ScrolledText( main_frame, wrap=tk.WORD, font=("Microsoft YaHei", 11), bg="white", fg="#333333", state=tk.DISABLED, relief=tk.FLAT, padx=10, pady=10 ) self.chat_display.pack(fill=tk.BOTH, expand=True) # 配置文本标签样式 self.chat_display.tag_configure( "user", foreground="#2c3e50", font=("Microsoft YaHei", 11, "bold"), spacing1=10, spacing3=5 ) self.chat_display.tag_configure( "assistant", foreground="#27ae60", font=("Microsoft YaHei", 11), spacing1=10, spacing3=5 ) self.chat_display.tag_configure( "system", foreground="#95a5a6", font=("Microsoft YaHei", 9, "italic"), spacing1=5, spacing3=5 ) self.chat_display.tag_configure( "error", foreground="#e74c3c", font=("Microsoft YaHei", 11), spacing1=10, spacing3=5 ) # 输入区域 input_frame = tk.Frame(main_frame, bg="#f0f0f0") input_frame.pack(fill=tk.X, pady=(10, 0)) # 输入框 self.input_text = tk.Text( input_frame, height=3, font=("Microsoft YaHei", 11), bg="white", fg="#333333", relief=tk.FLAT, padx=10, pady=10, wrap=tk.WORD ) self.input_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.input_text.bind("", self._on_enter) self.input_text.bind("", self._on_shift_enter) # 发送按钮 self.send_btn = tk.Button( input_frame, text="发送 ➤", font=("Microsoft YaHei", 11, "bold"), bg="#4a90d9", fg="white", relief=tk.FLAT, cursor="hand2", padx=20, pady=10, command=self.send_message ) self.send_btn.pack(side=tk.RIGHT, padx=(10, 0)) # 底部状态栏 status_frame = tk.Frame(self.root, bg="#e0e0e0", height=30) status_frame.pack(fill=tk.X, side=tk.BOTTOM) status_frame.pack_propagate(False) self.status_var = tk.StringVar() self.status_var.set("正在初始化...") status_label = tk.Label( status_frame, textvariable=self.status_var, font=("Microsoft YaHei", 9), bg="#e0e0e0", fg="#666666" ) status_label.pack(side=tk.LEFT, padx=10, pady=5) # 显示欢迎消息 self._display_message( "system", "欢迎使用 DeepSeek 智能问答助手!\n在下方输入你的问题,按 Enter 发送,Shift+Enter 换行。" ) def _on_enter(self, event): """处理 Enter 键发送消息""" if not event.state & 0x0001: # 检查是否按下 Shift self.send_message() return "break" return None def _on_shift_enter(self, event): """处理 Shift+Enter 换行""" return None def _display_message(self, role, content): """在对话区域显示消息""" self.chat_display.config(state=tk.NORMAL) # 添加时间戳 timestamp = datetime.now().strftime("%H:%M:%S") if role == "user": prefix = f"👤 你 ({timestamp}):\n" tag = "user" elif role == "assistant": prefix = f"🤖 DeepSeek ({timestamp}):\n" tag = "assistant" elif role == "error": prefix = f"⚠️ 错误 ({timestamp}):\n" tag = "error" else: prefix = f"ℹ️ ({timestamp}):\n" tag = "system" self.chat_display.insert(tk.END, prefix, tag) self.chat_display.insert(tk.END, content + "\n\n", tag) self.chat_display.see(tk.END) self.chat_display.config(state=tk.DISABLED) def send_message(self): """发送消息到 DeepSeek API""" if self.is_loading: return # 获取用户输入 user_input = self.input_text.get("1.0", tk.END).strip() if not user_input: messagebox.showwarning("提示", "请输入问题内容") return # 清空输入框 self.input_text.delete("1.0", tk.END) # 显示用户消息 self._display_message("user", user_input) # 添加到对话历史 self.conversation_history.append({"role": "user", "content": user_input}) # 禁用发送按钮,显示加载状态 self.is_loading = True self.send_btn.config(state=tk.DISABLED, text="思考中...") self.status_var.set("正在请求 DeepSeek API...") # 在后台线程中调用 API thread = threading.Thread(target=self._call_api, daemon=True) thread.start() def _call_api(self): """在后台线程中调用 DeepSeek API""" try: if not self.client: raise Exception("API 客户端未初始化,请检查 config.py 中的 API Key 配置") # 调用 API response = self.client.chat.completions.create( model=config.MODEL, messages=self.conversation_history, stream=False ) # 获取回复内容 reply = response.choices[0].message.content # 添加到对话历史 self.conversation_history.append({"role": "assistant", "content": reply}) # 在主线程中更新界面 self.root.after(0, self._display_message, "assistant", reply) self.root.after(0, self._reset_ui, "✓ 回复完成") except Exception as e: error_msg = f"请求失败: {str(e)}\n\n请检查:\n1. API Key 是否正确\n2. 网络连接是否正常\n3. 是否已安装 openai 库" self.root.after(0, self._display_message, "error", error_msg) self.root.after(0, self._reset_ui, "✗ 请求失败") def _reset_ui(self, status_text): """重置界面状态""" self.is_loading = False self.send_btn.config(state=tk.NORMAL, text="发送 ➤") self.status_var.set(status_text) def clear_conversation(self): """清空对话""" if messagebox.askyesno("确认", "确定要清空所有对话记录吗?"): self.conversation_history = [] self.chat_display.config(state=tk.NORMAL) self.chat_display.delete("1.0", tk.END) self.chat_display.config(state=tk.DISABLED) self._display_message( "system", "对话已清空。开始新的对话吧!" ) self.status_var.set("对话已清空") def main(): """程序入口""" root = tk.Tk() app = DeepSeekChatApp(root) root.mainloop() if __name__ == "__main__": main()