build_pack.py 產生對白索引(放在使用者資料目錄);render_skill.py 把人格卡渲染成 角色 skill 並檢查精選對白逐字來自索引;插件改成執行期從資料目錄讀索引。 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
108 lines
6.8 KiB
Markdown
108 lines
6.8 KiB
Markdown
# 文本建置:wiki → 對白
|
||
|
||
建置流水線的第一段。這些腳本不屬於插件執行期;原文與輸出放在 repo 之外,不入版本控制。
|
||
|
||
## 1. 讀取 wiki
|
||
|
||
用 tea 的驗證讀取 Gitea wiki 全部頁面,存成 markdown:
|
||
|
||
```bash
|
||
python3 -I tools/corpus/fetch_wiki.py jiantw83/sao ~/anime-companion-data/sao/wiki
|
||
```
|
||
|
||
## 2. 抽出對白
|
||
|
||
抽出所有「」對白與前後文,並用規則判定明確的說話者:
|
||
|
||
```bash
|
||
python3 -I tools/corpus/extract_dialogues.py ~/anime-companion-data/sao/wiki ~/anime-companion-data/sao/dialogues.jsonl
|
||
```
|
||
|
||
輸出每個對白一行 JSON:
|
||
|
||
| 欄位 | 說明 |
|
||
| --- | --- |
|
||
| `id` | `v{冊}c{章}-{章內序號}` |
|
||
| `volume`、`chapter`、`page`、`para` | 位置;`page` 是分頁,`para` 是章內段落序號 |
|
||
| `text` | 對白內容(不含「」) |
|
||
| `before`、`after` | 同段落中對白前後的敘述 |
|
||
| `prev_par`、`next_par` | 前後段落 |
|
||
| `speaker` | 規則判定的角色代號,無法判定為 `null` |
|
||
| `alias` | 判定依據的名字(例如「莉法」或「直葉」) |
|
||
| `mode` | 由別名推得的模式:`ingame`、`real`、`leafa` |
|
||
| `confidence` | `high`:句中只有一個候選且有說話動詞;`medium`:多個候選取句首第一個,需 W4 覆核 |
|
||
| `rule` | `lead_in`(同段落「…說:」)、`lead_in_prev`(前一段以「:」結尾)、`trail`(對白後接「某某說」) |
|
||
| `candidates` | 句中出現的所有候選名字 |
|
||
| `suspect_duplicate` | 同一章 6 段內出現相同的長對白,疑為 wiki 頁面銜接的重複 |
|
||
|
||
## 規則的邊界
|
||
|
||
這個譯本很少直接寫「某某說」,多數對白靠上下文(「他這麼說」「她點了點頭」)或輪流發言判斷,所以規則只涵蓋約一成的對白。其餘由 W4 的 sub-agent 標註。
|
||
|
||
別名表在 `characters.json`,新增角色或別名時改它。
|
||
|
||
## 測試
|
||
|
||
```bash
|
||
cd tools/corpus && python3 -m unittest -q test_extract_dialogues
|
||
```
|
||
|
||
## 3. 標註(W4)
|
||
|
||
規則只判定約一成,其餘由 Claude sub-agent 標註說話者、功能標籤與情緒。標籤白名單在 `tags.json`,標註指示在 `label_prompt.md`。
|
||
|
||
```bash
|
||
# 試跑:分層抽樣 100 句(未判定 50、規則中信心 25、規則高信心 25)
|
||
python3 tools/corpus/make_batches.py ~/anime-companion-data/sao/dialogues.jsonl ~/anime-companion-data/sao/labeling/pilot/in --pilot 100
|
||
# 每個批次檔交給一個 sub-agent,輸出同名 jsonl 到 .../pilot/out/
|
||
python3 tools/corpus/merge_labels.py ~/anime-companion-data/sao/dialogues.jsonl ~/anime-companion-data/sao/labeling/pilot/out ~/anime-companion-data/sao/labeling/pilot/merged.jsonl --review-dir ~/anime-companion-data/sao/labeling/pilot/review
|
||
```
|
||
|
||
- 批次檔不含規則判定的說話者,讓標註獨立,才能和規則比對。
|
||
- 只採用 `confidence=high` 的說話者;`unknown`、`none`(非說出口的「」)與其他信心都視為未判定。
|
||
- 標籤不在白名單內的整筆丟棄。
|
||
- `--review-dir` 為亞絲娜與直葉各輸出最多 20 句抽查清單。
|
||
|
||
### 試跑結果(100 句)
|
||
|
||
- 標註全部通過白名單檢查,採用 70 句(high 且非 unknown)。
|
||
- 規則高信心與標註一致 20/25,中信心 15/25。不一致的例子顯示規則會把「對她說道」的聽者當成說話者,也會把「我眼前」的「我」當成說話者,所以最終以標註為準,規則只當參考。
|
||
- sub-agent 回報的模糊處(非說出口的「」、無名角色、信心門檻)已補進 `label_prompt.md`。
|
||
|
||
### 全量結果
|
||
|
||
全部 4,324 句分 87 批(每批 50 句)標註,再對早期批次被標成 `none` 的 62 句用新版指示重標。
|
||
|
||
```bash
|
||
python3 tools/corpus/make_batches.py ~/anime-companion-data/sao/dialogues.jsonl ~/anime-companion-data/sao/labeling/full/in --all --batch-size 50
|
||
# 每批交給 sub-agent,輸出到 .../full/out/
|
||
python3 tools/corpus/verify_batches.py ~/anime-companion-data/sao/labeling/full # 逐批比對 id
|
||
python3 tools/corpus/make_relabel.py ~/anime-companion-data/sao/labeling/full ~/anime-companion-data/sao/labeling/relabel/in --max-batch 24
|
||
python3 tools/corpus/merge_labels.py ~/anime-companion-data/sao/dialogues.jsonl ~/anime-companion-data/sao/labeling/full/out,~/anime-companion-data/sao/labeling/relabel/out ~/anime-companion-data/sao/labeling/final.jsonl --review-dir ~/anime-companion-data/sao/labeling/review
|
||
```
|
||
|
||
- 全部通過白名單檢查。早期批次把 `none` 一律標成非說出口的話,重標後只有 2 句改成有說話者。
|
||
- 一個批次把 `confidence` 縮寫成 h/m/l,合併時對應回完整值(`merge_labels.py` 的 `CONFIDENCE_ALIASES`);`worry` 加進情緒白名單。
|
||
- 採用(high 且非 unknown)2,340 句;`none` 673 句;亞絲娜 304 句(第 1 冊 228、第 3 冊 15、第 4 冊 61),直葉/莉法 514 句(第 3 冊 303、第 4 冊 211)。
|
||
- 規則高信心與標註一致 188/262(72%),中信心 82/142(58%),所以最終以標註為準。
|
||
- 多個 agent 並行時共用暫存目錄會互相覆蓋腳本,所以 `verify_batches.py` 逐批比對 id;全部一致。
|
||
- wiki 的部分頁面有重複或錯置的段落,標註 agent 對這類句子多半降為 medium 或 low,不會進入採用的 2,340 句。
|
||
- `mode`(亞絲娜的「被囚禁/重逢」、直葉的「現實/莉法」)目前只有規則依別名推得的少數句子有值,大多數是空的;W5、W6 要另外依章節情境補上。
|
||
|
||
## 4. 角色包(W5、W6)
|
||
|
||
從合併後的標註產生每個角色的對白索引,再寫人格卡並渲染成角色 skill:
|
||
|
||
```bash
|
||
python3 tools/corpus/build_pack.py ~/anime-companion-data/sao/labeling/final.jsonl ~/.claude/anime-companion
|
||
# → ~/.claude/anime-companion/<角色代號>/index.jsonl(執行期檢索用)與 source.jsonl(寫人格卡用,附前文)
|
||
# 人格卡由 sub-agent 讀 source.jsonl 歸納,存到 ~/anime-companion-data/sao/personas/<角色代號>.md
|
||
python3 tools/corpus/render_skill.py ~/anime-companion-data/sao/personas/sao-asuna.md ~/.claude/anime-companion/sao-asuna/index.jsonl plugins/anime-companion/skills/sao-asuna/SKILL.md --code sao-asuna
|
||
```
|
||
|
||
- 入選條件:說話者明確、`confidence=high`、長度 4~80 字、非疑似重複、同句去重;`other` 且少於 6 字的丟掉。
|
||
- 模式標籤由前後文判定,沒判定出來的沿用同一章的多數模式。亞絲娜:`ingame`、`captive`、`reunion`、`real`;直葉:`leafa`(莉法)、`real`(直葉)。這是啟發式,不是人工標註。
|
||
- `render_skill.py` 會檢查人格卡「精選對白」的每一句都逐字來自索引,不一致就失敗。
|
||
- 索引在使用者資料目錄,不入 repo。人格卡(`SKILL.md`)入庫,內含各 38 句、每句不超過 80 字的精選對白。
|
||
- 目前結果:亞絲娜 255 句(ingame 189、reunion 35、captive 20、real 11),直葉 423 句(leafa 344、real 79)。
|