| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- """
- 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("<Return>", self._on_enter)
- self.input_text.bind("<Shift-Return>", 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()
|