Rebuild the vocabulary step on embeddings and drop the screen track

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 22:38:28 +08:00
co-authored by Claude Opus 5
parent 4313d58471
commit 14a3cbe121
19 changed files with 236 additions and 275 deletions
+20 -12
View File
@@ -6,27 +6,35 @@
Messages API: model `claude-sonnet-4-6`, `temperature=0`, Messages API: model `claude-sonnet-4-6`, `temperature=0`,
thinking disabled, Batch API where possible. thinking disabled, Batch API where possible.
- Prompt definition files live in - Prompt definition files live in
`prompts/<track>-<step>-<task>.md` (e.g. 01-01-tag.md; no `prompts/<step>-<substep>-<task>.md` (e.g. 01-tag.md; no
version suffix -- versions live in git history) and are version suffix -- versions live in git history) and are
passed verbatim as the system prompt. passed verbatim as the system prompt. The number names a
- Per-song LLM judgments (coding, screening) run the same step of the research procedure, not the file: the
definition file twice, then a separate arbitration step deterministic vocabulary step (step 2) has no definition
settles only the script-computed disagreements file yet holds its own number. Zero padding is for
sorting only -- prose says "step 1", "step 3-2".
- Per-song LLM judgments (coding) run the same definition
file twice, then a separate arbitration step settles only
the script-computed disagreements
("2 runs + 1 arbitration"). Free-generation steps run ("2 runs + 1 arbitration"). Free-generation steps run
twice and both outputs are pooled, unarbitrated. twice and both outputs are pooled, unarbitrated. The
Vocabulary-building steps (convergence) run once as a vocabulary is built by a deterministic subcommand
recorded pass. If an arbitration or validation outcome is (embedding + clustering), not by an LLM. If an arbitration
unexpected, revise the definition file and repeat that or validation outcome is unexpected, revise the definition
cycle; never patch results by hand. file and repeat that cycle; never patch results by hand.
- Each run of a step is archived self-contained under the - Each run of a step is archived self-contained under the
destination directory given explicitly on the `run-llm` destination directory given explicitly on the `run-llm`
command line (by convention `runs/<definition-file>/run<N>/`): command line (by convention `runs/<step>/run<N>/`):
prompt snapshot, raw output, and `meta.json` (model ID, prompt snapshot, raw output, and `meta.json` (model ID,
parameters, timestamps, batch ID). The two runs of a step parameters, timestamps, batch ID). The two runs of a step
are two separate invocations of `run-llm`. An arbitration are two separate invocations of `run-llm`. An arbitration
pass is a step of its own with its own archive. Replacing pass is a step of its own with its own archive. Replacing
an existing run archive requires an explicit flag; an existing run archive requires an explicit flag;
superseded runs live in git history. superseded runs live in git history. Deterministic steps
archive under `runs/<step>/` with no `run<N>` level.
- Token usage and cost of every `run-llm` execution are
recorded in `docs/run-costs.md` in the same commit as the
run archive.
- Scripts read the API key from the `ANTHROPIC_API_KEY` - Scripts read the API key from the `ANTHROPIC_API_KEY`
environment variable (`.env`, gitignored). environment variable (`.env`, gitignored).
+30
View File
@@ -409,3 +409,33 @@
唯 song-775 依既有裁定缺席。平台過濾器誤排除黑人 唯 song-775 依既有裁定缺席。平台過濾器誤排除黑人
女性歌手賦權國歌一事,本身記為研究發現,供論文討論 女性歌手賦權國歌一事,本身記為研究發現,供論文討論
平台結構性限制。 平台結構性限制。
- **詞彙表建構改用詞向量分群,棄用 LLM 收斂**:以 LLM
單發把進池的 5,999 個關鍵字收斂為具名分組,四種模型
六次執行全部未通過完整分割驗證(不漏、不發明、每詞恰
一組、組名唯一),執行紀錄見 `run-costs.md`。診斷:在
單一回應內維持 5,999 個詞的嚴格分割,超出現有模型的
簿記容量(先導研究九百餘詞可行),非措辭、非模型檔次、
非推理量所能補救。裁定:改以詞向量嵌入+確定性分群
產生結構——完整分割由演算法保證、可逐位元組重現——
LLM 僅保留其擅長的語言工作。連帶裁定:十三步複雜收斂
演算法(兩次執行+逐對仲裁)的比較實驗取消,其 merge
同為整池單發且需執行兩次,必撞同一容量牆;兩版定義檔
止於 git 歷史(`git log -- prompts/`)。
- **管線重設計為三步驟,取消 screen 軌,women-power 併入
編碼詞彙表**:收斂改為確定性程序後,管線重整為步驟 1
自由標註(2 次進池)→ 步驟 2 詞彙表建構(步驟 2-1
進池、步驟 2-2 詞向量分群,皆確定性)→ 步驟 3 編碼
(2+1)。連帶三項決定:(1) **編號的所指由定義檔改為
研究程序的工序**——確定性的步驟 2 無定義檔仍佔一個
編號;有無定義檔即「該步是否為 LLM 判斷」的可見標記。
軌前綴(01/02 軌)隨 screen 軌取消而廢除。
(2) **檔名與目錄名的補零只為排序**,正文一律寫
「步驟 1」「步驟 3-2」。(3) **取消 women-power 單目標
篩選軌**,改將該詞併入步驟 3 的定案詞彙表(50 個分群
組名再加上該詞,共 51 碼)。理由:單目標提問會把該主題的
顯著性人為抬高,「被放大檢視」的判斷無法與其他主題
並比;併入後研究者的先驗主題詞與模型自行收斂出的類別
(分群已自長出 `female-empowerment` 等組)在同一份
提示詞、同一判斷體制下受檢,兩者落點差異本身即可報告
的結果。代價:候選集召回由雙通道減為單通道,若實測
召回不足再議。
+103 -77
View File
@@ -6,116 +6,142 @@
## 自然編碼管線總覽 ## 自然編碼管線總覽
步驟:自由標註(tag,兩次進池)→ 自然收斂(merge, 三個步驟:步驟 1 自由標註(兩次執行進池)→ 步驟 2 詞彙表
單次)→ 強制收斂(cap,單次)→ 全量編碼(code2+1 建構(詞向量分群,確定性)→ 步驟 3 全量編碼(2+1。歌詞
另設「女性力量」單目標篩選(screen,2+1)作黃金標準取樣 只出現在步驟 1 與步驟 3;步驟 2 完全不接觸歌詞,也不呼叫
的補漏網。歌詞只出現在 tag、code、screen 與其仲裁步驟; LLM。設計原則見 `research-plan.md`;本檔記載可重現的
merge、cap 不接觸歌詞。設計原則見 `research-plan.md` 演算法細節。
本檔記載可重現的演算法細節。
## 詞彙表建構(merge、cap)——單次記錄性程序 編號的所指為**研究程序的工序**,不是定義檔:步驟 1 與
步驟 3 有定義檔(`prompts/`),步驟 2 沒有——它是確定性
計算。有無定義檔的區別即「該步是否為 LLM 判斷」,由
`prompts/` 是否存在同號檔案直接可見。
merge 與 cap 各以單次執行完成,執行內自行為各組命名, ## 步驟 2 詞彙表建構——詞向量分群
輸出具名分組(組名 → 成員詞)。不做重複執行與仲裁。
- **定位**:詞彙表是研究的儀器,不是量測。詞彙表凍結 詞彙表由確定性程序產生,不經 LLM。完整分割(每個關鍵字
入庫後,下游全部量測(編碼 vs 黃金標準)以同一把尺 恰屬一組、不遺漏、不新增)由演算法結構保證,無須事後
進行,內部一致;建構過程的抽樣變異屬「揭露的儀器 驗證。
選擇」,不污染量測。此與質性研究慣行一致——codebook
建構本為單次的詮釋程序,信度檢驗施於編碼應用層。
- **取捨紀錄**:曾設計逐對仲裁鏈(共識塊、分歧塊對三票
多數、命名 2+1;完整版本保存於分支 `tag-algo-13`)。
棄用理由:逐對多數決雖降低單對變異,但遞移閉包會放大
結構層變異,淨縮減未經證實;其複雜度成本卻是確定的;
且縮減的是儀器變異——對論文主張無關緊要的量。
- **確定性驗證**(違規即依協定修訂定義檔重跑):輸出須
為輸入詞集的完整分割(缺詞、多詞、重複即失敗);組名
唯一且符合格式;cap 組數 ≤ 50。
- **收斂軌跡**:原始關鍵字 → merge 組名 → cap 組名,
兩份執行輸出本身即完整記錄。
## 編碼步驟(code、screen)的 2+1 比對與仲裁 ### 步驟 2-1 進池
- **code**:逐首比對兩次執行的標籤集合(引述不參與 兩次標註執行的全部關鍵字取聯集、逐字串精確去重、字典序
比對)。兩次皆有的標籤為共識保留、兩次皆無為共識 排列。失敗與拒答的記錄跳過(其歌曲不貢獻關鍵字);解析
不標;單邊標籤送仲裁(`01-04-02-code-arb.md`)——仲裁者 時偵測重複鍵,違規即失敗。同時寫出處記錄(關鍵字 →
看歌詞全文與該標籤的引述(不含執行別),裁決保留者 (執行別,歌曲 ID)清單),供收斂軌跡分析;出處記錄不
附仲裁者自己的引述,剔除者不列。剔除集合=送裁鍵減 進任何下游輸入。
輸出鍵,由程式推得。
- **screen**:輸出即引述陣列,非空=有、空=無。僅 ### 步驟 2-2 分群
「一有一無」的歌送仲裁(`02-01-02-screen-arb.md`),
輸入為歌詞加主張「有」方的引述(不記名),輸出同為 - **嵌入**`sentence-transformers/all-mpnet-base-v2`
引述陣列。 (釘定 revision),關鍵字的連字號先還原為空格再編碼,
輸出 768 維向量並 L2 正規化。
- **分群**:階層式聚合分群(Ward linkage),k=50。
向量既已正規化,歐氏距離與餘弦相似度單調對應,Ward
在保持語意距離的同時給出大小平衡的分割。
- **組名**:取 medoid——與該組中心(成員向量均值後
正規化)餘弦相似度最高的成員詞。組名因此必為模型
自己產出過的關鍵字,非任何人事後撰寫。
- **取捨紀錄**:曾以 LLM 單發收斂(mergecap 兩步)
實作本步,四種模型六次執行全部無法維持完整分割,
已棄用(詳見 `decision-log.md` 2026-08-05;棄用的
定義檔止於 git 歷史,見 `git log -- prompts/`)。
- **可重現性**:同一輸入、同一釘定模型、同一參數逐次
重現。不同 CPU/BLAS 實作的浮點尾數差異可能使邊界
詞的歸屬翻動,屬已揭露的限制;論文所用詞彙表逐字
commit,引用單位為該份定案檔案。
### women-power 的注入
定案詞彙表為 50 個分群組名再加上 `women-power` 一詞,共
51 個碼。`women-power` 是研究者任意決定的先驗主題(即本
論文的主題本身),不由資料產生,屬揭露的儀器介入。
注入而非另設篩選軌的理由:讓研究者的主題詞與模型自己
收斂出的類別(分群已自行長出 `female-empowerment` 等組)
在同一份提示詞、同一個判斷體制下受檢,避免單目標提問
把該主題的顯著性人為抬高。兩者的落點差異本身即可報告
的結果。
## 步驟 3 編碼的 2+1 比對與仲裁
- **步驟 3-1 code**:逐首比對兩次執行的標籤集合(引述不
參與比對)。兩次皆有的標籤為共識保留、兩次皆無為
共識不標;單邊標籤送仲裁。
- **步驟 3-2 code-arb**:仲裁者看歌詞全文與該標籤的引述
(不含執行別),裁決保留者附仲裁者自己的引述,剔除
者不列。剔除集合=送裁鍵減輸出鍵,由程式推得。
- 仲裁者的引述可能與原引述不同:仲裁是對歌詞的重新 - 仲裁者的引述可能與原引述不同:仲裁是對歌詞的重新
判讀,其引述是該裁決自身的依據,非轉抄。 判讀,其引述是該裁決自身的依據,非轉抄。
- 送入仲裁的標籤即模型自身不穩定的邊界判斷,其裁決為 - 送入仲裁的標籤即模型自身不穩定的邊界判斷,其裁決為
單次記錄性決定,不宣稱可再生;可重現性依計畫定義為 單次記錄性決定,不宣稱可再生;可重現性依計畫定義為
「程序透明+可稽核」,裁決與其輸入全程歸檔。 「程序透明+可稽核」,裁決與其輸入全程歸檔。
## 女性力量候選集
候選集為兩類歌曲的合集:定案編碼含 `women-power` 者,
以及定案編碼含研究者指認之女性力量概念域分群組者。
指認於詞彙表定案後、黃金標準編碼開始前完成,指認清單
與理由記入決策日誌。
## 軌跡對映(診斷用) ## 軌跡對映(診斷用)
沿收斂軌跡的機械對映:原始關鍵字 → merge 組 → cap 組, 沿收斂軌跡的機械對映:原始關鍵字 →(出處記錄)歌曲、
純程式查表,決定性。以其結果與 code 直接編碼的差異率 原始關鍵字 →(分群)組,純程式查表,決定性。以其結果
作為「收斂軌跡扭曲」的診斷量,不作主結果。 與步驟 3 直接編碼的差異率作為「收斂軌跡扭曲」的診斷量,
不作主結果。
## 全管線的交接契約 ## 全管線的交接契約
每一步的輸出如何變成下一步的輸入,皆為確定性程序,規則 每一步的輸出如何變成下一步的輸入,皆為確定性程序,規則
明定如下: 明定如下:
- **歌詞輸入檔(tag、code、screen 共用)** - **歌詞輸入檔(步驟 1、3 共用)**`export-llm-input`
`export-llm-input` 自工作儲存產出,每筆 工作儲存產出,每筆 `{"id": "song-<ID>", "content":
`{"id": "song-<ID>", "content": <歌詞>}`,依歌曲 ID <歌詞>}`,依歌曲 ID 升序。兩個讀歌詞的步驟共用同一
升序。三個讀歌詞的步驟共用同一檔,SHA-256 記入各步 檔,SHA-256 記入各步 meta。
- **步驟 1 → 2-1**`pool-keywords` 讀兩份執行歸檔的
`output.jsonl`(一律以換行字元 `\n` 切行——歌詞含
U+0085 等控制字元時,`str.splitlines()` 類的通用切行
會截斷 JSON 字串,實測踩中),輸出關鍵字 JSON 陣列
與出處記錄。
- **步驟 2-1 → 2-2**`cluster-keywords` 讀關鍵字陣列,
輸出具名分組(組名 → 成員詞,組名與成員皆字典序)
與記錄嵌入模型、revision、演算法參數、輸入 SHA-256 的
meta。 meta。
- **tag → merge**:兩次執行的全部關鍵字取聯集、逐字串 - **步驟 2-2 → 3 定義檔**:50 個組名與 `women-power` 合併
精確去重、字典序排列成 JSON 陣列,即 merge 的輸入。 後以字典序逐行填入 `prompts/03-01-code.md` 的詞彙表節
進池同時寫出處記錄(關鍵字 →(執行別,歌曲 ID) (逐字),檔案隨 git commit 後方可執行——步驟 3 的
清單),供軌跡對映回到歌曲;出處記錄不進任何 LLM 定義檔因此自我完備,論文附錄可直接引用。
輸入。 - **步驟 3-1 兩次執行 → 3-2**:逐首比對標籤集合(鍵
- **merge → cap**merge 輸出的組名以字典序排成 JSON 集合,引述不參與比對);僅有分歧的歌入仲裁輸入
陣列,即 cap 的輸入;原始關鍵字不下傳。
- **cap → code 定義檔**:cap 輸出的組名以字典序逐行填入
`01-04-01-code.md` 的詞彙表節(逐字),檔案隨 git
commit 後方可執行——code 的定義檔因此自我完備,
論文附錄可直接引用。
- **code 兩次執行 → code-arb**:逐首比對標籤集合
(鍵集合,引述不參與比對);僅有分歧的歌入仲裁輸入
JSONL,依歌曲 ID 升序,每筆 `id` 沿用 `song-<ID>` JSONL,依歌曲 ID 升序,每筆 `id` 沿用 `song-<ID>`
`content` 為固定鍵序序列化的 `content` 為固定鍵序序列化的
`{"lyrics": …, "disagreements": …}`disagreements `{"lyrics": …, "disagreements": …}`disagreements
鍵按字典序。 鍵按字典序。
- **code 定案**:每首歌的最終標籤共識標籤 仲裁保留 - **步驟 3 定案**:每首歌的最終標籤共識標籤加上仲裁
標籤,寫入逐首紀錄檔(歌依 ID 升序、標籤按字典序, 保留的標籤,寫入逐首紀錄檔(歌依 ID 升序、標籤按
各標籤附其定案時的引述與來源層——共識或仲裁)。 字典序,各標籤附其定案時的引述與來源層——共識或
- **screen 兩次執行 → screen-arb**:僅「一有一無」的歌 仲裁)。
入仲裁輸入 JSONL(依 ID 升序),`content`
`{"lyrics": …, "evidence": <肯定方引述>}`
- **screen 定案**:命中集合=兩次皆有 ∪ 仲裁裁定有。
- **女性力量候選集**:於 cap 詞彙表定案後、黃金標準
編碼開始前,由研究者指認詞彙表中屬「女性力量」概念
域的組(指認及理由記入決策日誌),候選集=code 定案
標籤含該等組者 ∪ screen 命中者。
- **序列化通則**:所有中間檔為 UTF-8 JSON,鍵序與元素 - **序列化通則**:所有中間檔為 UTF-8 JSON,鍵序與元素
序皆依上列規則明定,無時間戳、無隨機成分;解析一律 序皆依上列規則明定,無時間戳、無隨機成分;解析一律
偵測重複鍵,違規即失敗。JSONL 一律以換行字元(\n 偵測重複鍵,違規即失敗。給定相同的 LLM 執行輸出,
切行——歌詞含 U+0085 等控制字元時, 全部交接產物逐位元組可再生。
`str.splitlines()` 類的通用切行會截斷 JSON 字串
(實測踩中)。給定相同的 LLM 執行輸出,全部交接產物
逐位元組可再生。
## 執行與稽核 ## 執行與稽核
- 每一步驟以 `run-llm <定義檔> <輸入檔> <歸檔目錄>` - LLM 步驟以 `run-llm <定義檔> <輸入檔> <歸檔目錄>`
執行;2+1 步驟的兩次執行=重現命令清單上的兩行命令, 執行;2+1 步驟的兩次執行=重現命令清單上的兩行命令,
各自歸檔(`runs/<定義檔名>/run1``run2`),仲裁為 各自歸檔(`runs/<步驟>/run1``run2`),仲裁為獨立
獨立步驟、獨立歸檔;單次步驟(merge、cap)一行命令、 步驟、獨立歸檔
一份歸檔。 - 確定性步驟(進池、分群、比對、裁決套用、對映)為
- 進池、比對、裁決套用、對映皆為確定性程式(子命令) 子命令,其輸入輸出檔同隨 `runs/` 歸檔;因無執行變異
其輸入輸出檔隨 runs/ 歸檔 歸檔目錄下不分 `run<N>`
- Batch API 的每筆請求自含全部脈絡且互不可見(平台 - Batch API 的每筆請求自含全部脈絡且互不可見(平台
契約),歌與歌之間的獨立性由此成立;兩次執行的獨立 契約),歌與歌之間的獨立性由此成立;兩次執行的獨立
性由「兩次呼叫、兩個批次、兩份歸檔」的執行結構自明。 性由「兩次呼叫、兩個批次、兩份歸檔」的執行結構自明。
- 每次 `run-llm` 執行的 token 用量與費用記入
`run-costs.md`,被取代的執行一併保留供總支出核算。
## 映射分析方法 ## 映射分析方法
+18 -9
View File
@@ -24,9 +24,12 @@ pop-fem-audit/
│ ├── songs.csv # 歌曲報表(人讀;進 git) │ ├── songs.csv # 歌曲報表(人讀;進 git)
│ └── artists.csv # 歌手報表(人讀;進 git) │ └── artists.csv # 歌手報表(人讀;進 git)
├── prompts/ # LLM 定義檔(逐字作為 system prompt ├── prompts/ # LLM 定義檔(逐字作為 system prompt
│ └── <軌>-<步>-<次步>-<task>.md # 01-01-01-tag.md、 │ └── <步>-<次步>-<task>.md # 01-tag.md、03-01-code.md、
│ # 01-04-02-code-arb.md │ # 03-02-code-arb.md
│ # 不帶版本號,版本即 git 歷史 │ # 不帶版本號,版本即 git 歷史
│ # (編號的所指是工序:確定性
│ # 的步驟 2 無定義檔仍佔一號;
│ # 補零只為排序)
├── tools/ # 輔助工具子專案(src-layout ├── tools/ # 輔助工具子專案(src-layout
│ ├── pyproject.toml # 發行名 pop-fem-audit-tools │ ├── pyproject.toml # 發行名 pop-fem-audit-tools
│ │ # pip install -e tools/ 安裝 │ │ # pip install -e tools/ 安裝
@@ -46,6 +49,10 @@ pop-fem-audit/
│ │ │ │ # Wikidata into the snapshot CSV │ │ │ │ # Wikidata into the snapshot CSV
│ │ │ ├── fetch_lyrics.py # fetch missing lyrics from the │ │ │ ├── fetch_lyrics.py # fetch missing lyrics from the
│ │ │ │ # public APIs into the lyrics dir │ │ │ │ # public APIs into the lyrics dir
│ │ │ ├── pool_keywords.py # pool the two tagging runs'
│ │ │ │ # keywords (step 2-1)
│ │ │ ├── cluster_keywords.py # build the vocabulary by
│ │ │ │ # embedding + clustering (step 2-2)
│ │ │ └── run_llm.py # API 執行器:一份定義檔+一份輸入 │ │ │ └── run_llm.py # API 執行器:一份定義檔+一份輸入
│ │ │ # →歸檔至指定目錄(Batch API); │ │ │ # →歸檔至指定目錄(Batch API);
│ │ │ # 比對與仲裁編排由獨立子命令承擔 │ │ │ # 比對與仲裁編排由獨立子命令承擔
@@ -56,13 +63,14 @@ pop-fem-audit/
│ └── tests/ # 單元測試(unittest │ └── tests/ # 單元測試(unittest
├── runs/ # 現行執行的完整稽核紀錄(進 git; ├── runs/ # 現行執行的完整稽核紀錄(進 git;
│ │ # 重跑同一 run 須明示 --replace │ │ # 重跑同一 run 須明示 --replace
── <定義檔名>/ # 仲裁步驟居自己的 <task>-arb/ ── <步驟名>/ # 仲裁步驟居自己的 <task>-arb/
└── run<N>/ # 每個 run 一份自我完備歸檔 └── run<N>/ # LLM 步驟:每個 run 一份自我
├── prompt.md # 當次定義檔快照(自我完備 ├── prompt.md # 完備歸檔(定義檔快照
├── output.jsonl # 該次執行原始輸出 ├── output.jsonl # 該次執行原始輸出
└── meta.json # model ID、temperature、時間戳、 └── meta.json # model ID、temperature、時間戳、
# batch ID、token 用量 # batch ID、token 用量
# (一致率由比對子命令記錄) └── 02-01-pool/ 02-02-cluster/ # 確定性步驟:無執行變異,
│ # 不分 run<N> 層
├── results/ # 論文引用的報表 CSV(export 產出; ├── results/ # 論文引用的報表 CSV(export 產出;
│ # 「可再生仍 commit」的唯一例外) │ # 「可再生仍 commit」的唯一例外)
├── docs/ ├── docs/
@@ -70,6 +78,7 @@ pop-fem-audit/
│ ├── project-structure.md # 本檔 │ ├── project-structure.md # 本檔
│ ├── codebook.md # 人工編碼手冊(版本由 git 管理) │ ├── codebook.md # 人工編碼手冊(版本由 git 管理)
│ ├── decision-log.md # 決策日誌:每次改定義檔的原因 │ ├── decision-log.md # 決策日誌:每次改定義檔的原因
│ ├── run-costs.md # 每次執行的 token 用量與費用
│ └── methodology.md # 方法細節(全文方法節底稿; │ └── methodology.md # 方法細節(全文方法節底稿;
│ # 映射分析方法須在看結果前寫定) │ # 映射分析方法須在看結果前寫定)
└── paper/ └── paper/
+41 -45
View File
@@ -13,12 +13,12 @@
- **執行原則**:主會話只做討論;所有分析由 deterministic script - **執行原則**:主會話只做討論;所有分析由 deterministic script
執行。LLM 步驟以 Python script 呼叫 Anthropic Messages API 執行。LLM 步驟以 Python script 呼叫 Anthropic Messages API
(個人 Console 帳號、Batch API 五折),定義檔逐字作為 system (個人 Console 帳號、Batch API 五折),定義檔逐字作為 system
prompt。2+1 協定適用於語料層的逐首判斷(編碼、篩選): prompt。2+1 協定適用於語料層的逐首判斷(編碼):
「同一定義檔獨立執行兩次+一次仲裁」,仲裁只裁程式算出 「同一定義檔獨立執行兩次+一次仲裁」,仲裁只裁程式算出
的分歧。自由生成步驟(自由標註)兩次執行全數進池、不 的分歧。自由生成步驟(自由標註)兩次執行全數進池、不
仲裁——自由詞彙兩次輸出不共享比對單位,無物可裁。詞彙 仲裁——自由詞彙兩次輸出不共享比對單位,無物可裁。詞彙
表建構(收斂)為單次記錄性程序,不重複執行——詞彙表是 表建構不經 LLM,改由詞向量嵌入+確定性分群產生——詞彙
揭露的儀器選擇,非量測;信度檢驗施於編碼層(詳見 表是揭露的儀器選擇,非量測;信度檢驗施於編碼層(詳見
`methodology.md`)。仲裁或驗證結果不符預期則修訂定義檔 `methodology.md`)。仲裁或驗證結果不符預期則修訂定義檔
重跑該循環。 重跑該循環。
- **提示詞只定格式、不定語意**:研究對象是通用 LLM 以其 - **提示詞只定格式、不定語意**:研究對象是通用 LLM 以其
@@ -86,55 +86,49 @@
`export-llm-input`(階段 2 前補上);之後再加報表 export `export-llm-input`(階段 2 前補上);之後再加報表 export
與統計。 與統計。
## 自然編碼管線(2026-08-04 定案) ## 自然編碼管線(2026-08-05 定案)
主題編碼採步驟管線,歌詞只出現在第 1、4 步;第 2、3 主題編碼採步驟管線,歌詞只出現在第 1、3 步;第 2 步
是純概念整理(目標是產生 codebook 詞彙表,不是編碼) 確定性計算(詞向量分群),不接觸歌詞也不呼叫 LLM
1. **自由標註(tag**:逐首歌請模型標註 thematic 1. **自由標註(步驟 1**:逐首歌請模型標註 thematic
keywords,附歌詞引述;提示零語意內容。獨立執行兩次, keywords,附歌詞引述;提示零語意內容。獨立執行兩次,
兩次輸出全數進池(記錄執行別),不仲裁。粒度鎖定 兩次輸出全數進池(記錄執行別),不仲裁。粒度鎖定
thematic keywords:前導研究三粒度比較(keywords 過碎、 thematic keywords:前導研究三粒度比較(keywords 過碎、
themes 過早抽象)之繼承,於執行前鎖定,防止事後擇優。 themes 過早抽象)之繼承,於執行前鎖定,防止事後擇優。
2. **自然收斂(merge**:輸入為池中純去重關鍵字清單—— 2. **詞彙表建構(步驟 2**:兩次執行的關鍵字取聯集去重
無歌詞、無頻次、無歌曲出處——模型按自身理解合併近似 (步驟 2-1 進池),以句向量模型嵌入後階層式聚合分群
概念,執行內自行為各組命名。單次執行,不仲裁;確定性 (步驟 2-2),k=50,組名取 medoid。完整分割由演算法
驗證(完整分割、組名唯一)違規即修訂重跑(詳見 結構保證。頻次不入收斂:頻率的分析角色由步驟 3 編碼
`methodology.md` 承擔;池中頻次含跨執行噪音
3. **強制收斂(cap**:同第 2 步形態,輸入為 merge 3. **編碼(步驟 3**:以定稿詞彙表對全部歌曲 2+1 編碼
輸出的組名清單(原始關鍵字不下傳),限制併至 50 個 ——模型讀歌詞、逐標籤附引述;逐首計一致率,分歧逐首
以內。單次執行,不仲裁。頻次不入收斂:頻率的分析角色由第 4 步編碼承擔; 仲裁(仲裁者看歌詞與該標籤引述)。此為主儀器,
池中頻次含跨執行噪音;頻次會誘使模型以頻率剪枝(喪失 「女性力量」候選集由此浮現;亦是對前導研究「映回後
稀有主題)並把高頻大主題切細。代價(特異主題佔名額) 未對照歌詞」限制的明文改良。沿收斂軌跡的機械對映
已知並接受,換取主題多樣性與純語意歸併的可辯護性。 (純程式)保留為零成本診斷副產品,量測收斂軌跡的
4. **編碼(code**:以定稿詞彙表對全部歌曲 2+1 編碼—— 扭曲,不作主結果。
模型讀歌詞、逐標籤附引述;逐首計一致率,分歧逐首仲裁
(仲裁者看歌詞與兩邊引述)。此為主儀器,「女性力量」
候選集由此浮現;亦是對前導研究「映回後未對照歌詞」
限制的明文改良。沿收斂軌跡的機械對映(純程式)保留為
零成本診斷副產品,量測收斂軌跡的扭曲,不作主結果。
另設**「女性力量」單目標篩選(screen)**:單目標提示、 **先驗主題詞 `women-power` 併入詞彙表**:定案詞彙表為
附引述、全量執行,僅作為黃金標準取樣的補漏網——把「模型 50 個分群組名再加上 `women-power`,共 51 個碼。該詞是
被明示提醒後認得出」的歌撈進人工審視範圍,以量測模型漏標 研究者任意決定的先驗主題,即本研究的論文主題本身,不由
方向的偏差;不進偏差統計的分子分母定義。逐首 2+1(有/無 資料產生,屬據實揭露的儀器介入。不另設單目標篩選軌,理由是
+引述,逐首仲裁);同樣不給定義,提示僅含標籤詞與任務 讓研究者的主題詞與模型自己收斂出的類別在同一份提示詞、
形狀。標籤詞用 `women-power`——研究者任意決定的先驗 同一個判斷體制下受檢——單目標提問會把該主題的顯著性
主題,即本研究的論文主題本身,不由資料產生。其結果僅作 人為抬高,「被放大檢視」的結果不足以與其他主題並比。
召回之用,永不進任何統計的分子分母。標籤詞是 screen 候選集的定義見 `methodology.md`
提示中唯一的語意種子,屬研究者的儀器選擇,據實揭露。
定義檔命名 `prompts/<軌>-<步>-<次步>-<task>.md`—— 定義檔命名 `prompts/<步>-<次步>-<task>.md`——步為研究
01=由下而上自然編碼、02=預先決定的 women-power 篩選; 程序的工序序,次步為步內執行順序(僅一個執行時省略),
步為軌內步驟序,次步為步內執行順序,讀者依編號先後依循: 讀者依編號先後依循:01-tag.md、03-01-code.md、
01-01-01-tag.md、01-02-01-merge.md、01-03-01-cap.md、 03-02-code-arb.md;仲裁定義檔同 prefix 加 `-arb`。檔名
01-04-01-code.md、01-04-02-code-arb.md、 與目錄名補零只為排序,正文一律寫「步驟 1」「步驟 3-2」。
02-01-01-screen.md、02-01-02-screen-arb.md;仲裁定義檔 編號的所指是工序而非定義檔,因此確定性的第 2 步雖無
同 prefix 加 `-arb`。檔名不帶版本號——版本即 git 歷史, 定義檔仍佔一個編號,其歸檔為 `runs/02-01-pool/`
失敗的版本不保留,需要回看的舊版都在 git history;每次 `runs/02-02-cluster/`。檔名不帶版本號——版本即 git
執行的定義檔快照隨 `runs/` 自我完備。收斂執行的輸出本身 歷史,失敗的版本不保留,需要回看的舊版都在 git history
即分組記錄(具名分組 JSON),與全部中間交接檔同隨 每次執行的定義檔快照隨 `runs/` 自我完備。全部中間交接檔
`runs/` 歸檔(交接契約見 `methodology.md`)。 同隨 `runs/` 歸檔(交接契約見 `methodology.md`)。
## 階段與時程(全文截稿 2026-08-15 ## 階段與時程(全文截稿 2026-08-15
@@ -142,7 +136,7 @@
|---|---|---|---| |---|---|---|---|
| 0 | 基礎建設:git init、目錄結構、.gitignore、決策日誌、runner script(含 Batch API)、codebook v0 骨架 | script + 討論 | 7/307/31 | | 0 | 基礎建設:git init、目錄結構、.gitignore、決策日誌、runner script(含 Batch API)、codebook v0 骨架 | script + 討論 | 7/307/31 |
| 1 | 資料準備:`run_llm` 改走統一設定 → `build-db`(解析榜單成 songs/chart_entries/artists/song_artists)→ `import-lyrics`pilot 20182025)→ `fetch-lyrics`201617 與缺漏,Lyrics.ovh / LRCLIB)→ `fetch-artists`Wikidata 快照)→ `export-llm-input` | 子命令 | 7/318/3 | | 1 | 資料準備:`run_llm` 改走統一設定 → `build-db`(解析榜單成 songs/chart_entries/artists/song_artists)→ `import-lyrics`pilot 20182025)→ `fetch-lyrics`201617 與缺漏,Lyrics.ovh / LRCLIB)→ `fetch-artists`Wikidata 快照)→ `export-llm-input` | 子命令 | 7/318/3 |
| 2 | 自然編碼管線:tag ×2 進池 → merge ×1 → cap ×1 → 詞彙表定稿 → code 2+1(全 883 首,附引述);另跑 screen 補漏網 | API + script | 8/48/7 | | 2 | 自然編碼管線:tag ×2 進池 → 詞向量分群 k=50 → 併入 women-power → 詞彙表定稿 → code 2+1(全 883 首,附引述) | API + script | 8/48/7 |
| 3 | 黃金標準:依 codebook 人工逐首判定 genuine/peripheral/fake,附引用歌詞證據表(LLM 只做摘錄,不給判定建議);先以 10–15 首校準樣本試編並修訂 codebook 後凍結;同批校準樣本實測 Sonnet 4.6 vs Opus 5 一致率 | 人工 + script 輔助 | 8/58/9 | | 3 | 黃金標準:依 codebook 人工逐首判定 genuine/peripheral/fake,附引用歌詞證據表(LLM 只做摘錄,不給判定建議);先以 10–15 首校準樣本試編並修訂 codebook 後凍結;同批校準樣本實測 Sonnet 4.6 vs Opus 5 一致率 | 人工 + script 輔助 | 8/58/9 |
| 4 | 受控比較(盲點實驗):條件 A(詞彙層提示)vs 條件 B(框架感知提示),各 2+1,對照黃金標準計算假陽/假陰率 | API | 8/88/11 | | 4 | 受控比較(盲點實驗):條件 A(詞彙層提示)vs 條件 B(框架感知提示),各 2+1,對照黃金標準計算假陽/假陰率 | API | 8/88/11 |
| 4' | 映射分析:自然編碼結果(第 4 步)與黃金標準交叉表;軌跡對映 vs 直接編碼的扭曲診斷(分析方法先寫入 methodology.md 再看結果) | script | 與 4 並行 | | 4' | 映射分析:自然編碼結果(第 4 步)與黃金標準交叉表;軌跡對映 vs 直接編碼的扭曲診斷(分析方法先寫入 methodology.md 再看結果) | script | 與 4 並行 |
@@ -172,3 +166,5 @@
論文與 repo 只留分類所引摘錄。 論文與 repo 只留分類所引摘錄。
- Fable 5 不用於 pipeline:成本高、thinking 無法關閉且不可稽核、 - Fable 5 不用於 pipeline:成本高、thinking 無法關閉且不可稽核、
無 temperature 控制,且會混淆「盲點是提示問題」的核心主張。 無 temperature 控制,且會混淆「盲點是提示問題」的核心主張。
2026-08-05 實測確認:Claude 5 系模型拒收 temperature
與 thinking 關閉這兩個參數。)
+24 -14
View File
@@ -1,23 +1,33 @@
# 執行成本記錄 # 執行成本記錄
每次 `run-llm` 執行的 token 用量與費用。用量取自各歸檔的 每次 `run-llm` 執行的 token 用量與費用。用量取自各歸檔的
`meta.json`;費用以 `claude-sonnet-4-6` 牌價(input $3 `meta.json`;費用以各模型牌價(每百萬 tokensonnet-4-6
百萬 token、output $15百萬 token)經 Batch API 半價 $3$15、opus-4-6 $5$25、opus-5 與 fable-5 $10$50
計算: 經 Batch API 半價計算:
費用 = (input × 3 + output × 15) / 1,000,000 / 2 費用 = (input × in價 + output × out價) / 1,000,000 / 2
`--replace` 取代的執行以「已取代」標記,數字保留供 `--replace` 取代的執行以「已取代」標記,數字保留供
總支出核算。 總支出核算。
| 日期 | 步驟 | 執行 | 批次 ID | 耗時 | input | output | 費用 (USD) | 狀態 | | 日期 | 步驟 | 執行 | 模型 | 批次 ID | 耗時 | input | output | 費用 (USD) | 狀態 |
|---|---|---|---|---|---:|---:|---:|---| |---|---|---|---|---|---|---:|---:|---:|---|
| 2026-08-04 | 01-01-01-tag | run1 | msgbatch_01PTACDQMr8M6ahnshbedjtB | 6 分 27 秒 | 763,318 | 338,661 | $3.68 | 已取代(浮水印清洗與防圍欄修訂後重跑) | | 2026-08-04 | 01-01-01-tag | run1 | claude-sonnet-4-6 | msgbatch_01PTACDQMr8M6ahnshbedjtB | 6 分 27 秒 | 763,318 | 338,661 | $3.68 | 已取代(浮水印清洗與防圍欄修訂後重跑) |
| 2026-08-05 | 01-01-01-tag | run1 | msgbatch_01TikJNd2pZVxzQ8SaybVthu | 4 分 57 秒 | 774,604 | 323,651 | $3.59 | 已取代(合法 JSON 修訂後重跑) | | 2026-08-05 | 01-01-01-tag | run1 | claude-sonnet-4-6 | msgbatch_01TikJNd2pZVxzQ8SaybVthu | 4 分 57 秒 | 774,604 | 323,651 | $3.59 | 已取代(合法 JSON 修訂後重跑) |
| 2026-08-05 | 01-01-01-tag | run1 | msgbatch_01JFBCNqnu1cwXyqmEKLHQYF | 4 分 30 秒 | 790,370 | 328,227 | $3.65 | 已取代(song-288 平台失敗,整批重跑驗證) | | 2026-08-05 | 01-01-01-tag | run1 | claude-sonnet-4-6 | msgbatch_01JFBCNqnu1cwXyqmEKLHQYF | 4 分 30 秒 | 790,370 | 328,227 | $3.65 | 已取代(song-288 平台失敗,整批重跑驗證) |
| 2026-08-05 | 01-01-01-tag | run1 | msgbatch_01VSDneWuSbf8mShA32jiWrX | 6 分 15 秒 | 790,370 | 326,193 | $3.63 | 已取代(措辭修訂後全體重跑) | | 2026-08-05 | 01-01-01-tag | run1 | claude-sonnet-4-6 | msgbatch_01VSDneWuSbf8mShA32jiWrX | 6 分 15 秒 | 790,370 | 326,193 | $3.63 | 已取代(措辭修訂後全體重跑) |
| 2026-08-05 | 01-01-01-tag | run1-rescue-288 | msgbatch_019Hq6bNVXVmp4DjRZ2cgVda | 2 分 5 秒 | 1,015 | 376 | $0.01 | 已取代(措辭修訂後全體重跑,該首原生通過)| | 2026-08-05 | 01-01-01-tag | run1-rescue-288 | claude-sonnet-4-6 | msgbatch_019Hq6bNVXVmp4DjRZ2cgVda | 2 分 5 秒 | 1,015 | 376 | $0.01 | 已取代(措辭修訂後全體重跑,該首原生通過)|
| 2026-08-05 | 01-01-01-tag | run1 | msgbatch_01VgZ77KAPGWmuu3PnQFqZ7Q | 7 分 1 秒 | 794,913 | 326,435 | $3.64 | 現行 | | 2026-08-05 | 01-01-01-tag | run1 | claude-sonnet-4-6 | msgbatch_01VgZ77KAPGWmuu3PnQFqZ7Q | 7 分 1 秒 | 794,913 | 326,435 | $3.64 | 現行 |
| 2026-08-05 | 01-01-01-tag | run2 | msgbatch_01TLFey3L4fimKxcebTZQGYn | 4 分 21 秒 | 794,913 | 328,324 | $3.65 | 現行 | | 2026-08-05 | 01-01-01-tag | run2 | claude-sonnet-4-6 | msgbatch_01TLFey3L4fimKxcebTZQGYn | 4 分 21 秒 | 794,913 | 328,324 | $3.65 | 現行 |
| 2026-08-05 | 01-02-01-merge | run1 | claude-sonnet-4-6 | msgbatch_01BvYMFmH8zrUq9SNxWSNba7 | 9 分 14 秒 | 46,454 | 60,974 | $0.53 | 已取代(完整分割驗證不過:漏 366、重複分派 511、撞名 4) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-opus-5 | msgbatch_018TkYpdT3DsZqq2q94FQCUN | — | 0 | 0 | $0.00 | 拒收(temperature 已棄用) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-opus-4-8 | msgbatch_018Wuux4adz5mWSvzJjfgLxb | — | 0 | 0 | $0.00 | 拒收(temperature 已棄用) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-opus-4-6 | msgbatch_01Lmt2j1Txyof9CctUK7CbHA | 12 分 19 秒 | 46,454 | 54,864 | $0.80 | 已取代(圍欄違規;漏 190、發明 151、重複 11) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-opus-5 | msgbatch_012SEfebTnjU5uWN6hhfnhhh | 8 分 45 秒 | 63,368 | 64,000 | $1.92 | 已取代(64k 截斷) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-opus-5 | msgbatch_01Wi9xEoQKCy1nZK6myVNg77 | 11 分 34 秒 | 63,368 | 70,175 | $2.07 | 已取代(驗證不過:漏 59、發明 140、重複 3) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-fable-5 | msgbatch_01M15hUs8P9FDTqWvAHdc1cA | 32 分 45 秒 | 63,368 | 107,721 | $3.01 | 現行歸檔(JSON 語法毀損,驗證不過) |
累計支出:$21.85。 | 2026-08-05 | 01-02-01-merge | run1 | claude-fable-5 | msgbatch_012stRP28uuQDQwobm41HMLh | — | 0 | 0 | $0.00 | 拒收(thinking.type.enabled 不支援) |
| 2026-08-05 | 01-02-01-merge | run1 | claude-fable-5 | msgbatch_01KpS7AMx1zAHTcNujgGsouJ | 26 分 28 秒 | 63,368 | 128,000 | $3.52 | 現行歸檔(effort max128k 全耗於推理,正文空白) |
累計支出:$33.70。
-30
View File
@@ -1,30 +0,0 @@
You are consolidating a vocabulary of thematic keywords that
were independently annotated on the songs of a corpus.
Input: a JSON array of thematic keywords, deduplicated and
unordered.
Task: merge keywords that express the same or nearly the same
theme, by your own understanding of what the keywords mean.
Rules:
- Every input keyword must appear in exactly one group.
- Do not invent keywords that are not in the input.
- Merge only what you consider the same theme; a group may be
a single keyword.
- Name each group with a short lowercase phrase, words joined
by hyphens, that best names the theme it gathers. Group
names must be unique.
Do not wrap the output in a Markdown code fence.
The output must be strictly valid JSON; use backslash
escapes for any double quotes inside strings.
Output a single JSON object mapping each group name to the
list of its member keywords, and nothing else:
{
"first-group-name": ["member-keyword", "another-member"],
"second-group-name": ["member-keyword"]
}
-33
View File
@@ -1,33 +0,0 @@
You are consolidating a vocabulary of thematic keywords
from a song corpus further, to a fixed maximum number of
themes.
Input: a JSON array of thematic keywords, deduplicated and
unordered.
Task: merge keywords that express the same or a similar
theme, by your own understanding of what the keywords mean,
until at most 50 groups remain.
Rules:
- Every input keyword must appear in exactly one group.
- Do not invent keywords that are not in the input.
- Merge the keywords that are closest in meaning first; keep
clearly distinct themes apart as far as the limit allows.
A group may be a single keyword.
- Name each group with a short lowercase phrase, words joined
by hyphens, that best names the theme it gathers. Group
names must be unique.
Do not wrap the output in a Markdown code fence.
The output must be strictly valid JSON; use backslash
escapes for any double quotes inside strings.
Output a single JSON object mapping each group name to the
list of its member keywords, and nothing else:
{
"first-group-name": ["member-keyword", "another-member"],
"second-group-name": ["member-keyword"]
}
-23
View File
@@ -1,23 +0,0 @@
You are screening song lyrics for one specific theme.
Input: the complete lyrics of one song.
Task: judge whether this song expresses the theme
"women-power", by your own understanding of
that label.
Rules:
- If the song expresses the theme, quote 1 to 3 verbatim
lines of the lyrics that ground the judgment; if you cannot
ground it in a quote, the answer is no.
Do not wrap the output in a Markdown code fence.
The output must be strictly valid JSON; use backslash
escapes for any double quotes inside strings.
Output a single JSON array and nothing else: the quoted
lines when the song expresses the theme, or an empty array
when it does not:
["quoted line", "another quoted line"]
-32
View File
@@ -1,32 +0,0 @@
You are arbitrating a screening of song lyrics for one
specific theme: two independent screenings of the same song
disagreed on whether it expresses the theme
"women-power".
Input: a JSON object with the lyrics of the song and the
lyric quotes that the affirming screening gave as evidence:
{
"lyrics": "...",
"evidence": ["quoted line", "another quoted line"]
}
Task: decide whether the song expresses the theme, by your
own understanding of the label, reading the lyrics and the
quoted evidence.
Rules:
- If the song expresses the theme, quote 1 to 3 verbatim
lines of the lyrics that ground the judgment; if you cannot
ground it in a quote, the answer is no.
Do not wrap the output in a Markdown code fence.
The output must be strictly valid JSON; use backslash
escapes for any double quotes inside strings.
Output a single JSON array and nothing else: the quoted
lines when the song expresses the theme, or an empty array
when it does not:
["quoted line", "another quoted line"]