1.将以下代码改为使用JupyterLab页面Notebook的.ipynb文件能适用的完整代码,给出每部分单元格的文件名;2.给出修改后的项目目录结构;3.给出需要在wsl终端中安装的项目代码需要的依赖。代码:基于您提供的文档,我将为您提供完整的简化版桌面助手代码。以下是所有必要的文件:
## 1. 主程序文件:`main.py`
```python
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import os
import datetime
import threading
# 导入自定义模块
from floating_icon import FloatingIcon
from face_recognizer import SimpleFaceRecognizer
from rag_system import SimpleRAG
import speech_recognition as sr
import pyttsx3
import cv2
class DesktopAssistant:
def __init__(self):
self.floating_icon = FloatingIcon(self)
self.face_recognizer = SimpleFaceRecognizer()
self.rag_system = SimpleRAG()
self.voice_engine = pyttsx3.init()
def run(self):
"""启动桌面助手"""
self.floating_icon.run()
class FunctionPanel:
def __init__(self, parent_window, assistant):
self.parent = parent_window
self.assistant = assistant
self.create_panel()
def create_panel(self):
"""创建功能面板"""
self.panel = tk.Toplevel(self.parent)
self.panel.title("桌面助手功能")
self.panel.geometry(f"+{self.parent.winfo_x()}+{self.parent.winfo_y()+60}")
self.panel.resizable(False, False)
# 设置按钮样式
style = ttk.Style()
style.configure("Func.TButton", font=("Arial", 10), padding=5)
# 语音键
self.voice_btn = ttk.Button(
self.panel, text="🎤 语音助手", style="Func.TButton",
command=self.run_voice_assistant
)
self.voice_btn.pack(fill=tk.X, pady=5, padx=10)
# 图标切换键
self.icon_switch_btn = ttk.Button(
self.panel, text="🖼️ 更换图标", style="Func.TButton",
command=self.assistant.floating_icon.switch_icon
)
self.icon_switch_btn.pack(fill=tk.X, pady=5, padx=10)
# 结束程序键
self.quit_btn = ttk.Button(
self.panel, text="❌ 退出程序", style="Func.TButton",
command=self.quit_app
)
self.quit_btn.pack(fill=tk.X, pady=5, padx=10)
def run_voice_assistant(self):
"""语音助手功能"""
# 在新线程中运行语音识别,避免阻塞GUI
threading.Thread(target=self._voice_assistant_thread, daemon=True).start()
def _voice_assistant_thread(self):
"""语音助手线程函数"""
try:
recognizer = sr.Recognizer()
with sr.Microphone() as source:
# 调整环境噪音
recognizer.adjust_for_ambient_noise(source, duration=0.5)
self._show_message("提示", "正在聆听,请说话...")
try:
# 监听语音
audio = recognizer.listen(source, timeout=5, phrase_time_limit=10)
# 语音识别
user_text = recognizer.recognize_google(audio, language="zh-CN")
self._show_message("识别结果", f"你说:{user_text}")
# RAG生成回答
response = self.assistant.rag_system.get_response(user_text)
# 语音播放回答
self.assistant.voice_engine.say(response)
self.assistant.voice_engine.runAndWait()
except sr.WaitTimeoutError:
self.assistant.voice_engine.say("超时了,没有检测到语音输入")
self.assistant.voice_engine.runAndWait()
except sr.UnknownValueError:
self.assistant.voice_engine.say("抱歉,我没听清你说的话")
self.assistant.voice_engine.runAndWait()
except sr.RequestError:
self.assistant.voice_engine.say("语音识别服务不可用,请检查网络")
self.assistant.voice_engine.runAndWait()
except Exception as e:
print(f"语音助手错误:{e}")
def _show_message(self, title, message):
"""线程安全的消息显示"""
def show():
messagebox.showinfo(title, message)
self.panel.after(0, show)
def quit_app(self):
"""退出程序"""
self.assistant.voice_engine.say("再见")
self.assistant.voice_engine.runAndWait()
self.panel.destroy()
self.parent.destroy()
if __name__ == "__main__":
assistant = DesktopAssistant()
assistant.run()
```
## 2. 桌面图标模块:`floating_icon.py`
```python
import tkinter as tk
from tkinter import messagebox, filedialog
from PIL import Image, ImageTk, ImageDraw, ImageFont
import os
class FloatingIcon:
def __init__(self, assistant):
self.assistant = assistant
self.root = tk.Tk()
self.setup_window()
self.load_default_icon()
self.bind_events()
def setup_window(self):
"""设置窗口属性"""
self.root.overrideredirect(True) # 隐藏系统边框
self.root.attributes('-topmost', True) # 始终置顶
self.root.attributes('-alpha', 0.9) # 透明度
self.root.geometry("50x50+100+100") # 初始位置
self.root.configure(bg='lightblue')
def load_default_icon(self):
"""加载默认图标"""
# 创建默认图标目录
os.makedirs("icons", exist_ok=True)
default_icon_path = os.path.join("icons", "default_icon.png")
# 如果默认图标不存在,创建文字图标
if not os.path.exists(default_icon_path):
self.create_text_icon(default_icon_path)
self.load_icon(default_icon_path)
def create_text_icon(self, path):
"""创建文字图标"""
img = Image.new('RGB', (50, 50), color='lightblue')
draw = ImageDraw.Draw(img)
# 使用默认字体
try:
font = ImageFont.truetype("Arial", 12)
except:
font = ImageFont.load_default()
draw.text((15, 18), "助手", fill='black', font=font)
img.save(path)
def load_icon(self, image_path):
"""加载图标图片"""
try:
img = Image.open(image_path).resize((50, 50), Image.Resampling.LANCZOS)
self.icon_img = ImageTk.PhotoImage(img)
# 更新图标显示
if hasattr(self, 'icon_label'):
self.icon_label.configure(image=self.icon_img)
else:
self.icon_label = tk.Label(self.root, image=self.icon_img, bg='lightblue')
self.icon_label.pack(fill=tk.BOTH, expand=True)
except Exception as e:
print(f"加载图标失败:{e}")
# 使用文字fallback
self.create_fallback_icon()
def create_fallback_icon(self):
"""创建fallback图标"""
img = Image.new('RGB', (50, 50), color='lightblue')
draw = ImageDraw.Draw(img)
try:
font = ImageFont.truetype("Arial", 10)
except:
font = ImageFont.load_default()
draw.text((12, 15), "助手", fill='black', font=font)
self.icon_img = ImageTk.PhotoImage(img)
if hasattr(self, 'icon_label'):
self.icon_label.configure(image=self.icon_img)
else:
self.icon_label = tk.Label(self.root, image=self.icon_img, bg='lightblue')
self.icon_label.pack(fill=tk.BOTH, expand=True)
def bind_events(self):
"""绑定事件"""
# 拖动事件
self.icon_label.bind('<ButtonPress-1>', self.start_drag)
self.icon_label.bind('<B1-Motion>', self.on_drag)
# 双击唤醒事件
self.icon_label.bind('<Double-Button-1>', self.on_double_click)
def start_drag(self, event):
"""开始拖动"""
self.drag_x = event.x
self.drag_y = event.y
def on_drag(self, event):
"""拖动中"""
new_x = self.root.winfo_x() + (event.x - self.drag_x)
new_y = self.root.winfo_y() + (event.y - self.drag_y)
self.root.geometry(f"+{new_x}+{new_y}")
def on_double_click(self, event):
"""双击唤醒"""
import threading
threading.Thread(target=self._wakeup_thread, daemon=True).start()
def _wakeup_thread(self):
"""唤醒线程"""
try:
if self.assistant.face_recognizer.verify_user():
self.assistant.voice_engine.say("欢迎回来")
self.assistant.voice_engine.runAndWait()
self.show_function_panel()
else:
self.assistant.voice_engine.say("陌生人,不认识")
self.assistant.voice_engine.runAndWait()
self.root.after(0, self.root.destroy)
except Exception as e:
print(f"人脸识别错误:{e}")
messagebox.showerror("错误", f"人脸识别失败:{e}")
def show_function_panel(self):
"""显示功能面板"""
self.root.after(0, lambda: FunctionPanel(self.root, self.assistant))
def switch_icon(self):
"""切换图标"""
file_path = filedialog.askopenfilename(
title="选择图标",
filetypes=[("图片文件", "*.jpg *.png *.gif"), ("所有文件", "*.*")]
)
if file_path:
self.load_icon(file_path)
messagebox.showinfo("成功", "图标已更换!")
def run(self):
"""运行图标"""
self.root.mainloop()
```
## 3. 人脸识别模块:`face_recognizer.py`
```python
import cv2
import os
import tkinter.messagebox as messagebox
class SimpleFaceRecognizer:
def __init__(self):
# 加载Haar级联人脸检测模型
self.face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
# 检查已知人脸目录
self.known_face_path = os.path.join("known_faces", "user.jpg")
self.known_face_exists = os.path.exists(self.known_face_path)
def verify_user(self):
"""验证用户(简化版:检测到人脸即通过)"""
if not self.known_face_exists:
messagebox.showerror("错误",
"未找到已注册人脸,请先添加user.jpg到known_faces文件夹!")
return False
try:
# 尝试使用摄像头(优先WSL2配置,失败则尝试本地)
cap = None
try:
# WSL2摄像头
cap = cv2.VideoCapture("http://localhost:8080/video")
if not cap.isOpened():
raise Exception("WSL2摄像头无法打开")
except:
# 本地摄像头
cap = cv2.VideoCapture(0)
if not cap or not cap.isOpened():
messagebox.showerror("错误", "无法打开摄像头!")
return False
# 捕获单帧画面
ret, frame = cap.read()
cap.release()
if not ret:
messagebox.showerror("错误", "无法读取摄像头画面!")
return False
# 人脸检测
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = self.face_cascade.detectMultiScale(gray_frame, 1.3, 5)
# 简化逻辑:存在人脸即通过
return len(faces) > 0
except Exception as e:
print(f"人脸验证错误:{e}")
messagebox.showerror("错误", f"人脸验证失败:{e}")
return False
```
## 4. RAG系统模块:`rag_system.py`
```python
import datetime
class SimpleRAG:
def __init__(self):
# 预定义问答模板
self.response_templates = {
# 天气相关
"天气": "今天晴天,气温25度左右,适合外出活动",
"下雨": "今天有小雨,记得带雨伞,出门注意安全",
"温度": "当前气温大约25度,体感舒适",
# 时间相关
"时间": f"现在是{datetime.datetime.now().strftime('%H:%M:%S')}",
"日期": f"今天是{datetime.datetime.now().strftime('%Y年%m月%d日')}",
"几点": f"现在是{datetime.datetime.now().strftime('%H点%M分')}",
# 桌面助手操作相关
"更换图标": "点击功能框中的🖼️更换图标按钮,然后选择本地图片即可更换",
"唤醒": "双击桌面图标即可唤醒我,并进行人脸识别",
"语音": "点击🎤语音助手按钮,然后对着麦克风说话即可",
# 问候相关
"你好": "你好!我是您的桌面助手,很高兴为您服务",
"谢谢": "不客气,很高兴能帮助您",
"再见": "再见,期待下次为您服务",
# 默认回答
"default": "抱歉,我暂时无法回答这个问题,你可以尝试问天气、时间或桌面助手的使用方法"
}
def get_response(self, user_query):
"""获取回答(关键词匹配)"""
user_query = user_query.lower()
# 遍历模板关键词
for keyword, response in self.response_templates.items():
if keyword != "default" and keyword in user_query:
return response
# 无匹配关键词,返回默认回答
return self.response_templates["default"]
```
## 5. 环境配置脚本:`setup_environment.py`
```python
import os
import subprocess
import sys
def setup_environment():
"""设置项目环境"""
print("正在设置桌面助手环境...")
# 创建必要的目录
directories = ["icons", "known_faces", "documents"]
for directory in directories:
os.makedirs(directory, exist_ok=True)
print(f"创建目录: {directory}")
# 创建默认图标
create_default_icon()
print("环境设置完成!")
print("请将注册的人脸图片命名为 'user.jpg' 并放入 'known_faces' 文件夹")
def create_default_icon():
"""创建默认图标"""
from PIL import Image, ImageDraw, ImageFont
icon_path = "icons/default_icon.png"
if not os.path.exists(icon_path):
img = Image.new('RGB', (50, 50), color='lightblue')
draw = ImageDraw.Draw(img)
try:
# 尝试使用系统字体
font = ImageFont.truetype("Arial", 12)
except:
# 使用默认字体
font = ImageFont.load_default()
draw.text((15, 18), "助手", fill='black', font=font)
img.save(icon_path)
print("创建默认图标")
if __name__ == "__main__":
setup_environment()
```
## 6. 依赖文件:`requirements.txt`
```txt
opencv-python==4.8.1.78
speechrecognition==3.10.0
pyaudio==0.2.11
pyttsx3==2.90
Pillow==10.0.1
numpy==1.24.3
```
## 7. 启动脚本:`start_assistant.py`
```python
#!/usr/bin/env python3
"""
桌面助手启动脚本
在D:\Develop\wsl_teamwork目录下运行:
WSL
jupyter lab
然后在Jupyter中运行此脚本,或在终端中运行:python start_assistant.py
"""
import os
import sys
def check_environment():
"""检查环境配置"""
print("检查WSL2环境配置...")
# 检查DISPLAY设置(WSL2图形界面)
display = os.environ.get('DISPLAY')
if not display:
print("警告: DISPLAY环境变量未设置,GUI可能无法显示")
print("请在WSL2中执行: export DISPLAY=:0")
# 检查必要的目录
required_dirs = ['icons', 'known_faces']
for dir_name in required_dirs:
if not os.path.exists(dir_name):
print(f"创建目录: {dir_name}")
os.makedirs(dir_name)
print("环境检查完成")
def main():
"""主启动函数"""
print("=" * 50)
print(" Python+WSL2 桌面助手 - 简化版")
print("=" * 50)
# 检查环境
check_environment()
# 设置环境
from setup_environment import setup_environment
setup_environment()
# 导入并启动主程序
try:
from main import DesktopAssistant
print("启动桌面助手...")
assistant = DesktopAssistant()
assistant.run()
except ImportError as e:
print(f"导入错误: {e}")
print("请确保所有依赖已安装: pip install -r requirements.txt")
except Exception as e:
print(f"启动错误: {e}")
if __name__ == "__main__":
main()
```
## 使用说明
1. **在D:\Develop\wsl_teamwork目录下**,打开命令行并输入:
```bash
WSL
jupyter lab
```
2. 在JupyterLab中上传所有文件,然后按顺序运行:
3. **第一步:安装依赖**
```python
!pip install -r requirements.txt
```
4. **第二步:设置环境**
```python
%run setup_environment.py
```
5. **第三步:添加人脸**
- 将注册的人脸图片命名为 `user.jpg` 放入 `known_faces` 文件夹
6. **第四步:启动助手**
```python
%run start_assistant.py
```
## 项目结构
```
D:\Develop\wsl_teamwork\
├── main.py # 主程序
├── floating_icon.py # 桌面图标模块
├── face_recognizer.py # 人脸识别模块
├── rag_system.py # RAG系统模块
├── setup_environment.py # 环境配置
├── start_assistant.py # 启动脚本
├── requirements.txt # 依赖列表
├── icons/ # 图标目录
├── known_faces/ # 已知人脸目录
└── documents/ # 知识库文档目录
```
这个简化版包含了所有核心功能:桌面图标显示拖动、人脸识别、语音交互和简单的RAG问答系统。您可以直接在WSL2 + JupyterLab环境中运行。