Ollama 本地GUI客戶端:為DeepSeek用戶量身定制的智能模型管理與交互工具

Ollama 本地GUI客戶端:為DeepSeek用戶量身定制的智能模型管理與交互工具

相關資源文件已經打包成EXE文件,可雙擊直接運行程序,且文章末尾已附上相關源碼,以供大家學習交流,博主主頁還有更多Python相關程序案例,秉著開源精神的想法,望大家喜歡,點個關注不迷路!!!

1. 簡介:

在人工智能領域,如何高效地管理、下載和與模型進行交互是每個開發者面臨的挑戰。DeepSeek:Ollama 本地客戶端 是一款專為開發者設計的工具,它使得智能模型的管理和交互變得前所未有的簡單與高效。無論是下載本地模型,還是實時與 AI 模型互動,DeepSeek 都能夠提供直觀、流暢的用戶體驗,助力開發者在人工智能的世界中快速前行。

為了更便捷地使用DeepSeek-R1并進行本地部署,我安裝了官方的ollama軟件并通過命令行進行操作。然而,由于命令行操作的使用習慣問題,我決定開發一個簡單的圖形客戶端來簡化這一過程。該圖形客戶端的使用需要先安裝官方的ollama軟件,安裝完成后即可通過該客戶端進行操作,從而提供了一個更為直觀和易用的圖形化界面,減少了對命令行的依賴。

具體來說,用戶需要訪問ollama官網下載并安裝ollama軟件,之后運行我開發的圖形客戶端(ollama_gui)。通過這個客戶端,用戶可以更加輕松地進行操作,不需要直接通過命令行輸入復雜的指令。這一做法大大提升了使用的便捷性和效率。

2. 功能亮點:

1. 簡潔直觀的用戶界面

采用 Tkinter 開發的圖形界面,用戶可以輕松地管理模型,進行下載、刪除等操作,完全不需要依賴復雜的命令行操作。通過簡單的點擊即可完成所有操作,適合各類開發者使用。

2. 全面的模型管理功能

下載模型: DeepSeek 支持用戶從 Ollama API 下載所需的模型,下載進度條會實時更新,用戶可以清晰地看到下載進度和速度。
刪除模型: 支持一鍵刪除本地模型,保持系統整潔,避免存儲空間的浪費。
實時智能對話功能
用戶選擇模型后,能夠直接向模型發送問題并獲得實時反饋。對話內容在聊天框中即時顯示,支持多輪交互,開發者可以迅速獲取所需答案,提升工作效率。

3. 下載速度與進度監控

在下載過程中,DeepSeek 會實時顯示下載的速度和總進度。無論模型的大小如何,用戶都能實時了解進度,并根據反饋調整操作,提升體驗。

4. 代碼塊高亮與一鍵復制

響應中的代碼塊會自動高亮顯示,用戶可直接復制代碼,方便二次使用。無論是復制單段代碼,還是復制整個對話記錄,DeepSeek 都能提供簡潔的操作方式。

5. 靈活的文本交互功能

聊天框和輸入框都支持直觀的文本操作,用戶可以右鍵點擊復制或粘貼內容,提升交互流暢度。此外,聊天內容中的代碼塊也能輕松復制,方便進行后續處理。

3.運行效果:

原CMD窗口界面:–>>>>

在這里插入圖片描述

GUI客戶端交互界面–>>>>

在這里插入圖片描述

4. 總結:

Ollama 本地客戶端 是一款針對開發者的強大工具,它不僅提供了易于操作的圖形界面,還集成了強大的模型管理與交互功能。通過這款工具,開發者能夠輕松獲取、管理并與本地模型進行高效互動。對于那些希望簡化 AI 模型操作、提升開發效率的用戶來說,這款客戶端無疑是一個值得嘗試的利器。

隨著人工智能技術的不斷發展,Ollama 本地客戶端將繼續更新和優化,帶來更多的功能和更好的用戶體驗。無論是新手開發者,還是資深專家,都能在這款工具中找到適合自己的功能,提升工作效率,專注于更具創意的開發工作。

5. 相關源碼:

import tkinter as tk
from tkinter import ttk, messagebox
import requests
import threading
import json
import webbrowser
from tkinter import scrolledtext
import time
import tkinter.font as font# Ollama API 地址
OLLAMA_API_URL = "http://localhost:11434/api"# 定義顏色常量,使用多彩顏色方案
BG_COLOR = "#f5f5f5"  # 背景色
FG_COLOR = "#333333"  # 前景色
BUTTON_BG_COLORS = ["#00C2FE", "#6CE264", "#FF3A48", "#FF8A30","#84BDFE"]  # 按鈕背景色數組
BUTTON_HOVER_BG_COLORS = ["#0087B1", "#1E7F18", "#B7000D", "#BE5200","#0059BE"]  # 按鈕懸停背景色數組
BUTTON_FG_COLOR = "white"  # 按鈕前景色
LABEL_BG_COLOR = "#e0e0e0"  # 標簽背景色
CODE_BG_COLOR = "#f8f9fa"  # 代碼塊背景色class OllamaClient:def __init__(self, root):self.root = rootself.root.title("Ollama GUI 客戶端")self.root.configure(bg=BG_COLOR)# 使窗口在桌面居中self.center_window()# 創建界面組件self.create_widgets()# 初始化模型列表self.update_model_list()# 下載取消標志位self.cancel_download = False# 關閉程序標志位self.cancel_APP = False# 綁定窗口關閉事件self.root.protocol("WM_DELETE_WINDOW", self.on_close)def center_window(self):# 獲取屏幕寬度和高度screen_width = self.root.winfo_screenwidth()screen_height = self.root.winfo_screenheight()# 窗口寬度和高度window_width = 800window_height = 600# 計算窗口左上角的坐標x = (screen_width - window_width) // 2y = (screen_height - window_height) // 2# 設置窗口的位置和大小self.root.geometry(f"{window_width}x{window_height}+{x}+{y}")def create_widgets(self):# 使用 grid 布局管理器self.root.columnconfigure(0, weight=1)self.root.rowconfigure(1, weight=1)# 頂部框架,用于放置模型選擇和下載相關組件top_frame = tk.Frame(self.root, bg=BG_COLOR)top_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew")top_frame.columnconfigure(0, weight=1)# 模型選擇下拉框self.model_combobox = ttk.Combobox(top_frame, background=LABEL_BG_COLOR)self.model_combobox.grid(row=0, column=0, padx=10, sticky="w")# 打開模型庫按鈕open_library_button = tk.Button(top_frame, text="打開模型庫", command=self.open_model_library,bg=BUTTON_BG_COLORS[0], fg=BUTTON_FG_COLOR,width=10, height=1)open_library_button.grid(row=0, column=1, padx=10)open_library_button.bind("<Enter>", lambda e: e.widget.config(bg=BUTTON_HOVER_BG_COLORS[0]))open_library_button.bind("<Leave>", lambda e: e.widget.config(bg=BUTTON_BG_COLORS[0]))# 下載模型按鈕self.download_button = tk.Button(top_frame, text="下載模型", command=self.download_model,bg=BUTTON_BG_COLORS[1], fg=BUTTON_FG_COLOR,width=10, height=1)self.download_button.grid(row=0, column=2, padx=10)self.download_button.bind("<Enter>", lambda e: e.widget.config(bg=BUTTON_HOVER_BG_COLORS[1]))self.download_button.bind("<Leave>", lambda e: e.widget.config(bg=BUTTON_BG_COLORS[1]))# 刪除模型按鈕self.delete_button = tk.Button(top_frame, text="刪除模型", command=self.delete_model,bg=BUTTON_BG_COLORS[2], fg=BUTTON_FG_COLOR,width=10, height=1)self.delete_button.grid(row=0, column=3, padx=10)self.delete_button.bind("<Enter>", lambda e: e.widget.config(bg=BUTTON_HOVER_BG_COLORS[2]))self.delete_button.bind("<Leave>", lambda e: e.widget.config(bg=BUTTON_BG_COLORS[2]))# 下載進度條及相關信息框架self.download_frame = tk.Frame(self.root, bg=BG_COLOR)self.download_frame.grid(row=2, column=0, padx=10, pady=5, sticky="ew")self.download_frame.grid_forget()self.download_progress = ttk.Progressbar(self.download_frame, orient="horizontal", length=300, mode="determinate")self.download_progress.pack(side=tk.LEFT, padx=10)self.download_info_label = tk.Label(self.download_frame, text="", bg=LABEL_BG_COLOR, fg=FG_COLOR)self.download_info_label.pack(side=tk.LEFT, padx=10)# 創建字體對象title_font = font.Font(family="黑體", size=12)# 聊天記錄顯示框,使用 scrolledtext 增加滾動條self.chat_text = scrolledtext.ScrolledText(self.root, width=80, height=20, bg=LABEL_BG_COLOR, fg=FG_COLOR)self.chat_text.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")self.chat_text.bind("<Button-3>", self.show_chat_context_menu)self.chat_text.tag_configure("title", font=title_font)self.chat_text.tag_configure("code", background=CODE_BG_COLOR)# 輸入框使用 scrolledtextself.input_text = scrolledtext.ScrolledText(self.root, width=80, height=5, bg=LABEL_BG_COLOR, fg=FG_COLOR)self.input_text.grid(row=3, column=0, padx=10, pady=10, sticky="ew")self.input_text.bind("<Button-3>", self.show_input_context_menu)# 創建一個新的框架來放置發送按鈕和清除按鈕button_frame = tk.Frame(self.root, bg=BG_COLOR)button_frame.grid(row=4, column=0, padx=10, pady=10, sticky="e")# 發送按鈕self.send_button = tk.Button(button_frame, text="發送", command=self.send_message,bg=BUTTON_BG_COLORS[3], fg=BUTTON_FG_COLOR,width=10, height=1)self.send_button.grid(row=0, column=0, padx=10)self.send_button.bind("<Enter>", lambda e: e.widget.config(bg=BUTTON_HOVER_BG_COLORS[3]))self.send_button.bind("<Leave>", lambda e: e.widget.config(bg=BUTTON_BG_COLORS[3]))# 清空聊天記錄按鈕self.clear_button = tk.Button(button_frame, text="清空聊天", command=self.clear_chat,bg=BUTTON_BG_COLORS[4], fg=BUTTON_FG_COLOR,width=10, height=1)self.clear_button.grid(row=0, column=1, padx=10)self.clear_button.bind("<Enter>", lambda e: e.widget.config(bg=BUTTON_HOVER_BG_COLORS[4]))self.clear_button.bind("<Leave>", lambda e: e.widget.config(bg=BUTTON_BG_COLORS[4]))def update_model_list(self):try:response = requests.get(f"{OLLAMA_API_URL}/tags")if response.status_code == 200:models = [model["name"] for model in response.json().get("models", [])]self.model_combobox['values'] = modelsif models:self.model_combobox.set(models[0])except Exception as e:messagebox.showerror("錯誤", f"獲取模型列表失敗: {str(e)}")def open_model_library(self):webbrowser.open("https://ollama.com/library")def download_model(self):# 創建自定義輸入對話框并居中顯示dialog = tk.Toplevel(self.root)dialog.title("下載模型")dialog.geometry("300x150")dialog.configure(bg=BG_COLOR)dialog.attributes("-topmost", True)# 使對話框居中dialog.update_idletasks()width = dialog.winfo_width()height = dialog.winfo_height()x = (self.root.winfo_screenwidth() // 2) - (width // 2)y = (self.root.winfo_screenheight() // 2) - (height // 2)dialog.geometry(f"{width}x{height}+{x}+{y}")tk.Label(dialog, text="請輸入要下載的模型名稱:", bg=BG_COLOR, fg=FG_COLOR).pack(pady=20)model_entry = tk.Entry(dialog, bg=LABEL_BG_COLOR, fg=FG_COLOR)model_entry.pack(pady=10)def start_download():model_name = model_entry.get()if model_name:dialog.destroy()self.download_frame.grid()self.cancel_download = False  # 重置取消標志位threading.Thread(target=self._download_model_thread, args=(model_name,)).start()download_btn = tk.Button(dialog, text="開始下載", command=start_download,bg=BUTTON_BG_COLORS[1], fg=BUTTON_FG_COLOR)download_btn.pack(pady=10)download_btn.bind("<Enter>", lambda e: e.widget.config(bg=BUTTON_HOVER_BG_COLORS[1]))download_btn.bind("<Leave>", lambda e: e.widget.config(bg=BUTTON_BG_COLORS[1]))def on_close(self):# 設置下載取消標志self.cancel_download = Trueself.cancel_APP = True# 關閉主窗口self.root.destroy()def _download_model_thread(self, model_name):try:data = {"name": model_name}response = requests.post(f"{OLLAMA_API_URL}/pull", json=data, stream=True)if response.status_code == 200:total_size = Nonedownloaded_size = 0start_time = time.time()prev_downloaded = 0prev_progress = 0prev_time = start_timeself.download_progress['value'] = 0for line in response.iter_lines():if self.cancel_download:  # 檢查取消標志位messagebox.showinfo("提示", "下載已取消")breakif line:try:chunk = line.decode('utf-8')data = json.loads(chunk)if 'total' in data:total_size = data['total']if 'completed' in data:downloaded_size = data['completed']if total_size:progress = (downloaded_size / total_size) * 100current_time = time.time()# 設置進度更新閾值和時間間隔if progress - prev_progress >= 1 or current_time - prev_time >= 0.5:elapsed_time = current_time - start_timeif elapsed_time > 0:speed = (downloaded_size - prev_downloaded) / elapsed_time / 1024# 根據文件大小動態調整單位if total_size / (1024 * 1024 * 1024) >= 1:total_size_gb = total_size / (1024 * 1024 * 1024)downloaded_size_gb = downloaded_size / (1024 * 1024 * 1024)info_text = f"速度: {speed:.2f} KB/s, 已下載: {downloaded_size_gb:.2f} GB, 總大小: {total_size_gb:.2f} GB, 進度: {progress:.2f}%"else:total_size_kb = total_size / 1024downloaded_size_kb = downloaded_size / 1024info_text = f"速度: {speed:.2f} KB/s, 已下載: {downloaded_size_kb:.2f} KB, 總大小: {total_size_kb:.2f} KB, 進度: {progress:.2f}%"self.download_info_label.config(text=info_text)prev_downloaded = downloaded_sizeself.download_progress['value'] = progressself.root.update_idletasks()prev_progress = progressprev_time = current_timeexcept Exception as e:messagebox.showerror("錯誤", f"解析下載進度出錯: {str(e)}")if not self.cancel_download:messagebox.showinfo("成功", "模型下載成功")self.update_model_list()else:messagebox.showerror("錯誤", f"模型下載失敗: {response.text}")except Exception as e:messagebox.showerror("錯誤", f"發生異常: {str(e)}")finally:self.download_frame.grid_forget()def delete_model(self):model_name = self.model_combobox.get()if model_name:try:data = {"model": model_name}print(f"嘗試刪除模型: {model_name}")  # 打印要刪除的模型名稱response = requests.delete(f"{OLLAMA_API_URL}/delete", json=data)print(f"請求響應狀態碼: {response.status_code}")  # 打印響應狀態碼print(f"請求響應內容: {response.text}")  # 打印響應內容if response.status_code == 200:messagebox.showinfo("成功", "模型刪除成功")self.update_model_list()else:messagebox.showerror("錯誤", f"模型刪除失敗: {response.text}")except Exception as e:messagebox.showerror("錯誤", f"發生異常: {str(e)}")else:messagebox.showwarning("警告", "請選擇要刪除的模型")# 在 OllamaClient 類中修改 send_message 方法def send_message(self):message = self.input_text.get(1.0, tk.END).strip()if message:model_name = self.model_combobox.get()if model_name:# 使用線程來執行推理任務threading.Thread(target=self._send_message_thread, args=(message, model_name)).start()else:messagebox.showwarning("警告", "請選擇要使用的模型")def _send_message_thread(self, message, model_name):try:start_time = time.time()  # 記錄開始時間data = {"model": model_name,"prompt": message}# 使用 stream=True 開啟流式響應response = requests.post(f"{OLLAMA_API_URL}/generate", json=data, stream=True)if response.status_code == 200:self.chat_text.insert(tk.END, f"問題: {message}\n","title")end_time = time.time()  # 記錄結束時間inference_time = end_time - start_time  # 計算推理時間self.chat_text.insert(tk.END, f"\n思考時間: {inference_time:.2f} 秒\n",)self.root.update_idletasks()  # 更新界面full_response = ""chunk_count = 0for line in response.iter_lines():if self.cancel_APP:  # 檢查取消標志位breakif line:try:chunk = line.decode('utf-8')data = json.loads(chunk)part = data.get("response", "")part = part.replace("<think>", "").replace("</think>", "")full_response += partself.chat_text.insert(tk.END, part)chunk_count += 1if chunk_count % 10 == 0:  # 每接收 10 個數據塊更新一次界面self.root.update_idletasks()except Exception as e:messagebox.showerror("錯誤", f"解析響應數據出錯: {str(e)}")self.root.update_idletasks()  # 確保最后一次更新界面self.input_text.delete(1.0, tk.END)self.highlight_code()else:messagebox.showerror("錯誤", f"請求失敗: {response.text}")except Exception as e:messagebox.showerror("錯誤", f"發生異常: {str(e)}")def clear_chat(self):self.chat_text.delete(1.0, tk.END)def show_chat_context_menu(self, event):context_menu = tk.Menu(self.root, tearoff=0)context_menu.add_command(label="復制", command=lambda: self.copy_chat_text())# 獲取點擊位置的標簽tags = self.chat_text.tag_names(tk.CURRENT)if "code" in tags:context_menu.add_command(label="復制當前代碼塊", command=lambda: self.copy_current_code_block())context_menu.add_command(label="復制所有代碼塊", command=lambda: self.copy_code_block())context_menu.post(event.x_root, event.y_root)def copy_chat_text(self):selected_text = self.chat_text.get(tk.SEL_FIRST, tk.SEL_LAST)if selected_text:self.root.clipboard_clear()self.root.clipboard_append(selected_text)def copy_code_block(self):tag_ranges = self.chat_text.tag_ranges("code")if tag_ranges:code_text = ""for i in range(0, len(tag_ranges), 2):start = tag_ranges[i]end = tag_ranges[i + 1]code_text += self.chat_text.get(start, end)self.root.clipboard_clear()self.root.clipboard_append(code_text)def copy_current_code_block(self):tag_ranges = self.chat_text.tag_ranges("code")current_pos = self.chat_text.index(tk.CURRENT)print(f"當前鼠標位置: {current_pos}")  # 打印當前鼠標位置用于調試code_text = None  # 初始化 code_text 為 Nonefor i in range(0, len(tag_ranges), 2):start = str(tag_ranges[i])  # 將 _tkinter.Tcl_Obj 轉換為字符串end = str(tag_ranges[i + 1])  # 將 _tkinter.Tcl_Obj 轉換為字符串print(f"代碼塊范圍: {start} - {end}")  # 打印代碼塊范圍用于調試if start <= current_pos <= end:code_text = self.chat_text.get(start, end)breakif code_text is not None:try:self.root.clipboard_clear()self.root.clipboard_append(code_text)print("代碼塊復制成功")except tk.TclError as e:print(f"剪貼板操作失敗: {e}")else:print("未找到包含當前位置的代碼塊")def show_input_context_menu(self, event):context_menu = tk.Menu(self.root, tearoff=0)context_menu.add_command(label="復制", command=lambda: self.copy_input_text())context_menu.add_command(label="粘貼", command=lambda: self.paste_input_text())context_menu.post(event.x_root, event.y_root)def copy_input_text(self):selected_text = self.input_text.get(tk.SEL_FIRST, tk.SEL_LAST)if selected_text:self.root.clipboard_clear()self.root.clipboard_append(selected_text)def paste_input_text(self):clipboard_text = self.root.clipboard_get()if clipboard_text:self.input_text.insert(tk.INSERT, clipboard_text)def highlight_code(self):content = self.chat_text.get(1.0, tk.END)start_index = 0while True:start = content.find("===", start_index)if start == -1:breakend = content.find("===", start + 3)if end == -1:breakstart_tag = f"1.0+{start}c"end_tag = f"1.0+{end + 3}c"self.chat_text.tag_add("code", start_tag, end_tag)print(f"代碼塊范圍: {start_tag} - {end_tag}")  # 調試信息,打印代碼塊范圍start_index = end + 3if __name__ == "__main__":root = tk.Tk()client = OllamaClient(root)root.mainloop()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/70177.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/70177.shtml
英文地址,請注明出處:http://en.pswp.cn/web/70177.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenMv識別色塊通過串口發給STM32

硬件連接 1、Openmv端 這里OpenMV端僅作為數據的發送端,所以只需要共地,以及OpenMV的TX(P4)與開發板的RX端連接即可。 2、STM32端 將開發板連接STM芯片RX端與轉串口TX端的跳帽取下,再將OpenMV的TX端(P4)與STM的RX連接。如果使用USB轉TTL則將TTL的RX端與STM的TX端連接…

以太網交換基礎(涵蓋二層轉發原理和MAC表的學習)

在當今的網絡世界中&#xff0c;以太網交換技術是局域網&#xff08;LAN&#xff09;的核心組成部分。無論是企業網絡、學校網絡還是家庭網絡&#xff0c;以太網交換機都扮演著至關重要的角色。本文將詳細介紹以太網交換的基礎知識&#xff0c;包括以太網協議、幀格式、MAC地址…

菜鳥之路Day15一一IO流(一)

菜鳥之路Day15一一IO流&#xff08;一&#xff09; 作者&#xff1a;blue 時間&#xff1a;2025.2.8 文章目錄 菜鳥之路Day15一一IO流&#xff08;一&#xff09;0.概述1.初識IO流1.1.什么是IO流&#xff1f;1.2.IO流的作用1.3.IO流的分類 2.IO流的體系結構3.字節輸出流的基本…

汽車零部件開發應該具備哪些編程思維?

目錄 1、功能安全思維 2、實時性與確定性思維 3、可靠性和冗余思維 4、硬件軟件協同思維 5、CAN總線通信思維 6、故障診斷和自診斷思維 7、功耗優化思維 8、軟件更新和版本管理思維 9、用戶體驗與安全性思維 汽車零部件開發中&#xff0c;嵌入式軟件在車輛系統中的作用…

idea拉取合并后的分支

文章目錄 遠程拉取代碼.更新本地庫拉取后本地庫就有了合并后的代碼 遠程拉取代碼.更新本地庫 拉取后本地庫就有了合并后的代碼

1-18 GIT設置公鑰

1-1 GIT如何設置公鑰 1.0 注冊賬號 這個應該都是會的&#xff0c;就不做介紹了 2.0 設置公鑰 PWD的作用是查看文件的路徑 ssh-keygen -t ed25519 -C "Gitee SSH Key" 讀取公鑰文件&#xff1a; cat ~/.ssh/id_ed25519.pub 3.0 測試 查看綁定的用戶名和郵箱&#xff1…

【MySQL】 常見數據類型

MySQL常見數據類型 1.整數類型2.浮點數類型3.定點數類型4.bit類型5.字符串類型 5.1char和varchar類型5.2日期類型和時間類型5.3enum和set類型 1.整數類型 整數類型默認都是有符號整數 類型名稱 字節數 類型說明 tinyint 1 帶符號的范圍-128127&#xff0c;無符號范圍…

DeepSeek 部署中的常見問題及解決方案

DeepSeek 作為一款智能語義搜索框架&#xff0c;其本地化部署在實際操作中可能因環境配置、權限管理、硬件資源等因素遇到多種問題。本文結合當前市面上的實踐經驗&#xff0c;整合了部署中的常見問題及解決方案&#xff0c;幫助用戶高效排查和優化部署流程。 一、權限不足問題…

《機器學習數學基礎》補充資料:求解線性方程組的克拉默法則

《機器學習數學基礎》中并沒有將解線性方程組作為重點&#xff0c;只是在第2章2.4.2節做了比較完整的概述。這是因為&#xff0c;如果用程序求解線性方程組&#xff0c;相對于高等數學教材中強調的手工求解&#xff0c;要簡單得多了。 本文是關于線性方程組的拓展&#xff0c;供…

Jenkins介紹

什么是Jenkins Jenkins 是一個開源的自動化服務器&#xff0c;主要用于持續集成和持續交付&#xff08;CI/CD&#xff09;。它幫助開發團隊自動化構建、測試和部署軟件&#xff0c;從而提高開發效率和軟件質量。 如果一個系統是前后端分離的開發模式&#xff0c;在集成階段會需…

module ‘cv2.dnn‘ has no attribute ‘DictValue‘解決辦法

module ‘cv2.dnn‘ has no attribute ‘DictValue‘解決辦法 pip install opencv-python4.7.0.72 -i https://pypi.tuna.tsinghua.edu.cn/simple 測試&#xff1a; python -c"import cv2"

【全棧】SprintBoot+vue3迷你商城-細節解析(2):分頁

【全棧】SprintBootvue3迷你商城-細節解析&#xff08;2&#xff09;&#xff1a;分頁 往期的文章都在這里啦&#xff0c;大家有興趣可以看一下 后端部分&#xff1a; 【全棧】SprintBootvue3迷你商城&#xff08;1&#xff09; 【全棧】SprintBootvue3迷你商城&#xff08;…

kubeadm拉起的k8s集群證書過期的做法集群已奔潰也可以解決

kubeadm拉起的k8s集群證書過期的做法 這個是很久之前遇到的了&#xff0c;今天有空&#xff08;心血來潮&#xff09;就都回憶回憶寫在這里為愛發光&#xff0c;部分內容來自arch先生&#xff08;死黨&#xff09;的幫助。有時候有很多部門提了建k8s的需求&#xff0c;有些是臨…

Webpack 基礎入門

一、Webpack 是什么 Webpack 是一款現代 JavaScript 應用程序的靜態模塊打包工具。在 Web 開發中&#xff0c;我們的項目會包含各種類型的文件&#xff0c;如 JavaScript、CSS、圖片等。Webpack 可以將這些文件打包成一個或多個文件&#xff0c;以便在瀏覽器中高效加載。它就像…

torchsparse安裝過程的問題

1、項目要求torchsparse githttps://github.com/mit-han-lab/torchsparse.gitv1.4.0 2、torch1.8.1cu111 nvcc--version&#xff1a;11.1 這個版本的cuda匹配的gcc、g經常是7.5。設置為7.5. &#xff08;這個gcc、g版本修改不一定&#xff0c;可以先進行后面的&#xff0c…

嵌入式音視頻開發(二)ffmpeg音視頻同步

系列文章目錄 嵌入式音視頻開發&#xff08;零&#xff09;移植ffmpeg及推流測試 嵌入式音視頻開發&#xff08;一&#xff09;ffmpeg框架及內核解析 嵌入式音視頻開發&#xff08;二&#xff09;ffmpeg音視頻同步 嵌入式音視頻開發&#xff08;三&#xff09;直播協議及編碼器…

iOS App的啟動與優化

App的啟動流程 App啟動分為冷啟動和熱啟動 冷啟動&#xff1a;從0開始啟動App熱啟動&#xff1a;App已經在內存中&#xff0c;但是后臺還掛著&#xff0c;再次點擊圖標啟動App。 一般對App啟動的優化都是針對冷啟動。 App冷啟動可分為三個階段&#xff1a; dyld&#xff1a…

oppo,湯臣倍健,康冠科技25屆春招內推

oppo&#xff0c;湯臣倍健&#xff0c;康冠科技25屆春招內推 ①康冠科技25屆春招 【職位】算法、軟件、硬件、技術&#xff0c;結構設計&#xff0c;供應鏈&#xff0c;產品&#xff0c;職能&#xff0c;商務 【一鍵內推】https://sourl.cn/2Mm9Lk 【內推碼】EVBM88 ②湯臣倍健…

centos 9 時間同步服務

在 CentOS 9 中&#xff0c;默認的時間同步服務是 chrony&#xff0c;而不是傳統的 ntpd。 因此&#xff0c;建議使用 chrony 來配置和管理時間同步。 以下是使用 chrony 配置 NTP 服務的步驟&#xff1a; 1. 安裝 chrony 首先&#xff0c;確保系統已安裝 chrony。 在 CentOS…

解鎖 Python 導入系統:從基礎到進階的深度指南

本文全面解讀 Python 導入系統&#xff0c;從導入機制的基礎概念&#xff0c;如模塊、包的導入方式&#xff0c;到查找、加載模塊的詳細過程&#xff0c;再到導入系統的高級特性和應用場景&#xff0c;通過豐富示例、直觀圖表和對比分析&#xff0c;助你深入理解并熟練運用導入…