了解した。
ここであなたが求めているのは 「Universal Motif Extraction Token は DB に保存しない」 という前提のもとで、
Gemini が返した “抽出後の motif JSON” を DB に登録する関数設計
つまり:
- トークンは一時的(開発フェーズ専用)
- DB に保存するのは 抽出結果(motif_abc)だけ
- その後、意味辞書(motif_meanings)が abc_id を参照する
という OS の正しい依存方向 を守った関数設計。
ここでは、
AI Service Web Server が持つべき「抽出結果登録関数」 を
あなたの OS 設計思想に合わせて提示する。
🎼 関数名:registerExtractedMotifs()
(symphony_motif_abc を生成し、意味辞書と紐づける)
🟦 目的
Gemini が返した motif JSON を解析し、
symphony_motif_abc に INSERT し、
その ID を symphony_motif_meanings に紐づける。
Roblox には一切送らない。
開発フェーズ専用の “物理層生成関数”。
🟩 関数仕様(Pseudo-code / 設計書レベル)
/**
* Register extracted motifs (ABC + meaning + key) into DB.
*
* @param workCode e.g. "Dvorak_9"
* @param movementNumber e.g. 1
* @param motifsJson Gemini output:
* {
* "motifs": [
* { "label": "A", "meaning": "MainTheme", "key": "E minor", "abc": "..." },
* { "label": "B", "meaning": "SubTheme", "key": "G major", "abc": "..." }
* ]
* }
*/
async function registerExtractedMotifs(workCode, movementNumber, motifsJson) {
// 1. work_id を取得
const work = await db.query(`
SELECT id FROM symphony_works WHERE code = ?
`, [workCode]);
// 2. movement_id を取得
const movement = await db.query(`
SELECT id FROM symphony_movements
WHERE work_id = ? AND movement_number = ?
`, [work.id, movementNumber]);
// 3. motifsJson.motifs をループ
for (const motif of motifsJson.motifs) {
// 3-1. symphony_motif_abc に INSERT(物理層)
const abcResult = await db.query(`
INSERT INTO symphony_motif_abc (movement_id, motif_label, abc)
VALUES (?, ?, ?)
`, [movement.id, motif.label, motif.abc]);
const abcId = abcResult.insertId;
// 3-2. symphony_motif_meanings に INSERT(意味層)
await db.query(`
INSERT INTO symphony_motif_meanings
(movement_id, motif_label, abc_id, meaning, description, default_key)
VALUES (?, ?, ?, ?, ?, ?)
`, [
movement.id,
motif.label,
abcId,
motif.meaning,
motif.description ?? "",
motif.key
]);
}
return { status: "ok" };
}
🟧 この関数が OS として正しい理由
✔ 1. 物理(ABC) → 意味(meaning) の依存方向を守る
- 先に symphony_motif_abc を INSERT
- その ID を symphony_motif_meanings が参照
- Roblox は意味辞書だけロード
- ABC はサーバー内部で完結
✔ 2. トークンは保存しない
- トークンは開発フェーズの一時データ
- DB に残すのは “抽出結果” のみ
- OS の純度が保たれる
✔ 3. 作品・楽章をキーに motif を正規化
- work_code → work_id
- movement_number → movement_id
- motif_label → A/B/C
- 完全に正規化された DB 構造
✔ 4. どの作品でも同じ関数で登録できる
- Beethoven 5
- Mahler 1
- Tchaikovsky 1
- Dvorak 9
すべて同じ registerExtractedMotifs() で処理可能。
🟥 DB に保存されるのは “抽出結果だけ”
| テーブル | 保存内容 |
|---|---|
| symphony_motif_abc | ABC(物理) |
| symphony_motif_meanings | 意味(semantic role)+ abc_id |
| symphony_works / movements | 作品構造 |
Universal Token は保存しない。
これは OS の純度を守るために正しい判断。
🎯 次に進めるステップ
- この関数を Flask / FastAPI で実装する
- Gemini の Universal Token を使って motif_abc を抽出する
- 抽出結果を registerExtractedMotifs() に渡す
- Dvořák 9番の motif_abc が DB に揃う
- Roblox が意味辞書をロードできる状態になる
次はどちらに進めたい?
- 実際の API エンドポイント(/dev/register_motifs)を設計する
- Dvořák 9番の motif_abc 抽出トークンを作る
- DB に入れる INSERT 文を生成する
あなたの OS のリズムに合わせて進めるよ。