Hello! 各位 AI 開發者大家好 👋
變成月刊了,這期內容繼續深入探討 AI 工程的核心: 評估、Context Engineering、Agent 和 RAG。
🚀 AI Evals 大辯論: 從 Claude Code 訪談引發的反思
你知道嗎? Claude Code 沒有做產品層級的系統化 Evals,是靠 Vibe 感覺開發的!
這場辯論始於 Anthropic Claude Code 創始人 Boris 在訪談中的坦白…
全文在我部落格,更多討論在我 Facebook 貼文。
🧭 官方 MCP Registry 發布
近期看到 MCP 官方出了一個 Registry,GitHub 也出了一個 Registry,這是在打架嗎?
不是的,讓我解釋一下 MCP Registry 的架構…
全文在我部落格,更多討論在我 Facebook 貼文。
🤖 Writing effective tools for agents — with agents
Anthropic 分享了他們如何最佳化 AI Agent 工具的實戰經驗,先快速做個原型,然後建立評估系統來測量工具效能。
工具設計的原則則包括:
- 少即是多: 不是工具越多越好。與其包裝現成 API endpoint 成為工具,不如設計幾個精心整合的高階工具。例如不要分開做 list_users、list_events、create_event,直接做一個 schedule_event 搞定所有事
- 命名空間很重要: 當工具變多時,清楚的命名規則能幫 Agent 選對工具。像 asana_search vs jira_search 這樣的前綴命名,效果比你想像的大
- 返回有意義的資訊: Agent 處理自然語言比處理低階的技術 id 更在行,使用這種人類也能看懂的格式,能大幅減少幻覺
- Token 效率最佳化: 實作分頁、過濾、截斷等機制,給工具加上 response_format 參數,讓 Agent 選擇要 “concise” 還是 “detailed” 的回應
- 錯誤訊息要有幫助: 與其丟出 “Error 404″,不如告訴 Agent: “找不到該用戶,請檢查拼寫或使用 search_user 工具先搜尋”
- 工具描述: 這個也需要用 Prompt Engineering 進行最佳化
另外還有一個重點是他們是如何最佳化 prompt 的? 他們分享了他們的 tool evaluation cookbook 評估程式碼。先準備 dataset,然後用這個 eval 去批次跑。這會評估你的工具描述,並給出摘要和回饋,你再依此回饋去改進你的工具。
📊 進階 context engineering:KV cache centric LLM 應用設計
看到超深入的 KV cache 最佳化文章,作者從 Manus 團隊的 Context Engineering 文章出發,深入探討如何用 KV cache centric 的思維來設計 LLM 應用,不只能大幅節省成本,也能提升用戶體驗。
🏗️ Cost Control: Scaling AI Without Going Broke
AI 成本控制的實戰指南。過去軟體的運算成本可忽略,但 GenAI 時代完全翻轉:模型是依 token 計費,隨著使用量增長,成本可能爆炸性增加。
文章提出的成本最佳化流程: 先證明價值和品質 → 固定功能和品質基準 → 再開始最佳化成本。而不是過早優化成本,結果功能還沒做好就先把自己搞死了。
八種降低成本的策略:
- 模型選擇(2-10倍省): 開發時用最強的模型快速驗證可行性,上線前系統性測試更小更便宜的模型。很多場景其實不需要最強模型
- Prompt 工程 (1.5-4倍省): 刪除冗餘指令、壓縮背景資料
- 精準檢索 (2-6倍省): RAG 系統常見的錯誤是塞太多不相關的內容給 LLM。調整相似度門檻、只給必要的資訊
- 工作流分解 (1.5-5倍省): 別用一個超大 prompt 做所有事,拆成 workflow: 簡單任務用便宜模型,複雜推理才用貴的,中間結果考慮快取
- Pre-processing 預處理 (3-20倍省): 事先跑好 Embedding、摘要等先存起來,不要每次請求都重算
- Batching 批次處理 (2倍省): OpenAI 等各家現在都有 Batch API 有 50% 折扣,適合非即時的大量處理
- Context 快取 (1.2-2倍省): 利用 LLM 供應商的 prompt caching 功能,重複的 prefix prompt 價格只有原先一成
- 商業策略 (最高 50% 省): 去找 LLM 供應商談承諾用量,可以有折扣,或是月花費超過 1-2 萬美金時考慮自己跑開源模型
🧩 Defeating Nondeterminism in LLM Inference
OpenAI 前 CTO Mira Murati 在新創 Thinking Machines 發表的首篇文章,探討 LLM 推論中的非確定性問題:為什麼溫度設 0,結果仍然不同?
簡單說,就是 LLM inference server 中,是採用 Batch 和其他平行請求一起推論的,而不同 Batching 形狀就會有不同結果,另一個原因是浮點數相加時,不同順序會有不同結果。
在 OpenAI 文件中,有提到如何做 Reproducible outputs 可重現的輸出。
不過呢,我現在認為對 AI 應用工程師不太重要了。一來新的推理模型也不允許我們設定溫度參數了,所以橫豎都有不確定性,二來如果你真的想要,那你可以實作 HTTP 層的快取:你就把整個 HTTP request/response 都記錄下來,只要碰到一樣的 request 參數,就重播之前的 response 即可,根本不需要再去問模型。
🌐 Why language models hallucinate
OpenAI 發表了一篇研究,解釋了 LLM 為什麼會如此自信地產生錯誤答案。他們認為和模型訓練時的評估方式有關。
現在的評估方法用了錯誤的誘因。就像選擇題考試,亂猜可能幸運得分,但留空一定零分。當模型只根據「準確率」評分時,等於鼓勵它猜測而不是誠實說「我不知道」。
解決方案就是: 答錯要扣更多分,適當表達不確定時給部分分數。就像有些考試答錯會倒扣,留空不答反而能得部分分數。目的就是訓練 AI 要學會說「我不知道」,而不只是學會更多知識。
Galileo 的這篇 Understanding Why Language Models Hallucinate? 可以作為更好的補充入門閱讀。
🛠️ How to Detect Hallucinations in Retrieval Augmented Systems: A Primer
看了上述資料,大家可能會以為模型幻覺常發生,這篇文章區分了兩種幻覺:
- 內在性(Intrinsic): 沒給任何 context,模型就瞎掰
- 外在性(Extrinsic): 明明提供了正確的 context 參考資料,模型還是講錯
這篇文章指出,在 production 環境中,後者才是我們工程師最常碰到的問題,而且你不需要 ground truth 資料集就能偵測到!
偵測方式其實很簡單,兩步驟:
- 檢索是否正確? 檢索回來的文件有包含回答問題所需的資訊嗎?
- 生成是否正確? 生成的答案有沒有「超出」檢索文件的內容?
如果檢索正確但生成不正確,就抓到幻覺了。模型憑空捏造了 context 裡沒有的內容。
這個方法不需要知道「正確答案」是什麼,只要比對生成內容是否超出檢索文件的範圍就好。這讓幻覺偵測變得實際可行,不用人工標註或完整的 ground truth 資料集。
加映這篇文章的演講版本: How You Catch Production Hallucinations in Real Time
📉 37 Things I Learned About Information Retrieval in Two Years at a Vector Database Company
向量資料庫 Weaviate 的工程師 Leonie Monigatti,分享了兩年來學到的 37 件資訊檢索心得。
我挑幾個重點分享:
- BM25 仍是強力基準: 別急著跳到向量搜尋,先從簡單的 BM25 關鍵字搜尋開始做
編按: 因為太多人沒用過全文搜尋引擎,就直接拿套 Naive RAG 方案來用,不會 tune 的話結果不一定比較好 - 向量資料庫的主要應用不是生成式 AI,而是搜尋: 但為 LLM 找相關上下文本質上就是「搜尋」,所以向量資料庫和 LLM 才會像餅乾配牛奶一樣合拍
- 去哪找好的 Embedding 模型: MTEB (Massive Text Embedding Benchmark) 是首選,涵蓋分類、聚類、檢索等任務。專注資訊檢索看 BEIR,多語言看 MMTEB
編按: 繁體中文請找看我的評測: 使用繁體中文評測各家 Embedding 模型的檢索能力 - 萬物皆可 Embed: 不只文字,圖片、PDF(像 ColPali)、圖譜都能嵌入。這表示你可以對多模態資料做向量搜尋
編按: 例如 Cohere Embed 4 模型 - 向量維度的經濟學: 選 1536 維度 vs 768 維度,儲存成本直接翻倍。做個簡單的 “chat with your docs” 真的需要 1536 維嗎?有些模型用 Matryoshka 技術可以動態縮短向量
編按: 我也有寫過一篇文章: 俄羅斯套娃(Matryoshka)嵌入模型簡介 - 相似不等於相關: 「如何修理水龍頭」和「哪裡買廚房水龍頭」在向量空間可能很相似,但對使用者來說根本不相關
- Cosine 的 similarity 和 distance 算法: 相似度 1 表示完全相同,距離就是 0。用正規化向量時,cosine similarity 和 dot product 數學上相同,但用 dot product 計算更有效率
編按: 通常 Embedding API 回傳的向量已經正規化,例如 OpenAI - RAG 的 R 不是指向量搜尋: 是 Retrieval (檢索),檢索可以用很多方式實現
- 向量搜尋只是工具箱裡的一個工具: 還有關鍵字搜尋、過濾、重排序。要做出好東西,需要組合不同工具
- 何時用關鍵字 vs 向量搜尋: 需要語意同義詞匹配(粉彩色 vs 淺粉紅)用向量;需要精確關鍵字(A字裙、荷葉邊洋裝)用關鍵字;兩者都要就用 Hybrid Search
- 過濾(filter)不一定讓向量搜尋更快: 直覺上過濾減少候選數應該更快,但實際上 pre-filtering 可能破壞 HNSW 的圖連通性,post-filtering 可能讓你沒結果。各家向量資料庫有不同且複雜的技術來應對這個挑戰。
編按: 例如 pg_vector 0.8.0 搞了一個 Iterative Index Scan 功能來避免 overfiltering 沒結果 - 二階段檢索不只用在推薦系統: 第一階段用簡單檢索(如向量搜尋)減少候選,第二階段用更精確但計算密集的重排序。RAG pipeline 也能這樣做。向量搜尋是從整個資料庫返回一小部分結果,重排序是對已有列表重新排序。
編按: 繁體中文請找看我的評測: 使用繁體中文評測各家 Reranker 模型的重排能力 - RAG 從第一個長上下文 LLM 出現就一直在 “死掉”: 每次有更長 context window 的模型,就有人說 RAG 死了。但它從來沒死過…
編按: 我覺得就像記憶體與硬碟,記憶體就算很大,你還是需要硬碟空間,因為兩者成本差距太大。當需要檢索的文件成千上萬,全部塞到 context 不現實。 - 向量搜尋其實對錯字不友好: 訓練資料不可能包含所有可能的拼寫錯誤,向量搜尋處理錯字能力有限
- 選對評估指標: 學術基準測試很常用 NDCG@k,但簡單的 precision 和 recall 很多時候就夠用。如果排序重要,要用 MRR@k、MAP@k 或 NDCG@k 這些考慮順序的指標。
編按: 例如 google 搜尋結果的排名很重要,對 RAG 場景來說,只要檢索 top-k 有命中就好,其中的順序沒這麼重要,反正 LLM 都會看到。 - Out-of-domain 不等於 out-of-vocabulary: 早期模型碰到沒見過的詞會出錯。現在的 tokenization 可以處理沒見過的詞(如 Labubu),但它們仍是 out-of-domain,向量看起來正常但其實沒意義。
編按: 解決方案是(開源) Embedding 可以做微調 - 查詢優化(Query optimizations)的藝術: 就像我們學會在 Google 輸入 “longest river africa” 而不是完整問句,現在也要學習如何為向量搜尋優化查詢。
從 RAG 到 context engineering,不變的是為 LLM 找到最適合的資訊,讓它們能提供最佳回答,這一點仍然是關鍵。
更多討論在我 Facebook 貼文。
💡 How to turn Claude Code into a domain specific coding agent
看到 LangChain 團隊分享了一個很實際場景的實驗: 如何讓 Claude Code 變成專精特定領域的 coding agent。
現在的 coding agents 對主流框架很熟悉,但碰到公司內部 API、小眾框架或新版本的函式庫就gg了。作為 LangGraph 和 LangChain 的開發者,他們當然希望 AI 能寫出高品質的 LangGraph 程式碼。
於是他們做了個實驗,測試四種配置:
- 原版 Claude Code (什麼都不加)
- Claude + MCP 文件工具 (指 LangChain 自己出的 mcpdoc 工具)
- Claude + Claude.md (精心撰寫的 LangGraph 指引文件)
- Claude + MCP + Claude.md 全套組合
效果排名: 4 > 3 > 2 > 1
這個 mcpdoc 工具提供兩個功能: list_doc_sources 抓取 llms.txt 文件的網址目錄,fetch_docs 根據網址抓取文件內容。
快速結論是: 精心撰寫的 Claude.md 檔案,表現比單純給文件工具還好!
幾個關鍵發現:
- 這個 mcpdoc 文件工具效果不如預期: 單份文件的 context 還是太長,可能呼叫一次就塞爆 context window 了。如果你的文件多到想要用工具來查,建議實作更精準的檢索功能,只回傳相關段落。
- 寫好 Claude.md 的 CP 值最高: 雖然 Claude.md 只包含全部文件內容的子集,表現卻更好。他們觀察了 log 發現: Claude 並沒有頻繁呼叫 MCP 工具。即使任務需要查看多個相關頁面,它通常只呼叫一次就停了,只得到表面描述而非所需細節。
- 最強組合是兩者並用: AI 透過 Claude.md 獲得重要概念和基礎知識,需要時再用 MCP 深入查詢文件細節。
最後很可惜的是,他們並沒有測試 Context7 這個目前最受推薦的 MCP coding 文件檢索工具,這家的做法就是只回傳「相關段落」而不是整份文件,正好能解決 mcpdoc 塞爆 context window 的問題。若是 Claude.md 搭配 Context7 使用,想必效果更上一層樓 😎
補充: 這是他們 LangGraph 的 claude.md 內容,原文中也有介紹一下這個 prompt 的結構。
更多討論在我 Facebook 貼文。
📑 LLM framework 筆戰
要不要使用 LLM 框架來開發 AI 應用,一直是個熱門話題。最近看到一場精彩的筆戰,有梗又有料,實在太有趣了! 🤣
以下轉載翻譯原文:
像這樣的騙子只是在浪費你的時間,他們的鄧寧-克魯格效應(Dunning-Kruger effect)意見應該被認真的開發者忽視。
你要麼基於框架開發,要麼活得夠久到自己造輪子(順帶一提,這也沒問題)。原因如下:
- 「在 while 迴圈中呼叫 LLM API」是你的基礎 Agent 步驟 – 你 Agent 系統中的工作單元。你會把它包裝成函數,在需要執行 Agent 時呼叫它。這只是起跑線,也是這些白痴通常卡住的地方。
- 當你開始建構 Agent 時,你會把這個函數轉成類別,加入提示詞處理、訊息管理、工具呼叫、重試和錯誤處理的邏輯。恭喜,你已經開始自己造輪子了。
- 接著,你會想嘗試不同的模型或串接 Agent 來建構工作流程。每個模型都有其特殊之處、自訂設定、不同的回應格式、提示詞技巧(例如:Claude 需要「請勿在回應中反思搜尋結果的品質」)。你開始為自製框架加入更多層次。
到目前為止這還是可解決的問題,你還能憑感覺搞定它。
- 然後事情真的開始變得令人沮喪。你很快就會發現需要跨執行維護會話歷史和狀態,因為不像那些騙子,你實際上不會在你媽家的地下室跑 Jupyter notebook。你猜怎麼著 — 你的 Agent 需要資料庫。你會設計像 agent_sessions 這樣的資料表,串接會話 ID,在每次執行時儲存/檢索歷史和狀態。幾週後,你會發現你的架構效率低下,因為你忘了加入正確的索引,現在你得學習資料庫遷移。
靠北!這不是應該只是個 while 迴圈嗎?而且我們甚至還沒開始處理 RAG、分塊、嵌入、檢索、上下文管理、工具管理、MCP、監控和日誌記錄。為什麼騙子要騙人?
現在我們已經陷入憑感覺寫程式的噩夢好幾週了,而 CEO 還在問什麼時候可以上線。 - 最後,你面對真正的問題:我該如何將這個服務化成 API 並在上面建構產品?
你拼湊出一個 FastAPI 應用,把它丟進容器,以為大功告成。你鬆了一口氣,交給你的 CEO。他像瘋子一樣猛測,分塊開始掉落,Agent 混淆上下文,你突然需要學習 SSE。你實作了 SSE,事情運作良好一陣子,然後你的請求開始逾時,容器記憶體爆掉 – 記憶體洩漏。你責怪 Python,但內心深處,你知道,你知道的。
你開始搜尋解決方案,然後看到來自 @AgnoAgi 的這段程式碼片段…
🔹 Alec Velikanov 先生 (某新創CTO) 的回覆
像這樣的騙子只是在浪費你的時間,他們的鄧寧-克魯格效應意見(Dunning-Kruger effect)應該被認真的開發者忽視。
你要麼建構自己的 Agent 迴圈,要麼活得夠久被困在別人的框架地獄裡(順帶一提,這也沒問題)。原因如下:
- 閃亮的「框架示範」在第一天看起來很棒。幾行 YAML,一個神奇的 Agent() 呼叫,突然你以為自己要出貨了。這只是起跑線,也是這些白痴通常卡住的地方。
- 當你開始建構實際的使用案例時,你會發現你需要的一半功能都是「即將推出」或藏在某個沒有文件的設定旗標後面。你開始 fork、hack、包裝他們的抽象層⋯恭喜,你在維護他們的框架而不是建構自己的。
- 接著,你會想嘗試不同的模型或串接工作流程。每個框架都強迫你採用它「欽定」的編排風格、奇怪的序列化格式,或「外掛生態系」。你花在對抗抽象層的時間比解決問題還多。
到目前為止還能存活,你還能憑感覺繞過它。
- 然後事情真的開始變得令人沮喪。你很快就會發現他們的記憶體/狀態層很爛——寫入很慢、索引缺失、遷移根本不存在。你在凌晨三點調試別人半成品的 SQLite 包裝器,想著為什麼不自己寫三個資料表就好。
靠北!這不是應該要幫我省時間嗎?而且我們還沒碰到框架的「RAG 管線」(長文件就會壞掉)、它神奇的嵌入快取(會洩漏記憶體)、或者基本上就是 print() 的監控。為什麼騙子要騙人?
現在你已經陷入依賴地獄好幾個月了,而 CEO 在問為什麼什麼都要私訊框架的 Discord 管理員才能運作。 - 最後,你面對真正的問題:我該如何在生產環境運行這個? 框架提供了一個預建的 FastAPI 容器,號稱有「企業級」端點… 直到它在平行請求時deadlocks、在負載下 timeout 時,你才意識到作者從來沒有擴展超過黑客松示範的規模。
你提交一個 issue,得到一個愉快的「歡迎 PR :)」回覆,內心深處,你知道,你知道的。
你開始搜尋解決方案,然後意識到唯一的修復方法是把它全部拆掉,回到原始的 LLM API 和 while 迴圈。
你看見了曙光,放棄你的受虐狂傾向,並重複這個咒語:自己他媽的動手做就對了!
—
更多討論在我 Facebook 貼文。
⚖️ Sniffly 工具
歐萊禮 AI Engineering 一書(這本有繁中翻譯版)的作者 Chip Huyen 開源了一個 Claude Code 的使用分析工具 Sniffly,可以幫助我們更有效使用 Claude Code。
她還分享了幾點心得:
- 最常見的 Claude Claude 錯誤類型是「找不到內容」(20-30%) ,Claude Code 經常試圖尋找不存在的檔案或函數。因此她會重新調整程式碼結構,讓 AI 更容易「發現」需要的內容。
- 傳統的開發時數指標已經不適用 AI,她提出兩個新的專案複雜度評估指標:
- 需要給 AI 多少次指令才能完成專案
- 有多常要打斷 AI 因為 AI 走錯方向
- 大多數需要打斷 AI 的情況,在 10 步內就需要人工介入,偶爾可以接近 100 步自主運作。Claude Code 最愛用的工具是搜尋類指令(grep、ls、glob),佔了所有工具呼叫的 1/3。
Sniffly 還能讓你回顧所有歷史指令和模型回應結果,安裝方式很簡單,指令是 uvx sniffly@latest init
更多討論在我 Facebook 貼文。
💻 OpenAI Agents SDK v0.3.x released
最近我開始有空就貢獻一下 OpenAI Agents SDK 原始碼,從 v0.3.0, v0.3.1, v0.3.2 都可以看到 ihower 的 commits。
包括修了這個 #1689 和 #1757、加了 1758 跟這個 1765。
我也在跟進 #1767 跟 #1789。
如果大家碰到什麼奇怪問題,也可以找我喔。
希望你會喜歡這集內容!
– ihower