Yoru Karu Studio
程式設計學習筆記 | 生活心得程式設計學習筆記 | 生活心得
前言 Django 3.0 開始支持異步視圖,Django 3.1 正式穩定。這為 I/O 密集型應用帶來了巨大的性能提升。
傳統同步視圖的問題:
def user_dashboard(request): # 串行執行,總耗時相加 user = User.objects.get(id=request.user.id) # 50ms orders = Order.objects.filter(user=user).all() # 100ms notifications = Notification.objects.filter(user=user).all() # 80ms # 總耗時:230ms return render(request, 'dashboard.html', { 'user': user, 'orders': orders, 'notifications': notifications, })異步視圖的優勢:
async def user_dashboard(request): # 並行執行,總耗時取最慢的那個 user, orders, notifications = await asyncio.gather( User.objects.aget(id=request.user.id), # 50ms Order.objects.filter(user=user).all(), # 100ms Notification.objects.filter(user=user).all(), # 80ms ) # 總耗時:100ms(取最慢的那個) return render(request, 'dashboard.html', { 'user': user, 'orders': orders, 'notifications': notifications, })性能提升:響應時間減少 56%(230ms → 100ms)!
前言 當你部署 Django 應用時,可能會看到兩種不同的啟動方式:
# 傳統方式:WSGI gunicorn myproject.wsgi:application # 新方式:ASGI uvicorn myproject.asgi:application這兩者有什麼區別?什麼時候該用哪個?
想像一個實際場景:
# 傳統同步視圖(WSGI) def get_user_data(request): user = User.objects.get(id=request.user.id) # 數據庫查詢:100ms posts = Post.objects.filter(user=user) # 數據庫查詢:150ms comments = Comment.objects.filter(user=user) # 數據庫查詢:120ms # 總耗時:370ms(串行執行) return JsonResponse({ 'user': user, 'posts': posts, 'comments': comments, }) # 異步視圖(ASGI) async def get_user_data(request): # 並行執行三個查詢! user, posts, comments = await asyncio.gather( User.objects.aget(id=request.user.id), # 100ms Post.objects.filter(user=user).all(), # 150ms Comment.objects.filter(user=user).all(), # 120ms ) # 總耗時:150ms(並行執行,取最慢的那個) return JsonResponse({ 'user': user, 'posts': posts, 'comments': comments, })異步能將響應時間從 370ms 降到 150ms! 但這需要 ASGI 的支持。
前言 在多線程環境中,如何讓每個線程擁有自己獨立的資料副本?這是一個經典的並發編程問題。
想像一個實際場景:
# ❌ 全局變量會被所有線程共享 current_user = None def process_request(request): global current_user current_user = request.user # 線程 A 設置 do_some_work() # 在這期間,線程 B 可能修改 current_user! send_email(current_user) # 可能發給錯誤的用戶!問題:
線程 A 處理用戶 Alice 的請求 線程 B 同時處理用戶 Bob 的請求 兩個線程共享同一個 current_user 變量 結果:Alice 的郵件可能發給 Bob! 解決方案:使用 threading.local
# ✅ 每個線程有自己的 current_user thread_local = threading.local() def process_request(request): thread_local.current_user = request.user # 線程隔離 do_some_work() # 其他線程不會影響 send_email(thread_local.current_user) # 安全!這篇文章將深入探討 threading.local 的實現原理,以及 Django 如何利用它保證線程安全。
為什麼 RAG 是 LLM 時代的必備技術? 想像大語言模型(LLM)是一位擁有淵博知識的頂尖學者。
預訓練就像這位學者在學校裡閱讀了數萬本書,形成了強大的語言能力和世界觀。 然而,他參加的是閉卷考試(直接提問 LLM):他無法回憶起所有細節,容易遺忘最近發生的事,也無法參考他從未讀過的公司內部文件。 RAG的作用,就是將閉卷考試變為開卷考試。當問題出現時,先讓他迅速查閱相關的參考資料,然後根據手邊的文件作答,確保答案的準確性和時效性。 理解 RAG,是從「玩轉」LLM 提升到「應用」LLM 解決實際業務問題的關鍵。
🧠 LLM 的三大知識困境 在沒有 RAG 之前,直接使用預訓練 LLM 進行問答,面臨三大挑戰:
1. 幻覺(Hallucination)
當模型被問到一個它不確定的細節時,它傾向於編造聽起來合理但事實上錯誤的資訊。這源於其訓練目標是「產生最可能的下一個詞」,而非「產生事實準確的詞」。 2. 知識過時(Knowledge Staleness)
LLM 的知識截止日期是其最後一次預訓練的時間點。對於訓練之後發生的新事件、最新財報、或法規變動,LLM 無法獲知。 範例:你問 2024 年的模型誰贏得了 2025 年的奧斯卡獎,它會根據過去的資訊來猜測或給出過時的答案。 3. 知識隔離(Knowledge Isolation)
LLM 無法存取你的專屬領域知識,例如公司的產品手冊、內部郵件、私有程式碼文件或未公開的研究報告。若要讓 LLM 基於這些文件回答,傳統方法成本過高。 🔎 RAG(檢索增強生成)是什麼? RAG 是一種將檢索系統 (Retriever) 和 生成模型 (Generator) 結合的技術,其目標是:在 LLM 生成回覆之前,先從外部知識庫中檢索相關的片段(Context),然後將這些片段作為提示詞的一部分輸入給 LLM,引導模型生成基於事實的答案。
RAG 的核心:將答案的依據外部化 特性 傳統 LLM(閉卷) RAG LLM(開卷) 知識來源 模型參數(記憶) 外部知識庫(參考資料) 問答流程 問句 → 直接生成答案 問句 → 檢索相關資料 → 根據資料生成答案 知識更新 需重新訓練或微調模型 只需更新外部資料庫 準確性 依賴記憶,易產生幻覺 基於事實,準確性高 📐 RAG 的標準架構流程 RAG 系統分為兩個主要階段:索引階段(預處理)和運行階段(問答)。
為什麼延遲如此重要?
想像你在使用一個應用程式,每次點擊都要等待好幾秒才有反應。即使功能再強大,這樣的體驗也會讓人抓狂。
延遲(Latency)是衡量系統效能最直接的指標,而尾延遲(Tail Latency)更是決定用戶體驗的關鍵因素。
認證機制的重要性
在現代 API 設計中,選擇合適的認證機制是確保系統安全的第一步。不同的認證方式有著截然不同的特性,適用於不同的場景。
讓我們深入比較 API Key、Session 和 JWT 這三種最常用的認證方式。