Plan: Defect Library — 影像缺陷知識庫 + 分類輔助 (#513)¶
#513:現場有成千上百種 defect type,判斷邏輯散在各站點 case-by-case 的程式 (kernel,rule + ML)裡,沒有整理過的知識層、也沒有 AI 輔助工程師判斷「這張圖是哪一種 defect」。延伸自 #104。
⚠️ 重新框定(2026-07,supersedes 先前所有 defect-specific 設計)¶
user 明確拍板:不為 defect library 開發任何客製化功能。原話—— 「程式碼裡面不要有 defect / classify / tool 什麼什麼,他就是用 context card 與 doc question、card suggestions、擅用 multiple keys」、「幾乎不該有新程式碼,我們需要平台 擴充功能,但不是客製化」。
原則:defect library 不是一組功能,而是既有通用原語的一種「用法」。唯一可接受的 新程式碼是通用平台擴充(任何 collection / 任何 use case 都受惠),絕不是 defect 專屬。 所有「defect 味道」的東西都應該落在資料(卡片內容)+ 慣例(怎麼下 key)+ prompting, 而非程式碼。
因此已撤除(commit 25cd0ca1):kb/defect_library.py、lookup_defect +
classify_defect 兩個 agent tool、它們在 3 個 kb preset 的掛載、只為 classify 加的 KB-chat
vlm_describer 接線。這些正是被拒絕的客製化。
保留(它們本來就是通用平台擴充,只是措辭泛化掉了 defect):P2 影像向量插座、P6 外部圖 抓取 ingest、P7 SourceDoc attachments、P8 附件 UI、P9 retriever 父文合併。
架構鐵則(user 拍板)¶
- defect lib = 一個 KB collection,非新 App、非新 resource、非新 defect 專屬工具。
- image-embedding 模型由他隊做;架構要加法非取代(他隊交付前後都能動)。
- 盡量複用既有機制;新程式碼只能是通用平台擴充。
三個用例 → 各自對應的既有 / 通用能力¶
- C 查代號 → 定義 / 判斷標準 / 範例圖(純文字、不需圖):
- entry =
ContextCard;station/層級靠 scope-qualified multi-key 進keys(list):etchtool07|M4(機台)/etch|M4(站型)/M4(全域)。norm_keys派生。 - 查詢走既有
lookup_glossary(確定性 exact-key 查 context card)或kb_search(模糊)。 - override(機台蓋站型蓋全域)= agent 由具體 key 查到廣 key、第一命中勝 —— 這是
下 key 的慣例 + prompt/collection guidance,不是
resolve程式碼。 -
零新程式碼;交付 = 種子卡 + guidance(見 P11)。
-
B 上傳圖 → 這是哪一種 defect:三條檢索路(user 拍板),查詢圖是對話當下的暫時 上傳圖、不是 KB 文件(「那張圖不是文件」):
- 以圖搜圖(image→image):等他隊
ImageEmbedder交付 → P4。 - 圖轉文 + metadata → 搜文 → top-k → 綜合作答:對話當下用 VLM 把上傳圖描述成查詢
文字(+ user 給的站點/條件 metadata)→
kb_search打 defect 卡 → 綜合 + 推薦。 - 圖轉文無 metadata → 走 2 的路。
-
路 2/3 的唯一通用缺口:KB chat 訊息目前只有文字,無法夾一張暫時圖給 agent 看 → P10(通用多模態 chat 輸入;任何 KB chat 想「看這張圖問問題」都受惠)。
-
A 系統自動餵產線圖 + 現成 indices → 砍掉:沒有 image_id、圖→run 反查不到、indices 只能 user 手動給。零 measurement 整合。
flywheel(庫怎麼長大)= 零新程式碼、複用既有且皆通用¶
- cardgen(#506,已完整落地)指向 defect collection → 起草 scope-qualified 卡 → reconcile (keep/update/new)→ 人核 commit → ContextCard。閉環已存在,冷啟近乎免費。
- #377 DocQuestion:agent 沒把握就發問,term 答覆直接落地成 ContextCard(
land_term_answer)。 - 不新增
DefectLabelresource、不做 auto-classify 捕捉(那是客製)。
現況查證(為什麼加法可行)¶
- collection 沒有
kind欄(resources/kb.py);「長出來的」慣例 ⇒ image 不必發明 discriminator。 DocChunk早有embedding+embedding_alt兩個可空向量欄;加第三個embedding_img是純加法(P2 已做),與描述向量並存。- retriever 合流吃 N 條 arm,
None-gated ⇒ image arm 是純加法。 - 圖今天透過 VLM 描述被索引(
parsers/vlm_image.py);原圖 bytes 留SourceDoc.content。 - ContextCard lookup 是 collection-scoped、
norm_keys精準 element membership ⇒ multi-key scope 用既有.contains就成立(無需 resolve 碼)。 lookup_glossary是確定性 exact-key context-card 查詢(無 LLM、無 retriever)⇒ 用例 C 的查詢腳。
Phases(flat integer)¶
- P1 · ~~entry 模型 + scope-chain lookup_defect~~ → 已撤除(
25cd0ca1) - 原本加了
defect_library.resolve+lookup_defecttool,屬 defect 客製,被 user 拒絕。 -
用例 C 改為用法慣例:scope-qualified multi-key ContextCard +
lookup_glossary+ prompt。見 P11。 -
P2 · 影像向量插座(通用、空的、零行為變化)—— DONE
DocChunk.embedding_img(可空Vector)+kb/image_embedder.py(ImageEmbedderprotocol + stub)+ retriever text→image arm(None-gated)+create_app(kb_image_embedder=…)接線。-
通用:任何要以圖為第三訊號的 collection 都用得上。行為零變化。
-
P3 · ~~classify_defect 圖分類 tool~~ → 已撤除(
25cd0ca1) - 原本加了
candidates_in_scope+build_classification_prompt+classify_defecttool + KB-chatvlm_describer接線,屬 defect 客製,被 user 拒絕。 -
用例 B 改為通用多模態 chat 輸入(P10)+ 既有
kb_search;查詢圖是暫時 chat 附件、非文件。 -
P4 · image embedder 接上(gated on 他隊交付)—— 未做
- 實作
ImageEmbedder(他隊模型 adapter),create_app從None換真的;ingest 多算圖向量填embedding_img;re-index 回填。第三 arm 自動亮 → 用例 B 路 1(以圖搜圖)。 -
⚠️ generic CLIP 對 wafer/SEM 是 OOD,八成要他隊用累積標註圖 fine-tune;交付含準確率驗證。
-
P5 · flywheel —— 零新程式碼(複用既有,皆通用)
- = cardgen(#506,已存在)指向 defect collection + #377 DocQuestion。無新 resource、無捕捉客製。
-
交付 = 設定 + guidance:collection 開
auto_digest、卡提案人核長庫。屬 P11 的用法交付。 -
P6 · 外部圖抓取 ingest(通用)—— DONE
- HTML/MD 裡的
<img src>/外部連結 → SSRF allowlist 過濾 →IImageFetcher抓回 → 存成獨立 image SourceDoc(bytes 留著,VLM 描述 + P4 可上向量)。沿用 archive 展開接縫。 kb.image_fetch.{allowed_hosts,timeout}(schema + loader + example);空 allowlist=OFF、加法不變。-
通用:任何「文字帶內部圖連結」的知識都受惠(非 defect 專屬)。
-
P7 · SourceDoc attachments(通用、BE)—— DONE
- 附件 = 有父連結的子 SourceDoc(
parent_doc_id,indexed;空=頂層),走一般 parser dispatch → 可搜 / 可上向量,零 per-type 碼。path 慣例{父}/.att/{…}(無 hash;撞名走一般 409)。 - CRUD 全走既有 doc 機制:
move保parent_doc_id+ 鎖.att/前綴、刪父 cascade 刪附件、list_documents每列回parent_doc_id。Schema v8→v9 no-op reindex。 -
通用:任何文件要掛子資源(圖 / PDF / CSV)都受惠。
-
P8 · 附件顯示 + CRUD(通用、FE)—— DONE
-
KbDocIde依parent_doc_id把附件從 tree 切掉;新元件AttachmentBar(卡列名/型別/大小、 +上傳、每卡改名/取代/刪除)接編輯頁下方;點卡開既有KbDocViewerdrawer(零型別特判)。 -
P9 · retriever attachment-aware 父文合併(通用)—— DONE
-
Retriever._augment_with_parents:命中附件 chunk(語意薄)→ 依parent_doc_id額外帶回父文件 全文 passage(繼承分數、去重;無附件時 byte-for-byte 不變)。反向(父→附圖)延後。 -
P10 · KB chat 暫時圖附件 → VLM 描述 → 搜(通用多模態 chat 輸入)—— DONE(用例 B 路 2/3)
- 通用擴充:KB chat 訊息可夾帶一張暫時上傳圖(非 ingest、非 SourceDoc)→ 平台在對話當下
用 VLM 把它描述成查詢文字 → 併入 user 的文字(站點/條件 metadata)→
kb_search→ agent 綜合作答。 任何 KB chat 都受惠,非 defect 專屬;是用例 B 路 2/3 的地基(路 1 = 以圖搜圖,等 P4)。 - 收斂的設計決定:(a) 圖用 base64 掛在
_MsgBody.image(暫時、選配;非獨立 upload/非 doc id); (b) VLM 描述在 route 的 turn 前處理(send_message的_fold_image)注入 query,沿用 #106 卡片 pre-scan 的「augment agent_content、不動已存訊息」樣式,ChatTurnEngine零改;(c) FE 複用 #364 的extractClipboardFiles貼/拖解析,不重造。選 (A) 用完即丟(user 拍板「不小就即丟」):KbMessage是KbChat的內嵌 sub-struct(無 id/無 blob),存圖要動 chat 資料模型 + 新 blob 層 + endpoint + FE 歷史渲染 → 不小;即丟則零 resource 改動。 - 實作:BE
_ImageInput+_MsgBody.image+_fold_image(decode base64→magic re-sniff→describer.describe走asyncio.to_thread→併 caption;無 VLM/非圖/壞 base64 皆 400 fail-loud); 把vlm_describer以通用名義接回register_kb_chat_routes(= 25cd0ca1 砍的那段,這次正當理由是 通用多模態)。FEkbImage.ts(fileToImageInput/stagedImagePreview)+KbImageInput型別 +useKbChat.send(content, image?)(允許 image-only)+KbChatPanel附圖 chip/paperclip/paste/drop。 - commit:BE
33887142、FE3e6883b1。測試:BE 5(描述+併查詢、即丟不存、無 VLM/非圖/壞 base64 400)、 FE 22(helper/hook forwarding/image-only/composer attach→chip→forward→clear/remove);full web 1696 綠、 KB-chat 58 綠、ty/typecheck 綠。 -
⚠️ 交付前 B 準度:主要價值是 triage + 資料累積;細分近似缺陷靠 P4 圖向量。DoD 待補:live canned check(真 VLM 一張缺陷圖 → 描述 → 搜到對的卡)。
-
P11 · 種子卡 + guidance(用法交付,零程式碼)—— 要做
- guidance:一份說明「怎麼經營 defect library」——entry = ContextCard;key 用
machine|code/type|code/code三層 scope-qualified 慣例;body = morphology + 白話判斷標準; 範例圖 = P7 附件;override = 下具體 key + 由具體查到廣(prompt/guidance,非碼);查詢走lookup_glossary/kb_search;圖問走 P10;長庫走 cardgen(#506)+ #377。 - 落地形態(擇一,皆非程式碼):優先做 collection
guidance(#90) —— 把上面慣例寫成 collection 層 guidance 文字,steer KB agent 依慣例查/建卡;種子卡走既有 create/upsert 或 collection ZIP round-trip(#101)。不寫進 mkdocs nav 除非要一份對外文件(避免 --strict 負擔)。 - Unit:無(純資料 / guidance);驗證 = live —— 建幾張跨 scope 卡、查 code 驗 override、上傳一張圖走 P10。
相依 / gating¶
- P2 / P6 / P7 / P8 / P9 / P10 已完成(皆通用平台擴充,保留)。P10 是唯一還要寫的程式碼,已交付。
- P4 gated on 他隊交付
ImageEmbedder(用例 B 路 1)。 - P5 / P11 零碼:設定 + guidance + 種子卡(operational,交運維/user 用真資料落地)。
- measurement 整合已移除,無外部系統相依。
待決 / 風險¶
- P10 圖怎麼掛訊息 + VLM 描述在哪層:grill/TDD 時定;優先複用 workspace chat 附圖接縫(#364)。
- 機台→type→layer 拓撲:先 user 提供 scope(下 key + prompt),拓撲有了再自動展開。
- 圖向量領域適配:他隊需用累積標註圖 fine-tune;ground truth 靠 flywheel 累積。
- 交付前 B 準度:主要價值是 triage + 資料累積;細分準度靠 P4。
DoD 待補¶
- P2 / P6 缺 live check(真圖 / 真 VLM)+ full 100% gate。
- P10 完成後需 live canned check(真 VLM 一張缺陷圖 → 描述 → 搜到對的卡)。
- push 需 user 授權(本 session 曾明確拒絕 push);commit 全留 worktree branch。
Related: #104 #106 #133 #377 #355 #506 #364 #90 #101