Files
Jeffery (jiantw83)andClaude Sonnet 5.5 697ed6a0b9 feat: 亞絲娜與直葉的角色包 (#6, #7)
build_pack.py 產生對白索引(放在使用者資料目錄);render_skill.py 把人格卡渲染成
角色 skill 並檢查精選對白逐字來自索引;插件改成執行期從資料目錄讀索引。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 20:52:40 +00:00

108 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 文本建置: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)。