feat(t73): 轉檔層接進主流程——docx 真的走得通(零件完成≠功能完成)

ExtractWithGemma 讀檔後改走 ConvertToText,LLM 只會收到文字永不收二進位。
刻意不吞錯:ErrNoText(掃描件/空檔) 與 ErrUnsupported(未支援格式) 都往上拋,
因為靜默略過正是 leo 撞到的病。

接線測試 5/5(驗用戶真的會走的那條路,非只測零件):
  scan 收得到 .docx/收 .md/不收 .png
   docx 一路走到 Gemini API 才因假 key 失敗 = 決定性證據:
     轉檔確實發生在送模型之前(非宣稱)
  抽不出文字 → 明確失敗且 errors.Is(ErrNoText) 可判定,不靜默送空卡
  未支援格式 → ErrUnsupported,與 ErrNoText 可區分(給用戶的說法不同)
  .md 迴歸保護:不因接了轉檔層而壞掉

順帶修:變數名與既有 text(LLM 回應) 衝突 → 改 srcText(輸入原稿),IDE 診斷抓到。
全 collector 測試綠。
This commit is contained in:
2026-07-27 20:44:29 +08:00
parent 66d4fef045
commit 09bf454402
2 changed files with 149 additions and 1 deletions
+12 -1
View File
@@ -56,11 +56,22 @@ func ExtractWithGemma(apiKey, model, absRoot, relPath string) ([]string, error)
if err != nil {
return nil, fmt.Errorf("讀原稿失敗:%w", err)
}
// 本地轉檔層(t73/t162026-07-27):任何格式在這裡變成「模型可讀的純文字」。
// 純文字檔原樣通過;.docx 等走對應抽取器。**LLM 只會收到文字,永遠不會收到二進位**
//(那正是這一層存在的理由——見 convert.go 檔頭與 pdf-extraction-options.md 洞 B)。
srcText, err := ConvertToText(relPath, raw)
if err != nil {
// 這裡刻意**不吞錯**:靜默略過正是 leo 撞到的病(丟檔進去沒反應)。
// ErrNoText=掃描件/空檔,ErrUnsupported=還沒支援的格式,兩者訊息不同但都要說出來。
return nil, fmt.Errorf("轉檔失敗(%s):%w", relPath, err)
}
pageName := pageNameOf(relPath)
reqBody, _ := json.Marshal(map[string]any{
"contents": []map[string]any{
{"parts": []map[string]any{{"text": gemmaPrompt(pageName, string(raw))}}},
{"parts": []map[string]any{{"text": gemmaPrompt(pageName, srcText)}}},
},
"generationConfig": map[string]any{"temperature": 0.2, "maxOutputTokens": 8192},
})