最新[AI] Prompt 的眉角:讓你的 LLM 不再雞同鴨講
前言自從大型語言模型(LLM)普及之後,大家是不是都開始想辦法把 AI 整合到自己的工作流程裡?從寫程式、除錯、文件整理到發想,LLM 真的超好用。但是,有沒有遇過你給它一個指令,它卻回覆得牛頭不對馬嘴,讓你覺得它根本聽不懂你在說什麼?
這種「雞同鴨講」的狀況,其實大部分時候不是模型不夠聰明,而是我們給的「說明書」不夠清楚。這個說明書,就是我們常說的 Prompt。
Prompt 不只是單純輸入問題,它是一種跟 LLM 溝通的藝術,也是一種工程。寫得好的 Prompt,能讓 LLM 成為你的神隊友;寫得不好,就變成一個只能給你模糊答案的黑箱。今天想跟大家分享一些我在實務上常用、而且很有效的 Prompt 技巧,希望能幫大家跟 LLM 合作得更順暢。
怎麼跟 LLM 溝通最有效?從角色設定開始想像一下,你要跟一個同事請教問題,你會直接丟一句「請解釋區塊鏈」嗎?通常不會對不對?你會先設定情境:「嘿,我是新來的,對區塊鏈有點好奇,可以請你用資深工程師的角度,跟我這個新手解釋一下嗎?」
對 LLM 也是一樣!給 LLM 一個明確的「角色(Role)」,它會更好地理解你的意圖,並以該角色應有的知 ...
[AI] 把 token 當成錢來算,context window 不是越大越好
前言每次看 API 帳單或看到 Token 耗盡的錯誤時,是不是都會有一種「這到底是什麼東西在計費」的懵懵懂懂?
LLM 的 Token 機制和 Context Window,聽起來很高深,但其實就是這兩個東西在決定你的程式會花多少錢、會不會卡。我今天不講大道理,只用最實際的方式拆解它們,還有我在實務上踩過的坑。
Token 到底在算什麼?最常見的迷思是:Token 等於一個英文字母,或等於一個中文字。
其實 Token 是模型底層的「碎塊」。英文大概 4 個字元等於 1 個 Token,中文因為每個字佔用空間較大,通常 1 個中文字會被拆成 1 到 2 個 Token(視語言模型而定)。
舉個例子,Prompt 寫這樣:
1請將以下文章翻譯成英文:今天天氣很好。
這句話大約會消耗 15-20 個 Token(Input token)。你會發現,中文的 Token 消耗速度比英文快很多,這也是為什麼台灣工程師特別需要注意的地方。
Context Window 不是越大越好Context Window 就是模型一次能記住的「工作記憶」容量。你可以想像成你開會時能同時記憶的紙張數量。
早 ...
[學習筆記] 技術筆記要寫給未來的自己看
前言學技術時,很容易一直收藏文章、影片和文件。
但收藏久了會發現,資料越來越多,真正用得到的時候卻常常找不到。
後來我覺得,技術筆記不一定要寫得很完整,但要能讓未來的自己快速想起來:「當時我到底怎麼解的?」
不要只貼連結只貼連結的筆記,短期看起來很快。
例如:
1Docker 教學:https://example.com/docker
但過一段時間後,可能會遇到幾個問題:
忘記這篇連結重點是什麼。
網站失效。
文章內容太長,不知道當初看的是哪一段。
當時的問題情境已經忘了。
所以我會至少補一句自己的摘要。
1這篇主要是在講 Docker volume,解決 container 重建後資料消失的問題。
這樣未來找回來時會快很多。
記錄問題情境技術筆記最有價值的部分,通常不是答案本身,而是問題情境。
例如:
123問題:本機可以連 DB,但部署到測試機後連線失敗。原因:測試機沒有設定正確的 connection string。解法:補上環境變數 Database__ConnectionString。
這種筆記下次遇到類似問題時,非常好用。
因為你不是只記得一個指令,而是記得完整判 ...
[後端] Log 不只是用來看錯誤
前言很多人一開始寫 log,都是在程式壞掉時才想到:
1Console.WriteLine("error");
或是:
1Console.WriteLine(ex.Message);
這當然比完全沒有 log 好,但如果系統真的在線上環境出問題,這種資訊通常還是不夠。
log 的價值不只是「看到錯誤」,更重要的是幫助我們還原當時發生了什麼事。
Log 要能串起流程假設使用者回報:「我按送出之後畫面一直失敗。」
如果 log 只有一行:
1System error
那幾乎沒有辦法判斷問題在哪。
比較有幫助的 log,至少要能讓我們串起流程:
12345Start creating order. userId=123Validate order request completed. userId=123Call payment service. userId=123, orderId=456Payment service timeout. userId=123, orderId=456Create order failed. userId=123, orderId ...
[工程分享] 重構不是看到不順眼就重寫
前言寫程式久了,總會看到一些讓人手癢的程式碼。
變數命名怪怪的、方法太長、邏輯繞來繞去,第一個反應可能是:「我想把它重寫掉。」
但重構不是單純把程式改成自己喜歡的樣子。
重構的目標應該是降低維護成本,而且不能改變原本行為。
重構前先確認目的我覺得重構前要先問:
這段程式現在造成什麼問題?
是讀不懂、難測試、容易出錯,還是擴充困難?
這次重構能解決哪個具體痛點?
有沒有測試可以保護行為不變?
如果答案只是「我覺得不漂亮」,那可能還不到需要重構的程度。
程式碼當然可以追求美感,但在工作專案裡,改動要有足夠理由。
小步調整比大爆改安全重構最怕一次改太多。
例如同時做:
改命名
拆方法
換設計模式
改資料結構
順便修 bug
這樣 review 很難看,出問題也很難定位。
比較安全的方式是小步調整:
1234先補測試再拆出方法再改善命名最後才調整結構
每一步都保持可執行、可驗證。
不要把修 bug 和重構混在一起修 bug 是改變錯誤行為。
重構是不改變行為,只改善內部結構。
如果兩件事混在同一個 commit 或 PR,未來追問題會比較麻煩。
比較好的做法是:
123commit ...
[後端] Cache 可以加速,也可能製造麻煩
前言Cache 是很常聽到的效能優化方式。
簡單來說,就是把常用的結果先存起來,下次需要時不用重新計算或重新查詢。
聽起來很美好,但 Cache 不是免費的。它可以讓系統變快,也可能讓資料變得難以理解。
Cache 解決的是重複成本假設某個 API 每次都要查很多資料、做很多計算,但結果短時間內不太會變。
這時候就可以考慮 Cache。
第一次請求:
1查資料庫 -> 計算 -> 回傳結果 -> 存入 Cache
下一次請求:
1從 Cache 取結果 -> 回傳
如果資料真的不常變,這樣可以省下很多成本。
最大問題是資料何時失效Cache 最麻煩的地方通常不是怎麼存,而是什麼時候要讓它失效。
例如商品資料被修改了,但 Cache 裡還留著舊資料。
使用者看到的就可能是:
12資料庫:新價格頁面:舊價格
這種問題常常比查詢慢更難排查。
所以加入 Cache 前,要先想清楚:
資料可以舊多久?
什麼情況要清掉 Cache?
Cache 清不掉時會造成多大影響?
使用者是否能接受短暫不一致?
TTL 是常見做法TTL 是 Time To Live,也就是 ...
[SQL] Index 是什麼?先用查書目錄的方式理解
前言剛開始接觸資料庫效能問題時,常常會聽到一句話:
「這個查詢很慢,可能要加 index。」
但 index 到底是什麼?為什麼加了它查詢就可能變快?
這篇先不鑽太深的資料結構,而是用比較直覺的方式整理 index 的基本概念。
Index 可以想成書的目錄假設你手上有一本很厚的書,想找「例外處理」這個主題。
如果沒有目錄,你只能從第一頁開始慢慢翻。
但如果有目錄,你可以先查目錄,找到相關章節在哪一頁,再直接翻過去。
資料庫的 index 概念也很像。
沒有 index 時,資料庫可能需要掃描整張表,逐筆檢查資料是否符合條件。
有 index 時,資料庫可以透過索引結構更快找到符合條件的資料。
最常見的使用情境假設有一張 Users 表:
123456CREATE TABLE Users ( Id INT PRIMARY KEY, Email VARCHAR(255), Name VARCHAR(100), CreatedAt DATETIME);
如果系統常常用 Email 查使用者:
123SELECT *FROM UsersWHERE Email = & ...
[Git] 分支策略不用一開始就搞得很複雜
前言很多人在學 Git 分支時,會看到各種流程圖:Git Flow、GitHub Flow、GitLab Flow。
這些流程都有它們的使用情境,但如果專案很小、團隊人數也不多,一開始就套很複雜的分支策略,反而會讓大家卡在流程上。
我覺得分支策略的重點不是名字,而是團隊能不能穩定交付。
最小可用的分支概念最簡單可以先分成兩種:
12main 穩定版本feature 開發中的功能分支
平常開發時,不直接在 main 上改。
而是開一個功能分支:
1git checkout -b feature/add-login-page
完成後送 PR,review 沒問題再合回 main。
這樣至少可以避免開發中的程式直接污染穩定分支。
分支名稱要看得懂分支名稱不用太華麗,但要能看出用途。
例如:
1234feature/add-search-pagefix/login-timeoutchore/update-dependenciesdocs/cloudflare-pages-guide
看到名稱時,至少能知道這個分支大概在做什麼。
比起:
1234testnewfix2hikari-b ...
[API] 錯誤處理不要只回傳失敗
前言在寫 API 的時候,很容易把成功流程寫得很完整,但錯誤流程只簡單回一句「失敗」。
例如:
1234{ "success": false, "message": "error"}
這種回應對使用者不友善,對前端不友善,對未來要查問題的自己也不友善。
這篇整理一下,我覺得 API 錯誤處理至少可以注意的幾件事。
錯誤訊息要能被理解錯誤訊息的第一個目的,是讓呼叫端知道發生了什麼事。
例如登入失敗時,如果只回:
123{ "message": "failed"}
前端很難判斷要顯示什麼,也不知道是帳號不存在、密碼錯誤,還是系統暫時異常。
可以改成比較明確的格式:
1234{ "code": "INVALID_CREDENTIALS", "message": "帳號或密碼錯誤"}
message 給人看,code 給程式判斷。
這樣前端可 ...
[API] 為什麼有時候需要版本控管?
前言API 一開始通常都很單純。
前端要什麼,後端就回什麼。
但當系統開始被更多人使用,API 一旦改動,就可能影響既有前端、App、第三方串接,甚至是已經發布出去的舊版本程式。
這時候就會遇到一個問題:API 要怎麼改,才不會把舊使用者弄壞?
什麼情況會破壞相容性?不是所有 API 修改都需要新版本。
例如新增一個 response 欄位,多數情況下不會破壞舊呼叫端:
12345{ "id": 1, "name": "Hikari", "email": "hikari@example.com"}
但以下這些改動就比較危險:
移除既有欄位。
改變欄位型別。
改變欄位名稱。
改變錯誤格式。
改變必要參數。
改變原本的業務規則。
例如原本 id 是數字:
123{ "id": 1}
突然改成字串:
123{ "id": "U001"}
對後端來說可能只是 ...
![[AI] Prompt 的眉角:讓你的 LLM 不再雞同鴨講](/img/covers/llm-prompt-techniques-practical-tips.jpg)
![[AI] 把 token 當成錢來算,context window 不是越大越好](/img/covers/token-cost-context-window.jpg)
![[學習筆記] 技術筆記要寫給未來的自己看](/img/covers/technical-note-habit.jpg)
![[後端] Log 不只是用來看錯誤](/img/covers/logging-basic.jpg)
![[工程分享] 重構不是看到不順眼就重寫](/img/covers/refactor-basic.jpg)
![[後端] Cache 可以加速,也可能製造麻煩](/img/covers/cache-basic.jpg)
![[SQL] Index 是什麼?先用查書目錄的方式理解](/img/covers/sql-index-basic.jpg)
![[Git] 分支策略不用一開始就搞得很複雜](/img/covers/branch-strategy.jpg)
![[API] 錯誤處理不要只回傳失敗](/img/covers/api-error-handling.jpg)
![[API] 為什麼有時候需要版本控管?](/img/covers/api-versioning.jpg)