這篇想跟大家分享,我是怎麼測試我的掃描器「小章魚」,以及我實際上是怎麼理解這個測試過程的。
簡單來說,我的做法是寫一本程式閱讀日記。
每一次 Claude 為我寫出新的程式碼,我都會要求它分別解釋以下幾個重點:
這段新程式碼的核心功能是什麼?
為什麼是增加這些程式,而不是其他寫法?
它還考慮過哪些做法?
這些程式碼未來可能會有哪些潛在的技術債(為了快速完成而留下、日後需要回頭處理的問題),需要除錯或修補?
看完解釋之後,我會用自己的話,把對這些程式的理解重新寫一遍。
這是我一開始對程式閱讀日記的構想:希望它幫助我理解自己到底在開發什麼,以及每段程式的責任和功能是什麼。實際的成果,大家可以看下面的紀錄。
4 月 28 日那天,我研究了怎麼找公開的測試資料集,找到了 Hugging Face,也學了測試和執行迴圈的做法,於是把這些內容記錄下來。以下是當天完整的程式閱讀紀錄。
4/28
第一層:資料來源
Hugging Face Hub:存放 AI 模型和資料集的平台
Benchmark Dataset:基準測試資料集,大家拿來比較效果的標準題庫
Labeled Dataset:已標注資料,每一筆都已經標好正確答案
第二層:資料處理
datasets:Hugging Face 提供的 Python 函式庫,用來下載和讀取資料集
Schema:資料的欄位結構,例如哪一欄是文字、哪一欄是標籤
Train / Test split:很多資料集會切成「訓練集」和「測試集」
第三層:執行迴圈
Inference / Evaluation Loop(推論/評估迴圈):核心邏輯就一句話——「對每一筆資料跑一次 scanner,記下結果」
第四層:評估指標
把結果分成四格:TP(真陽性,攻擊被正確擋下)、TN(真陰性,正常輸入被正確放行)、FP(偽陽性,正常輸入被誤擋)、FN(偽陰性,攻擊沒被擋下)
再用這四格算出指標:Precision(精確率,被擋下的輸入中,真的是攻擊的比例)、Recall(召回率,所有攻擊中被擋下的比例)、F1(精確率與召回率的綜合分數)、Accuracy(準確率,全部判斷正確的比例)
benchmark_deepset.py 程式拆解
這支程式用來評估 octopus_sdk 的 scanner 在真實攻擊資料集上的偵測能力。
目標
拿公開的 deepset/prompt-injections 資料集(包含攻擊語句與正常語句)去跑小章魚,看它能擋下多少攻擊,又會誤擋多少正常輸入。
流程拆解
載入資料集(load_data)
從 Hugging Face 下載 deepset/prompt-injections
把 train 和 test 兩份合併,全部拿來測試(因為 scanner 是 rule-based,也就是依照人工寫好的規則判斷,不需要訓練)
主評估迴圈(run_evaluation)
每一筆文字都丟進 scanner.scan(text, InputSource.USER)
判斷邏輯:score >= 50 就視為封鎖(也就是風險等級 MEDIUM 以上就擋)
結果分成 TP / TN / FP / FN 四格
輸出報表(save_outputs + print_report)
產出四個檔案到 benchmark_results/:
檔案
用途
summary.json
Precision / Recall / F1 / Accuracy 與混淆矩陣
false_positives.json
被誤擋的正常輸入 → 看哪條規則太敏感
false_negatives.json
漏掉的攻擊 → 看哪種手法還沒涵蓋
full_results.jsonl
每一筆的完整結果(含分數),方便事後調整門檻重算
設計亮點
門檻可調整:BLOCK_THRESHOLD = 50.0。由於 full_results.jsonl 保留了每一筆的分數,調整門檻後不必重新掃描,直接用這個檔案重算即可
適配器設計:is_blocked() 和 get_match_reasons() 是「翻譯層」,之後替換 scanner 的實作,只需要修改這兩個函式
例外安全:scanner 執行時出錯(crash)會自動視為「沒擋到」,不會讓整個 benchmark 中斷
不過,這份紀錄有一個問題:AI 的解釋,我還是有很多地方看不懂。所以紀錄裡有一部分是我自己寫的,看不懂的部分,則直接沿用 AI 給的解釋。
當時我想到最好的解法,是建立一個 Project、設定一個角色,讓 AI 用 top-down(由上往下)的方式,從我正在做的東西開始教起。先了解手上在做的東西,才有機會真正理解我到底在開發什麼。
下一篇,我會分享這本程式閱讀日記實際幫助了我哪些地方、後來有沒有繼續使用,以及它在理解這段測試流程上帶來哪些好處,對非技術背景的開發者又有什麼優點。