feat(collector): workers-ai 路改吃共用契約——免金鑰預設路的卡跟 BYOK 一樣完整(Arcrun#134)
InkStoneCo#44 ④ 只修了 gemma BYOK 路(JSON 契約+wikishape 機械組卡), 免金鑰預設路(多數用戶實際走的)仍吃雲端舊 prompt 的舊格式卡 ⇒ 走預設路 拿到次級知識庫。 修法=契約單一真相源:wikiExtractPrompt(原 gemmaPrompt 改名,因為它已是 兩條路共用)由 daemon 整段帶上雲(request prompt 欄位),雲端只當執行器回 模型原文(response output),解析(parseWikiExtractJSON)與組卡(BuildWikiDoc) 回到本 package 與 gemma 路同一段程式碼——同形不再靠「兩邊要一起改」的叮嚀。 版本歪斜兩向都有路:舊雲端忽略 prompt 回 card ⇒ fallback 走 legacy 落卡 (#60 前綴/不覆蓋保護原封不動,收端 lint 新舊雙軌);舊 daemon 不帶 prompt ⇒ 雲端 legacy 行為不變(對向修法在 Arcrun work/extract-wiki-json-0815)。 測試:+2——①request 的 prompt 必須是 wikiExtractPrompt 本人(不是手抄第二份) ②同原稿+同判斷走兩條路,.wiki/ 產物逐位元組相同(卡+00-INDEX+manifest)。 既有兩則(stub 回 card)自動變成舊雲端 fallback 的守衛。go test ./... 全綠。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+32
-2
@@ -22,6 +22,15 @@
|
||||
// 讀原檔 → ConvertToText(本機轉檔)→ 送 API → 淨化 → 落卡
|
||||
// ↑ 只有這一步不同
|
||||
//
|
||||
// 🔴 Arcrun#134(2026-08-15):**提示詞也由 daemon 帶去**(request 的 `prompt` 欄位)。
|
||||
// 之前雲端自備一份 prompt、daemon 另有一份 gemma 用的,兩份靠註解叮嚀「一起改」——
|
||||
// InkStoneCo#44 ④ 改了 gemma 那份(JSON 契約+wikishape 機械組卡),雲端沒跟上,
|
||||
// 免金鑰預設路的用戶因此繼續拿舊格式卡。修法=契約只住本 package 一份
|
||||
// (wikiExtractPrompt + parseWikiExtractJSON + BuildWikiDoc 同進同出),
|
||||
// 雲端只是「用實例自己的 env.AI 跑生成」的執行器,回應 `output` 原文。
|
||||
// 版本歪斜:舊雲端會忽略 prompt、照舊回 `card`(舊格式 markdown)⇒ 本檔 fallback
|
||||
// 走 legacy 落卡(收端 lint 新舊雙軌仍接受,#60 的前綴與不覆蓋保護原封不動)。
|
||||
//
|
||||
// ⚠️ 隱私邊界不變:送出去的是**已在本機轉成純文字的原稿**,回來的是知識卡;
|
||||
// 原始檔案(docx/pdf/xlsx)仍然不出用戶的電腦。
|
||||
package collector
|
||||
@@ -66,9 +75,12 @@ func ExtractWithWorkersAI(cypherURL, apiKey, absRoot, relPath string) ([]string,
|
||||
}
|
||||
|
||||
pageName := pageNameOf(relPath)
|
||||
// #134:prompt=與 gemma 路同一份契約(同 package 同函式,物理上不可能漂移)。
|
||||
// page_name/text 仍照送:舊雲端不認得 prompt,會拿它們組 legacy 提示詞回舊卡。
|
||||
reqBody, _ := json.Marshal(map[string]string{
|
||||
"page_name": pageName,
|
||||
"text": srcText,
|
||||
"prompt": wikiExtractPrompt(pageName, srcText),
|
||||
})
|
||||
|
||||
url := strings.TrimSuffix(strings.TrimSpace(cypherURL), "/") + "/portal/daemon/extract"
|
||||
@@ -104,19 +116,37 @@ func ExtractWithWorkersAI(cypherURL, apiKey, absRoot, relPath string) ([]string,
|
||||
var parsed struct {
|
||||
Success bool `json:"success"`
|
||||
Card string `json:"card"`
|
||||
Output string `json:"output"` // #134:新雲端在 prompt 模式回模型原文
|
||||
Error string `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &parsed); err != nil {
|
||||
return nil, fmt.Errorf("雲端回應解析失敗:%w", err)
|
||||
}
|
||||
if !parsed.Success || strings.TrimSpace(parsed.Card) == "" {
|
||||
if !parsed.Success || (strings.TrimSpace(parsed.Card) == "" && strings.TrimSpace(parsed.Output) == "") {
|
||||
if parsed.Error != "" {
|
||||
return nil, fmt.Errorf("雲端萃取失敗:%s", parsed.Error)
|
||||
}
|
||||
return nil, fmt.Errorf("雲端沒有回傳卡片內容")
|
||||
}
|
||||
|
||||
// 與 gemma 路共用同一套淨化與落卡(卡片格式契約一致:第一行必須是「# <頁名>」)
|
||||
// #134 主線:新雲端回 `output`(模型對 wikiExtractPrompt 的原始回應)⇒
|
||||
// 與 gemma 路走**同一段**收尾:解析 JSON 判斷 → wikishape 機械組卡落 `.wiki/`。
|
||||
// 兩條萃取路的卡片形狀從此由同一份程式碼保證,不是由兩份 prompt 各自維持。
|
||||
if strings.TrimSpace(parsed.Output) != "" {
|
||||
ex, perr := parseWikiExtractJSON(parsed.Output)
|
||||
if perr != nil {
|
||||
return nil, perr
|
||||
}
|
||||
cards, berr := BuildWikiDoc(absRoot, relPath, srcText, ex, time.Now())
|
||||
if berr != nil {
|
||||
return nil, berr
|
||||
}
|
||||
// 沒有可萃概念=合法結果:不產卡,00-INDEX 列「空」(同 gemma 路)。
|
||||
return cards, nil
|
||||
}
|
||||
|
||||
// legacy fallback:舊雲端(不認得 prompt)回 `card`(舊格式 markdown)。
|
||||
// 與 gemma 舊路同一套淨化與落卡(第一行必須是「# <頁名>」),#60 保護不動。
|
||||
card := cleanGemmaCard(parsed.Card, pageName)
|
||||
if !strings.HasPrefix(card, "# ") {
|
||||
return nil, fmt.Errorf("萃出內容不像卡片(未以 # 開頭):%.120s", card)
|
||||
|
||||
Reference in New Issue
Block a user