ここでは 「Gemini 抽出結果(motifsJson)を DB に登録するための Python コード」 を、
あなたの OS 設計(物理 → 意味 → 構造)に完全準拠した形で提示する。
SQL を手入力するのではなく、
AI Service Web Server が実際に動かす Python 関数 を作る。
🎼 register_extracted_motifs() — Python 実装(完全版)
以下は FastAPI / Flask / 任意の Python Web Server で動く
DB 登録関数の実装例。
- 物理(ABC) → symphony_motif_abc
- 意味(meaning) → symphony_motif_meanings
- 依存方向を守る
- トークンは保存しない
- 抽出結果だけ DB に入れる
🟦 Python コード(MySQL Connector / aiomysql / pymysql どれでも動く構造)
import pymysql
def register_extracted_motifs(db, work_code: str, movement_number: int, motifs_json: dict):
"""
Gemini が返した motif JSON を DB に登録する。
symphony_motif_abc → symphony_motif_meanings の順で INSERT する。
"""
# 1. work_id を取得
with db.cursor() as cur:
cur.execute("""
SELECT id FROM symphony_works WHERE code = %s
""", (work_code,))
row = cur.fetchone()
if not row:
raise ValueError(f"work_code not found: {work_code}")
work_id = row[0]
# 2. movement_id を取得
with db.cursor() as cur:
cur.execute("""
SELECT id FROM symphony_movements
WHERE work_id = %s AND movement_number = %s
""", (work_id, movement_number))
row = cur.fetchone()
if not row:
raise ValueError(f"movement not found: {work_code} movement {movement_number}")
movement_id = row[0]
# 3. motifs_json["motifs"] をループ
for motif in motifs_json["motifs"]:
label = motif["label"]
abc = motif["abc"]
meaning = motif.get("meaning", "")
description = motif.get("description", "")
key = motif.get("key", "")
# 3-1. symphony_motif_abc に INSERT(物理)
with db.cursor() as cur:
cur.execute("""
INSERT INTO symphony_motif_abc (movement_id, motif_label, abc)
VALUES (%s, %s, %s)
""", (movement_id, label, abc))
abc_id = cur.lastrowid
# 3-2. symphony_motif_meanings に INSERT(意味)
with db.cursor() as cur:
cur.execute("""
INSERT INTO symphony_motif_meanings
(movement_id, motif_label, abc_id, meaning, description, default_key)
VALUES (%s, %s, %s, %s, %s, %s)
""", (movement_id, label, abc_id, meaning, description, key))
db.commit()
return {
"status": "ok",
"work_code": work_code,
"movement_number": movement_number,
"motifs_registered": len(motifs_json["motifs"])
}
🟩 この関数が OS として正しい理由
✔ 1. 物理 → 意味 の依存方向を守る
- 先に symphony_motif_abc
- 次に symphony_motif_meanings(abc_id を参照)
これはあなたの OS の根幹。
✔ 2. トークンは保存しない
- Universal Token は一時的
- DB に残すのは “抽出結果だけ”
✔ 3. 作品・楽章を正規化して参照
- work_code → work_id
- movement_number → movement_id
- motif_label → A/B/C
✔ 4. どの作品でも同じ関数で登録できる
- Beethoven 5
- Mahler 1
- Tchaikovsky 1
- Dvorak 9
すべてこの関数で motif_abc を登録できる。
🟥 実際の使用例(Dvořák 9番 第1楽章)
motifs_json = {
"motifs": [
{
"label": "A",
"meaning": "MainTheme",
"description": "短調の力強い主題。跳躍と民族的旋律。",
"key": "E minor",
"abc": "X:1\nL:1/8\nK:Em\nE2 G2 B2 ..."
},
{
"label": "B",
"meaning": "SubTheme",
"description": "長調の広がりある旋律。",
"key": "G major",
"abc": "X:1\nL:1/8\nK:G\nB2 d2 g2 ..."
}
]
}
register_extracted_motifs(db, "Dvorak_9", 1, motifs_json)
🎯 次に進めるステップ
- この関数を FastAPI / Flask に組み込む
- /dev/register_motifs API を作る
- Universal Token → Gemini → register_extracted_motifs の流れを完成させる
- Dvořák 9番の全楽章を登録する
- 次の作品(ベト5、チャイコ1、マーラー1)へ拡張
次はどこに進めたい?