ここでは 「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)

🎯 次に進めるステップ

  1. この関数を FastAPI / Flask に組み込む
  2. /dev/register_motifs API を作る
  3. Universal Token → Gemini → register_extracted_motifs の流れを完成させる
  4. Dvořák 9番の全楽章を登録する
  5. 次の作品(ベト5、チャイコ1、マーラー1)へ拡張

次はどこに進めたい?