ロリポップ!AIゲートウェイが対応した判定特化モデル「Jev」を使って、音楽ファイルのジャンルやムードを判定する CLI を作りました。librosa で測った特徴を Jev に渡す 2 段構成で、精度を上げていく過程で見えてきた「Jev は渡したデータをどう読んでいるのか」を、実験結果と合わせて紹介します。
目次
はじめに
GMOペパボの黒瀧です。ロリポップ!AIゲートウェイが TypeSafe AI の判定特化モデル Jev に対応しました(お知らせ)。
Jev は「生成」ではなく「判定」に特化したモデルで、選択肢から選ぶ・段階で評価する・Yes/No を判定する、といったことを 0.1〜0.5 秒程度で返してくれます。せっかくなので触ってみようと思い、音楽ファイルからジャンルやムードを判定する CLI を作ってみました。
作る過程で「Jev は渡したデータをどう読んでいるのか」が少し見えてきたので、その実験結果も合わせて紹介します。作ったものは GitHub で公開しています。
Jev の呼び出し方
ロリポップ!AIゲートウェイの API キーがあれば、すぐに使えます。ほかのモデルで使う /v1/chat/completions ではなく、Jev 専用の /v1/systemone を使います。
リクエストには、判定の材料となる state と、聞きたいことを並べた questions を渡します。
AI_GATEWAY_BASE_URL=https://ai-gateway.lolipop.jp
curl -sS "$AI_GATEWAY_BASE_URL/v1/systemone" \
-H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev-latest",
"state": {
"inquiry": "先週注文したマグカップがまだ届きません。注文番号は12345です。急ぎで使いたいので早く対応してほしいです。"
},
"questions": {
"category": {
"type": "choice",
"instructions": "問い合わせの種類はどれか?",
"criteria": {
"shipping": "配送・到着に関する問い合わせ",
"refund": "返品・返金に関する問い合わせ",
"product": "商品仕様に関する質問"
}
},
"urgency": {
"type": "score",
"instructions": "問い合わせの緊急度は?",
"criteria": ["低い", "やや低い", "普通", "やや高い", "高い"]
},
"angry": {
"type": "noul",
"instructions": "問い合わせ者は怒っているか?"
}
}
}'questions の type は 3 種類あります。
| type | 用途 | criteria | 返ってくるもの |
|---|---|---|---|
choice | 選択肢から 1 つ選ぶ | {キー: 説明文} のオブジェクト | choice・confidence・全選択肢の probabilities |
score | 段階で評価する | 低い順に並べた配列 | 確率で重み付けした score(連続値)・probabilities |
noul | Yes/No を判定する | 不要 | 0〜1 の noul |
上のリクエストの結果は、category が shipping(確率 1.0)、urgency が 3.16(「やや高い」78%・「高い」19%)、angry が 0.49 でした。1 回のリクエストで複数の判定をまとめて聞けて、応答は 0.42 秒でした。
作ったもの: jev-music
Jev の state はテキスト(JSON)なので、音声ファイルをそのまま渡すことはできません。そこで、次の 2 段構成にしました。
mp3/wav ──librosa──▶ 特徴量(BPM, キー, 音圧, 音色…)──テキスト化──▶ Jev ──▶ ジャンル・ムード
「測定」 「判定」- 測定(テンポ・キー・音圧・音色など)は librosa に任せる。信号処理で正確な数値が出るものを、わざわざ AI に推測させる必要はありません
- 判定(ジャンル・ムード・踊れるか など)は Jev に任せる。正解が 1 つに決まらず、確率で答えるのが自然なものです
uv run jev-music song.mp3🎵 guitar_obsession-80s-radio-tune-113798.mp3
[librosa] 測定
テンポ 117.5 BPM(ビート 239 個 / 拍の明確さ 0.576 / 2・4拍子系)
キー F major(確からしさ 0.138)
長さ 120.0 秒 / 音圧 -16.3 dBFS / 抑揚 20.2 dB
音色 重心 2711 Hz / 低音比 0.444 / 高音比 0.0428 / ノイズ感 0.0342
リズム 打楽器比 0.221 / 毎秒 2.71 音
[Jev] 判定
ジャンル rock(rock 80% / pop 19% / house_techno 1%)
ムード energetic(energetic 85% / happy 13% / calm 1%)
明るさ 2.62 / 4
激しさ 2.58 / 4
踊れる 65%
作業BGM 54%
電子音中心 58%
⏱ 解析 4.58s / Jev 0.49slibrosa で測っているもの
| 特徴 | 中身 |
|---|---|
| テンポ | librosa.beat.beat_track |
| 拍の明確さ | オンセット強度の自己相関のピーク(0〜1) |
| 拍子 | 自己相関の 3 拍目と 4 拍目の強さを比べて 3 拍子系 / 2・4 拍子系を推定 |
| キー | クロマ特徴と Krumhansl のキープロファイルの相関 |
| 音圧・抑揚 | RMS の平均と、上位 5% と下位 5% の差 |
| 音色 | スペクトル重心、150Hz 未満・4kHz 超のエネルギー比、スペクトル平坦度 |
| 打楽器比 | HPSS(調波音と打楽器音の分離)でのエネルギー比 |
Jev に渡しているもの
数値だけだと多いのか少ないのかが分かりにくいので、目安の言葉を添えて state にしています。
"state": {
"audio_features": {
"tempo": "117.5 BPM(中くらい。ビート検出は倍・半分に誤ることがある)",
"pulse_clarity": "0.576(拍の感じやすさ。はっきりしている)",
"key": "F major(長調、推定の確からしさ 0.138)",
"loudness": "平均 -16.3 dBFS(音圧高い)",
"bass": "150Hz未満のエネルギー比 0.444(ベース・キックなど低音が中くらい)",
"treble": "4kHz超のエネルギー比 0.0428(シンバル・ハイハット・歪みなど高音成分が多い)",
"noisiness": "スペクトル平坦度 0.0342(ノイズ・歪み・シンセ成分が多い)",
"percussive_ratio": "打楽器成分の割合 0.221(打楽器成分中くらい)"
}
}questions には、ジャンル(17 種の choice)、ムード(7 種の choice)、明るさ・激しさ(score)、踊れるか・作業 BGM 向きか・電子音中心か(noul)の 7 つを並べています。
精度を上げる: 2/7 → 6/7
librosa には、ジャンルがはっきりしたサンプル曲(ブラームス、ドラムンベース、ワルツ、ラグタイムなど)が付属しています。この 7 曲を正解データにして、改善していきました。
最初の版は 2/7 正解。7 曲中 5 曲が house_techno(ハウス/テクノ)と判定されていました。
原因 1: どの曲でも「ビートが非常に一定」になっていた
最初はビート間隔のばらつきを「規則性」として渡していたのですが、これが全曲 0.93〜0.96 になっていました。ビート検出器は等間隔にビートを置こうとするので、ビート間隔からテンポの揺れを測っても差が出ないのです。
その結果、全曲に「非常に一定(機械的)」という言葉が付き、4 つ打ちのハウス/テクノに引っ張られていました。
オンセット強度の自己相関から「拍の明確さ」を取るように変えると、テンポを揺らして演奏するブラームスは 0.17、機械的なワルツは 0.9 と、ちゃんと差が出るようになりました。
原因 2: ジャンルの説明と特徴量の言葉がかみ合っていなかった
低音比・高音比・平坦度を追加しても 3/7 どまり。効いたのは criteria(ジャンルの説明文)の書き直し でした。
- "classical": "クラシック。オーケストラ・ピアノ、打楽器が少なくダイナミクスが大きい",
+ "classical": "クラシック。オーケストラ・ピアノ・弦楽・室内楽。ドラムもベースラインも無いので低音と打楽器成分が少ない、澄んだ楽音、録音の音圧は控えめで抑揚が大きい、3拍子のワルツも多い",
- "jazz": "ジャズ。スウィング、即興、ビートの揺らぎ",
+ "jazz": "ジャズ。ウッドベースが鳴り続けるため低音が多い一方、ドラムはブラシやシンバル中心で打楽器成分は少ない。ピアノ・管楽器、スウィング",state で使っている言葉(低音・打楽器成分・音圧・抑揚)と同じ言葉でジャンルを説明するようにしたところ、6/7 正解 になりました。
| 曲 | 改善前 | 改善後 |
|---|---|---|
| brahms(クラシック) | classical ✅ | classical 84% ✅ |
| choice(ドラムンベース) | house_techno ❌ | drum_and_bass 95% ✅ |
| nutcracker(クラシック) | lofi ❌ | classical 82% ✅ |
| pistachio(ラグタイム) | house_techno ❌ | classical 81% ✅ |
| sweetwaltz(ワルツ) | house_techno ❌ | classical 99% ✅ |
| vibeace(ジャズ寄りラウンジ) | lofi ✅ | jazz 60% ✅ |
| fishin(カントリーポップ) | house_techno ❌ | pop 79% ❌ |
残った fishin は歌もののカントリーポップで、特徴量の上ではポップスそのものです。バンジョーの音色は今の特徴量では見分けられないので、この 1 曲に合わせて調整するのはやめました。
実験: Jev は数値を読んでいるのか、言葉を見ているのか
ここまでの経緯から、「Jev は state と criteria の言葉を照らし合わせているのでは?」という疑問が湧きました。jev-music は入力を完全に制御できるので、これを確かめる実験台にしてみました。
実験 1: 数値+言葉 / 数値だけ / 言葉だけ
同じ 7 曲で、state の渡し方だけを変えました。
| state の渡し方 | 例 | 正解数 | 正解ジャンルへの確率(平均) |
|---|---|---|---|
| 数値+言葉 | 0.794(低音が非常に多い) | 6/7 | 74% |
| 数値だけ | 0.794 | 6/7 | 57% |
| 言葉だけ | 低音が非常に多い | 6/7 | 72% |
数値だけでも正解数は変わりません。 Jev は数値の大小もちゃんと判定に使えています。ただし確信度は下がり、それを押し上げているのは主に言葉のほうでした。
実験 2: 特徴を 1 つずつ動かす
基準曲(くるみ割り人形。低音比 0.087)の低音比だけを書き換えて、ジャンルの確率がどう動くかを見ました。
| 低音比 | 数値だけ: classical | jazz | 数値+言葉: classical | jazz |
|---|---|---|---|---|
| 0.1 | 72% | 2% | 84% | · |
| 0.2 | 63% | 4% | 16% | 3% |
| 0.3 | 49% | 6% | 12% | 4% |
| 0.4 | 31% | 10% | 12% | 5% |
| 0.5 | 20% | 13% | 12% | 5% |
| 0.6 | 11% | 32% | 2% | 54% |
(数値+言葉の 0.2〜0.5 は folk_acoustic が 1 位)
- 数値だけ: classical が 72 → 63 → 49 → 31% と、なめらかに下がっていく
- 数値+言葉: 言葉が「少ない → 中くらい」に切り替わる 0.2 で、84% → 16% に急落。0.2〜0.5 の間はほぼ横ばい
言葉があると、Jev は数値よりも言葉に従います。つまり、こちらが決めた言葉のしきい値が、そのまま判定の境界になります。
BPM でも面白い結果が出ました。
| BPM | 数値だけ: classical | drum_and_bass | 数値+言葉: classical | drum_and_bass |
|---|---|---|---|---|
| 135 | 51% | 12% | 83% | 3% |
| 150 | 66% | 10% | 88% | 1% |
| 165 | 43% | 49% | 82% | 7% |
| 180 | 26% | 67% | 83% | 8% |
数値だけのときは、drum_and_bass の説明文に書いた「BPM 160-180 前後」の範囲に入ったところで逆転しました。state の数値と criteria に書いた数値の範囲を照らし合わせている ようです。一方、言葉を添えると 135 以上はすべて「速い」になるため、180 でもほとんど反応しませんでした。言葉が数値の情報を隠してしまったわけです。
state 設計の指針
| やりたいこと | 渡し方 |
|---|---|
| 判定をはっきりさせたい(確信度を上げたい) | 言葉を添える。ただし境界は自分で決めることになる |
| 境界付近の値をきめ細かく扱いたい | 数値だけを渡し、criteria 側にも数値の目安を書く |
| 特定の範囲で判定を切り替えたい | criteria に数値の範囲を明記する(例: BPM 160-180) |
7 曲・基準曲 1 曲・各条件 1 回の小さな実験なので傾向として見てほしいのですが、「state と criteria を同じ言葉で書く」「言葉のしきい値は判定の境界になる」は、Jev を使うときに意識しておくとよさそうです。実験の詳細は docs/jev-probe.md にまとめています。
実際の曲でも試してみる
サンプル以外の曲でも試してみました。ファイル名に「edm」「rock」などが入っていますが、Jev に渡しているのは librosa の特徴量だけで、ファイル名は渡していません。
| EDM×ロック系のビート | 80s ラジオ風の曲 | |
|---|---|---|
| ジャンル | hiphop 25% / drum_and_bass 23% / rock 17% / edm 16% / house_techno 14% | rock 81% / pop 18% |
| genre の confidence | 0.19 | 0.79 |
| ムード | dark 74% | energetic 86% |
| 電子音中心 | 75% | 58% |
80s ラジオ風の曲は、「高音成分が多い」「ノイズ・歪み成分が多い」「音圧高い」という state が、rock の説明文とそのまま重なって rock 81% になりました。
EDM×ロックの曲は、1 位の hiphop でも 25% しかなく、電子系とロックに確率が割れました。電子音とロックが混ざった曲なので、この迷い方はむしろ正直です。こういう曲では 1 位だけでなく、確率の上位をまとめて「ジャンル候補」として見せるほうが、Jev の出力に合っていると感じました。
速度とコスト
- 応答時間: 7 つの質問をまとめて聞いても、毎回 0.4〜0.5 秒
- トークン: 1 回あたり入力約 2,270 トークン。その大半は 17 ジャンルの説明文で、state は 1 割程度
- 料金: 入力 $0.042 / 100 万トークン、出力は無料。1 回あたり約 $0.0001(2026年9月18日〜24日は無料キャンペーン)
同じ入力で 2 回呼び出しても、確率の差は 1〜2% でした。判定が安定していて、速く、安いので、大量のデータを捌く処理や、LLM を呼ぶ前の振り分けに向いていそうです。
まとめ
- Jev は音声を直接は受け取れないので、「測定」は librosa、「判定」は Jev と役割を分けるとうまくはまった
- 精度に一番効いたのは、特徴量を増やすことより、criteria を state と同じ言葉で書くこと だった
- Jev は数値も読んでいるが、言葉を添えると言葉に従う。言葉のしきい値がそのまま判定の境界になる
今後は、4 ビート・8 ビート・16 ビートといったリズムの刻みやテンポの揺れの判定、mp3 のタグ(曲名・アーティスト)をヒントとして渡す機能を試してみたいと思っています。
参考
- kurotaky/jev-music(今回作った CLI と実験スクリプト)
- JevにLLMモデルの使い分けを任せる仕組みをロリポップ!AIゲートウェイで作ってみた(Jev の別の使い方の例)
- 判定特化型AIモデル Jev が登場!(ロリポップ!AIゲートウェイのお知らせ)
ブログの著者欄
採用情報
関連記事
KEYWORD
CATEGORY
-
技術情報(616)
-
イベント(247)
-
カルチャー(61)
-
デザイン(79)
TAG
- 5G
- Active Directory
- ADB
- AI
- AI for DevOps
- AI TALK
- AI 機械学習強化学習
- AI/機械学習
- AIO
- AIエージェント
- AIコーディング
- AIコーディングエージェント
- AIセキュリティ
- AI人財
- AI政策
- AI教育
- AI時代のセキュリティ
- AI活用
- AI研究
- AI駆動
- Anthropic
- Behind the Scenes
- BIT VALLEY
- blockchain
- ChatGPT
- ChatGPT Team
- Claude Code
- Claude Team
- CLI
- cloudflare
- cloudnative
- CNDO
- CNDT
- CODE BLUE
- ConoHa
- ConoHa VPS
- ConoHa VPS MCP
- CSS
- CTF
- DBMS_CLOUD
- DEF CON
- DEF CON 34
- Designship
- developer
- DevRel
- DevSecOpsThon
- Docker
- DTF
- EDR
- Engineering Journey
- Expert
- Expert Cross
- GMO AI&ロボティクス商事
- GMO AI&ロボティクス商事
- GMO AIR
- GMO DESIGN AWARD
- GMO Developers Day
- GMO Developers Night
- GMO Flatt Security
- GMO GPUクラウド
- GMO Hacking Night
- GMO kitaQ
- GMO SONIC
- GMOアドパートナーズ
- GMOアドマーケティング
- GMOインターネット
- GMOインターネットグループ
- GMOインターネットグループ陸上部
- GMOグローバルサイン
- GMOコネクト
- GMOサイバーセキュリティ byイエラエ
- GMOサイバーセキュリティbyイエラエ
- GMOデジキッズ
- GMOヒューマノイド・ラボ
- GMOブランドセキュリティ
- GMOペイメントゲートウェイ
- GMOペパボ
- GMOメイクショップ
- GMOメディア
- GMOロボッツ
- GMO大会議
- GMO天秤AI
- Go
- GPUクラウド
- GTB
- Hack-1グランプリ
- IETF
- iOS
- IoT
- ISUCON
- Japan Drone
- JapanDrone
- Java
- Jev
- JJUG
- JSAI
- JSAI2026
- K8s
- Kaigi on Rails
- Kerberos
- Kids VALLEY
- LLM
- LLMO
- MCP
- MCP Apps
- MCP Server
- MetaMask
- MySQL
- NFT
- Nuxt
- NVIDIA
- OpenStack
- Oracle
- Oracle Autonomous Database
- OSS
- Perl
- PHP
- PHPcon
- PHPerKaigi
- PL/SQL
- Python
- QUIC
- React
- RFC
- RPA
- Ruby
- SECCON
- Selenium
- Sim-to-Real
- Spectrum Tokyo Meetup
- splunk
- SQL
- SRE
- Takumi byGMO
- Terraform
- TypeSafe AI
- TypeScript
- UI/UX
- vibe
- VLA
- VPN
- VPS
- VS Code
- WebRTC
- Webアプリケーション開発
- Webアプリ開発
- XR
- XSS
- Yoitoi Summit
- ZTNA
- アウトプット
- アカデミア
- アドベントカレンダー
- イベントレポート
- インターンシップ
- インハウス
- インフラ
- エキスパート制度
- エキスパート座談会
- エンジニア採用
- エンジニア文化
- お名前.com
- カスタマーサポート
- クラウド
- クリエイターインタビュー
- クリエイティブ
- コーディングエージェント
- コンテナ
- コンピュータビジョン
- サイバーセキュリティ
- サイバー攻撃
- サマーインターン
- スクラム
- スパム対策
- スペシャリスト
- セキュリティ
- セキュリティカンファレンス
- セキュリティ人材
- センシング
- ソフトウェアサプライチェーン
- ソフトウェア開発
- チームビルディング
- データサイエンティスト
- データベース
- デザイン
- デプロイ
- テレイグジスタンス
- ネットのセキュリティもGMO
- ハーネスエンジニアリング
- バイブコーディング
- バックエンド
- ヒューマノイド
- ヒューマノイドロボット
- フィジカルAI
- フルスタック開発
- プログラミング教育
- プロダクト開発
- ブロックチェーン
- フロントエンド
- プロンプトインジェクション
- ペアリング暗号
- ペネトレーションテスト
- ホスティング
- ホワイトハッカー
- ものづくり
- ゆめみらいワーク
- リモートワーク
- レッドチーム
- レンタルサーバー
- ロボット
- ロボット導入
- ロボット政策
- ロボット社会実装
- ロボット警備
- ロボティクス
- ロリポップ!
- ロリポップ!デプロイナウ
- ワークフロー
- 世界モデル
- 京大ミートアップ
- 京都大学
- 京都未踏
- 人型ロボット
- 人工知能
- 人工知能学会
- 個人情報検出
- 光学
- 分類
- 四足歩行ロボット
- 国際ロボット展
- 国際標準化
- 基礎
- 多拠点開発
- 大規模言語モデル
- 大阪公立大学
- 学習データ
- 宇宙セキュリティ
- 宮崎オフィス
- 強化学習
- 応用
- 技育プロジェクト
- 技術イベント
- 技術ブログ
- 技術同人誌
- 技術広報
- 技術書典
- 拡張知能
- 新卒
- 新卒研修
- 新規サービス開発
- 映像
- 映像クリエイター
- 映像制作
- 暗号
- 未踏
- 業務効率化
- 機械学習
- 次世代育成
- 決済
- 生成AI
- 産学連携
- 産官学連携
- 研究開発
- 社会実装
- 社内コミュニティ
- 組織横断
- 耐量子暗号
- 脆弱性診断
- 自動化
- 自律実行
- 若手人材育成
- 責任あるイノベーション
- 通信技術
- 開発組織
- 開発者
PICKUP
-
判定特化AI「Jev」に音楽のジャンルを判定させてみた ─ librosa で測って Jev で決める
技術情報
-
【Expert Cross #5・後編】研究を組織の力に GMOインターネットグループ・真次彰平が描く、領域を越えた協働のかたち
技術情報
-
【Expert Cross #5・前編】研究の成果をブランディングへ接続 真次彰平が臨む、「研究するGMOインターネットグループ」への展望
技術情報
-
【エキスパート座談会 #3】AIエージェント、何を作ってどう活用してる?:それぞれの制約の中で「手綱を握る」仕事へ
技術情報
-
【イベントレポート後編】第4回 GMO大会議🍁秋|「GMOフィジカルAI Awards 2026」受賞者発表と社会実装への挑戦
イベント
-
【イベントレポート前編】第4回 GMO大会議🍁秋|日本の勝ち筋はフィジカルAIにあり!産官学のトップランナーが描く成長戦略
イベント