🎵
🎵Supabase×OpenAIで楽曲データをベクトル化するノウハウ
はじめに
楽曲データベースから「楽曲の特徴」をベクトル(特徴量)化し、類似検索やレコメンドに応用する実装例を解説します。SupabaseとOpenAIを活用し、実際に動くPythonコードを分かりやすく説明します。
全体の仕組み
このスクリプトは、
- Supabaseから楽曲データ(タイトル、アーティスト、テーマなど)を取得し
- OpenAIの埋め込みAPIを使ってAIベクトル化
- ベクトルを正規化し、データベースに保存
という流れを自動で処理します。
コードのポイント解説
必要なライブラリと環境設定
Supabase(PostgreSQLベースのクラウドDB)、OpenAI API、dotenv(環境変数管理)、numpy(ベクトル計算)を使います。
import os
import numpy as np
from openai import OpenAI
from dotenv import load_dotenv
from supabase import create_client, Client
load_dotenv()
SUPABASE_URL = os.getenv("SUPABASE_URL")
SUPABASE_SERVICE_KEY = os.getenv("SUPABASE_SERVICE_KEY")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
supabase: Client = create_client(SUPABASE_URL, SUPABASE_SERVICE_KEY)
openai_client = OpenAI(api_key=OPENAI_API_KEY)
embedding_model = "text-embedding-3-small"
楽曲情報を「埋め込み向けテキスト」に変換
リスト型情報(テーマ、参加アーティスト)は.join()でカンマ区切りの文字列に変換。各項目には「title:」「artist:」などラベルを明示するので、区切りの混乱が起きにくい設計です。
def generate_embedding_text(track):
summary = track.get('lyric_summary') or ""
themes_list = track.get('themes') or []
featured_list = track.get('featured_artists') or []
themes_str = ', '.join(themes_list)
featured_str = ', '.join(featured_list)
return (
f"title: {track.get('title', '')}, "
f"artist: {track.get('artist', '')}, "
f"featured: {featured_str}, "
f"year: {track.get('year', '')}, "
f"themes: {themes_str}, "
f"summary: {summary}"
)
メイン処理
楽曲テーブルから全件取得して、1件ずつ
- 入力テキスト生成
- ベクトル化API呼び出し
- ベクトル正規化
- DBの
ctx_vecカラムに更新
を繰り返します。エラー時も確認しやすい出力付きです。
def main():
print("データベースの全楽曲ベクトルを更新します...")
select_columns = 'id, title, artist, year, themes, lyric_summary, featured_artists'
response = supabase.table('hiphop_tracks').select(select_columns).execute()
if not response.data:
print(" - データベースに楽曲データが見つかりません。")
return
all_tracks = response.data
print(f" - {len(all_tracks)}件の楽曲が見つかりました。")
for track in all_tracks:
track_id = track['id']
track_title = track['title']
print(f"\n - ID: {track_id} ({track_title}) のベクトルを更新中...")
input_text = generate_embedding_text(track)
print(f" - AIへの入力テキスト: 「{input_text[:100]}...」")
embedding_response = openai_client.embeddings.create(input=input_text, model=embedding_model)
vector = np.array(embedding_response.data.embedding)
normalized_vector = (vector / np.linalg.norm(vector)).tolist()
update_response = supabase.table('hiphop_tracks').update({'ctx_vec': normalized_vector}).eq('id', track_id).execute()
if len(update_response.data) > 0:
print(f" - ID: {track_id} のベクトルを正常に更新しました。")
else:
print(f" - ID: {track_id} の更新に失敗した可能性があります。")
print("\nすべての更新処理が完了しました。")
まとめ・応用例
ベクトルがDBに保存されることで、
- 類似楽曲検索(ユークリッド距離・コサイン類似度など)
- レコメンド
- 構造化データ分析
が簡単にできるようになります。
特にAI×DBを使った楽曲・文化データのアーカイブ運用をしたい人には、ベース実装として参考になるはずです。コードを自分のDBやモデル構成に合わせて拡張してみてください
Discussion