
昨天把 MCP 放回它的位置:它是 AI 應用程式和外部工具 server 溝通的協定。今天回頭看第三週,確認本地助理從收到問題、選工具、執行,到把結果交回模型,整條路有沒有接起來。
這週從一個工具開始,最後有四種工具可以選。模型負責提出呼叫;真正執行之前,Python 會再檢查一次。
目前 knowledge/tools.py --checkpoint 有四個案例:列出檔名包含 deployment 的來源、讀取指定文件的片段、搜尋 SQLite FTS5 官方文件,以及回答不需要工具的算術題。前三個案例應該各選到對應工具;最後一題應該直接回答,不呼叫工具。
執行前要先啟動本機 MLX-LM server,使用專案設定的 Qwen 模型,再於另一個終端機執行:
HF_HUB_OFFLINE=1 uv run python knowledge/tools.py --checkpoint
這裡的網頁搜尋案例使用固定 fixture,只回傳一筆 SQLite 文件資料,不會真的連上搜尋服務。它驗收的是 Qwen 有沒有選 web_search、Python 有沒有把工具結果交回模型,以及最後回答有沒有整理出標題和網址。
截至 10 月 1 日的驗證紀錄,四個案例都通過。這是當時這個模型和這組固定問題的結果;每個案例只跑一次,不能拿來推論一般使用情境下的工具選擇準確率。程式目前也沿用 Day 17 的 checkpoint 標籤,因此命令最後會顯示 Day 17 tools checkpoint:PASS。
工具結構描述(schema)會告訴模型可用工具、參數名稱和型別。但模型回傳的工具呼叫仍是外部輸入。knowledge/tools.py 會檢查工具名稱是否在允許清單、arguments 是否為可接受的 JSON、欄位是否完全符合該工具的規格,再決定要不要呼叫函式。
例如 list_sources 只收 name_contains,值必須是字串,長度不能超過 80 個字元。模型多帶一個 path,或把欄位改成錯誤型別,dispatcher 就會拒絕這次呼叫。這個檢查由 Python 執行,不依賴模型遵守 schema 的描述。
每一輪最多執行一個工具,最多送出兩次模型請求:第一次提出工具呼叫,工具結果回來後再問模型一次。若模型第二次又提出工具呼叫,程式會停止這一輪。checkpoint 輸出會列出每個案例的 model_calls 和 tool_call_count;有工具呼叫時,也會印出工具名稱、參數與結果。
list_sources 和 get_document_chunks 只讀固定 manifest;web_search 回傳候選資料。import_web_source 則會保存原始來源、轉成 raw 文件並重建索引,所以它會改變本地知識庫。
匯入工具不接受任意 URL 或路徑。它只處理最近一次搜尋取得的來源 ID,而且 Python 會確認使用者在目前這一輪明確選了該來源,才執行匯入。checkpoint 的網頁搜尋案例刻意停在候選結果,沒有呼叫匯入;來源選擇與匯入的限制則由程式測試另外檢查。
這也是為什麼「模型選對工具」還不夠。Day 18 的 10 題路由評估全數命中,但評分只看工具名稱或是否直接回答,沒有評 arguments,也沒有執行工具。Day 19 才把參數驗證補進 dispatcher。模型判斷、程式驗證、工具權限,是三個要分開看的部分。
目前這個工具層可以列出文件、讀取有限數量的片段、搜尋外部候選,並在使用者選定後匯入來源。每次呼叫都經過 Python 的允許清單和參數檢查;需要寫入知識庫的操作還要有使用者明確選擇。
這些檢查涵蓋固定案例和程式端的輸入限制,沒有證明模型永遠不會選錯,也沒有完成整體安全評估。網頁搜尋 checkpoint 使用 fixture,匯入流程的選擇條件另由單元測試檢查。讀者可以從專案 Repository 查看程式與各日驗證紀錄:https://github.com/gilbertytw-lab/ai-engineering-frontier。
今天增加了什麼?整理出第三週回顧,並用既有 checkpoint 說明模型選工具、Python 驗證和結果回傳各自負責的部分。
它解決了什麼問題?讀者可以分辨模型提出呼叫,和應用程式真的執行呼叫,是兩個不同步驟。
讀者可以執行哪一個命令?啟動本機模型後執行 HF_HUB_OFFLINE=1 uv run python knowledge/tools.py --checkpoint。
下一步會先讓知識庫離開這五份示範文件:挑一批可重現的真實資料,量測大量匯入、建索引、查詢和回答的表現。確認資料規模與答案品質後,再做一個方便查詢、查看來源的 HTML 介面。