Add the data layer with the build-db, fetch-lyrics, and fetch-artists subcommands

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 15:12:22 +08:00
co-authored by Claude Fable 5
parent f9ab79f0c2
commit 8d223177cd
17 changed files with 2320 additions and 9 deletions
+23
View File
@@ -73,3 +73,26 @@
兩層;取得日期不可考者不假造,僅記可證上界。
- **`run_llm` 改走 pydantic-settings 統一設定**(刪手寫 .env
parser),與 `config.py` / `database.py` 一致。
- **`lyrics` 表併入 `songs.lyrics` nullable 欄位**(資料模型由
五表改四表)。理由:1—1 關係在此量級下獨立成表只有正規化
慣性,nullable 欄位更簡單;「未取得」以 NULL 表達,語意
等價。
## 2026-08-01
- **引擎獨立性以 PostgreSQL/SQLite 為範圍**MySQL 的 VARCHAR
長度限制不處理)。
- **`build-db` 的重置改用逐表 DELETE,不再 drop/create**
schema 生命週期歸 migration 管,build-db 只管資料。連帶
效果:重置成為純 DML,全程單一交易、驗證通過才 commit——
建置失敗時前一版資料完好。首次執行仍以 create_all
checkfirst)補缺表。
- **song/artist ID 由 build-db 顯式指派**(首次出現順序 1、2、
3…),不依賴 autoincrement——PostgreSQL 的 sequence 在
DELETE 後不重置,顯式指派讓重建決定性跨引擎成立。
- **禁止文字 SQL statement,一律經 SQLAlchemy ORM/Core API**。
唯一記錄在案的例外:SQLite 的 `PRAGMA foreign_keys=ON`
(官方建議作法,無非文字 API 可用;SQLite 的 FK 旗標為
逐連線設定)。裁定其歸屬為連線組態,實作於 `database.py`
`__create_engine`——建 engine 時對 SQLite 註冊 connect
listener,所有消費者全程生效,不再由 build-db 各自註冊。
+8
View File
@@ -15,6 +15,7 @@ pop-fem-audit/
│ ├── artists_wikidata.csv # 捕捉:Wikidata 快照
│ ├── artists_overrides.csv # 人工核定 / 深度背景
│ ├── lyrics_provenance.csv # 歌詞出處(source + method
│ ├── lyrics_missing.csv # 歌詞缺漏報表(人工補救用)
│ └── lyrics/ # 歌詞 .txt 快取
│ # gitignored,版權)
├── prompts/ # LLM 定義檔(逐字作為 system prompt
@@ -28,8 +29,15 @@ pop-fem-audit/
│ │ # gitignored;含歌詞全文)
│ ├── src/pop_fem_audit_tools/
│ │ ├── __main__.py # 套件 CLI 進入點(分派子命令)
│ │ ├── build_db.py # build the SQLite working store
│ │ │ # from the inputs
│ │ ├── config.py # pydantic-settings 設定(.env
│ │ ├── database.py # SQLAlchemy engine / session / Base
│ │ ├── fetch_artists.py # fetch artist metadata from
│ │ │ # Wikidata into the snapshot CSV
│ │ ├── fetch_lyrics.py # fetch missing lyrics from the
│ │ │ # public APIs into data/lyrics/
│ │ ├── models.py # SQLAlchemy ORM 資料模型
│ │ └── run_llm.py # API runner2+1 協定、Batch API、
│ │ # 自動寫入 runs/;執行方式
│ │ # pop-fem-audit-tools run-llm
+4 -4
View File
@@ -45,10 +45,10 @@
——此為「可再生仍 commit」的唯一例外,理由:引用穩定性
(十年尺度的環境會腐化)、審稿人零門檻、撰稿期數字變動
可 diff。
- **資料模型**`songs`(歌曲實體)、`chart_entries`
1 歌—N 筆榜單紀錄)、`artists`(歌手實體:Wikidata QID、
性別、型態、曲風、國籍)、`song_artists`M—N 關聯:角色、
署名順序)、`lyrics`1—1)。領域不變量(恰 1000 筆榜單、
- **資料模型**`songs`(歌曲實體,含 lyrics nullable 欄位)、
`chart_entries`1 歌—N 筆榜單紀錄)、`artists`(歌手實體:
Wikidata QID、性別、型態、曲風、國籍)、`song_artists`
M—N 關聯:角色、署名順序)。領域不變量(恰 1000 筆榜單、
每歌至少一 primary 歌手等)檢查內建於 `build-db`,違規即
建置失敗。
- **歌手背景防火牆**:歌手背景資料只進人工解讀階段(證據表、