-- Views
May 01, 26
スライド概要
【講演内容】
今年2月に社内のAIコンペがあり、参加作品として「先生が学生を指導したときの会話音声から学生指導記録を生成する」というツールを、
OCI Speech / OCI Generative AIといったサービスと連携させて開発しました。
本セッションでは、MySQL HeatWave GenAIの機能の一つであるNL2SQL機能を実際に組み込んでみてのポイントや感想などをご紹介します。
1. 検証記録アプリと構成概要
- 学生指導の生成・検索アプリ
- Autonomous Database(SELECT AI)からHeatWaveへの移行検証
2. NL2SQL機能の概要と利用環境
- 自然言語からSQL生成・の仕組み
- 利用したモデル・HeatWave構成
3.実装で解決した課題
- SQL生成精度の低いさと処理時間の課題
- 日本語検索時のエラー(文字コード問題など)
4. 改善アプローチとポイント
- プロンプト設計(検索ルールの先出し・Few-shot例)
- モデル評価による精度・速度改善
5. 検証結果と今後の展望
- NL2SQLの現状評価と実用性
- AI活用における設計・チューニングの重要性
【発表者】
株式会社パソナデータ&デザインデータテクノロジー
本部 データベース部
神田 智大氏
【イベント情報】
HeatWavejp Meetup #18
https://heatwavejp.connpass.com/event/387800/
HeatWavejpは、MySQL HeatWave の良さを知っていただき、参加者同士でノウハウやナレッジを共有できるユーザーコミュニティです。参加者同士のつながりを深めるため、以下の活動を行ってまいります。 COMMUNICATION *Slackやconnpassを活用したユーザー同士のコミュニケーションの場の提供 EVENT *オンライン/オフラインでのMeetupセミナーや勉強会の開催(隔月程度) SHARING *製品情報や最新アップデート、リリース情報の共有 INTERACT *参加者のコミュニティ・ネットワークやユーザー同士の交流を促進
AI活用による 教育機関の学生指導記録ツール を開発してみた ~NL2SQL機能活用におけるポイントと感想~ 株式会社パソナデータ&デザイン データテクノロジー本部 データベース部 HeatWaveリードエンジニア 神田智大
自己紹介 • 名前:神田 智大(かんだ ともひろ) • 所属:株式会社パソナデータ&デザイン データテクノロジー本部 データベース部 MySQL HeatWaveリードエンジニア • 趣味:奥さんと着物で出掛けること • 年内の目標:HeatWavejpのイベントに着物で登壇
検証対象:学生指導記録の生成・検索アプリ 今回の焦点 MySQL HeatWave のNL2SQL機能 先生 学生
やりたかったこと:構成の移行 • 社内コンペ時はAutonomous AI Database (SELECT AI)を採用 • 今回は MySQL HeatWave(NL2SQL)への移行をやってみたかった 「機能としては同じだし、サクッと移行できるだろう」 という甘い見通し
本日のLTの結論
移行したMySQL HeatWaveの構成 • 今回検証に使用したMySQL HeatWave • リージョン:大阪 • バージョン:9.6.1 • シェイプ:MySQL2 • ECUP:2 • メモリー:16GB • HeatWaveクラスタ:有効 • ノード:1 • メモリー:512 GB • NL2SQL機能で使用するLLMモデル • meta.llama-3.3-70b-instruct (大阪リージョンでのみ使用可能)
前提:基本的なベストプラクティスは抑えている • NL2SQLで推奨されるDB設計はすべて実施済み 例:会話音声情報テーブル ①テーブル・カラムの適切な命名 CREATE TABLE `VOICE` ( `VOICE_ID` int NOT NULL AUTO_INCREMENT COMMENT '音声ID', `USER_ID` int NOT NULL COMMENT 'ユーザID', ②カラムへのコメント付与 `VOICE_DATE` date NOT NULL COMMENT '日付', `VOICE_TITLE` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'タイトル', `VOICE_STR` longtext COLLATE utf8mb4_unicode_ci COMMENT '会話文字列', `VOICE_SUMMARY` longtext COLLATE utf8mb4_unicode_ci COMMENT '要約', PRIMARY KEY (`VOICE_ID`), ③外部キーによるリレーション設定 KEY `IX_VOICE_USER_ID` (`USER_ID`), CONSTRAINT `FK_VOICE_USER_ID` FOREIGN KEY (`USER_ID`) REFERENCES `USERS` (`USER_ID`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='音声情報' SECONDARY_ENGINE=RAPID ④テーブルへのコメント付与
直面した現実(問題発生) • meta.llama-3.3-70b-instruct (高性能モデル)を使用 ①検索ルール無しでは生成SQLの精度が低い ( 間違った検索条件/無駄な検索条件) 例:織田信長にカウンセラーを勧めた会話を検索して - 間違った検索条件 WHERE USER.NAME=‘織田信長’ - 不要なキーワードでの検索条件 WHERE VOICE_SUMMARY LIKE ‘%勧めた%’ ②検索ルールを追加していくと SQLの生成に異常に時間がかかる 例: [input] 織田信長にカウンセラーを勧めた会話を検索して [検索ルール] - テーブルの結合条件の指定 - 不要キーワードの指定 : SQL生成に60秒ほど時間がかかり、 SQL生成に失敗する 結果:ユーザー待ち時間が長く、検索に失敗する NL2SQL機能は実用的ではない状況
改善策②:プロンプトの最適化 プロンプト [Block 1] 検索ルール – 先だしの鉄則 [Block 2] 凡例(Few-shot Example) - ★最も効果的 [Block 3] 質問(input) - 最後に配置 ポイント① 検索ルール(業務ロジック)は先出しで、 最初に読み込ませる 効果:意図したSQLに収束しやすい ポイント② 質問に対する検索条件(WHERE句)の 凡例を記載する 効果:SQL生成速度、精度が改善される
実際に使ったプロンプト(抜粋) プロンプト(抜粋) [Block 1] 検索ルール [Search Rules] If the keyword is a person's name, do not use the `USER_NAME` field in the `guidio`.`USERS` table for the search. [Block 2] 凡例 Example: “神田先生と田中花子との面談内容を探して” → (VOICE_TITLE LIKE ‘%神田先生%’ OR VOICE_SUMMARY LIKE ‘%神田先生%’) AND (VOICE_TITLE LIKE '%田中花子%' OR VOICE_SUMMARY LIKE '%田中花子%’) [input] 織田信長にカウンセラーの話した会話を探して。 [Block 3] 質問
改善施策②:プロンプト改善のインパクト • 質問より前に「検索ルールを追加」することで生成SQLの精度が向上 • 凡例を追加することで、完璧なSQLを生成しSQL生成速度は1/7秒にまで改善 (ただし、それでも遅い…) 例:織田信長にカウンセラーを勧めた会話を検索して(※詳細な検索ルールあり) 凡例なしプロンプト 凡例ありプロンプト ※meta.llama-3.3-70b-instruct (高性能モデル) ※meta.llama-3.3-70b-instruct (高性能モデル) 生成時間:50~60秒 精度:SQL生成できず 生成時間:約7秒 精度:完璧なSQLを生成 ※後述のバグ?に関連あり※ (SQL生成は出来ているが、 内部処理でエラーになっている模様)
【考察】なぜ順序で精度が変わるのか? LLMは「前から順に」文脈(コンテキスト)を構築する 【検索ルールの先だし】 【検索ルールの後出し】 検索ルール 質問 質問 検索ルール 事前に制約がある状態で自然言語を解釈する 結果、精度が高くなる ・一旦解釈した内容を、後からルールで 修正しようとして混乱する ・長文になるほど後半の影響が弱まる
【考察】なぜ「凡例」が効くのか? Few-shot的な振る舞い:「ゼロからの推論」→ 「パターンマッチ」へ切り替え プロンプトの抜粋 Example: “神田先生と田中花子との面談内容を探して” → (VOICE_TITLE LIKE ‘%神田先生%’ OR VOICE_SUMMARY LIKE ‘%神田先生%’) AND (VOICE_TITLE LIKE '%田中花子%' OR VOICE_SUMMARY LIKE '%田中花子%’) Few-shot:指示文(プロンプト)と少数の具体例(インプットと期待する回答のペア) を入力することで、モデルが文脈を理解し、未知のタスクの出力精度を向上させる手法
補足:モデルの違い • 高性能モデルを使用することでSQL生成速度は3倍程度の差が出る (ただし、それでも遅い…) 例:織田信長にカウンセラーを勧めた会話を検索して llama3.1-8b-instruct-v1(軽量モデル) meta.llama-3.3-70b-instruct (高性能モデル) 生成時間:20~25秒 精度:不要な検索条件あり 生成時間:約7秒 精度:完璧なSQLを生成 - 不要なキーワードでの検索条件 WHERE VOICE_SUMMARY LIKE ‘%勧めた%’ 現時点ではNL2SQL機能を使うなら llama-3.3モデルが精度/速度ともにベスト ※凡例なしだとSQL生成失敗する挙動あり※
遭遇したNL2SQLの“失敗判定”の挙動
MySQL SQL > CALL sys.NL_SQL(@input, @output, JSON_OBJECT('schemas',JSON_ARRAY('guidio'),'model_id','meta.llama3.3-70b-instruct’));
+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| nl_sql_info
|
+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| {"level": 1, "stage": "validated_sql", "message": "Generated SQL statement: SELECT `T1`.* FROM .... WHERE ..."} |
+-----------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (7.7862 sec)
SQL生成で正しいSQL生成できている
(手動実行するとキチンと動作するし結果セットが返る)
+------------------------------------------------------------------------------------------------------------------+
| nl_sql_info
|
+------------------------------------------------------------------------------------------------------------------+
| {"level": 1, "stage": "execution", "message": "Executing generated SQL statement..."} |
+------------------------------------------------------------------------------------------------------------------+
1 row in set (7.7862 sec)
生成したSQLの実行結果が Emptyになる
Empty set (7.7862 sec)
ERROR: 1300 (HY000): Invalid latin1 character string: 'EXPLAI...'
Invalid latin1 character string が出力される
遭遇したNL2SQLの“失敗判定”の挙動
• output 変数 にアクセスすると「I was not able to generate a valid SQL
statement.」メッセージ
• 有効なSQLを生成できているはずなのに、
「有効なSQLを生成できなかった」としてSQLが出力されない(取得できない)
MySQL SQL > select @output;
+-----------------------------------------------------------------------------------------------------------------+
| @output
|
+-----------------------------------------------------------------------------------------------------------------+
{"tables": ["guidio.ORGANIZATION", "guidio.USERS", "guidio.VOICE"],
"schemas": ["guidio"],
"model_id": "meta.llama-3.3-70b-instruct",
"sql_query": "I was not able to generate a valid SQL statement.",
"is_sql_valid": 0}
+-----------------------------------------------------------------------------------------------------------------+
1 row in set (0.0008 sec)
I was not able to generate a valid SQL statement.
(有効なSQLを生成できなかったメッセージ)
文字コード依存の問題? • LIKE検索のキーワードに「日本語を含む」と発生する 日本語キーワードでLIKE検索するSQL WHERE VOICE_SUMMARY LIKE ‘%織田信長%’ 英語キーワードでLIKE検索するSQL WHERE VOICE_SUMMARY LIKE ‘%Oda Nobunaga%’ Invalid latin1 character string エラー発生 SQL生成・実行ともに成功 • 文字セット関連のパラメータやDB / テーブル定義は全て utf8mb4 で統一して いるのに latin1 キャラクターセットでエラー…? ERROR: 1300 (HY000): Invalid latin1 character string: 'EXPLAI...' メッセージが途切れているが「EXPLAIN」、つまり生成SQLの検証時に文字コードがずれている?
暫定対策:凡例でエラーが回避される • 凡例(Example)をプロンプトに追加すると、Invalid latin1 character string エラーは発生しなくなる • output変数に生成されたSQLが表示されるようになる • 検証フェーズでエラーがなくなる模様 • しかし、NL2SQL内の生成SQLの実行結果はEmpty Setのまま… • NL2SQL内の実行処理内で別の問題が発生している可能性がある…? 凡例なしプロンプト (SQL生成に失敗判定) 凡例ありプロンプト (SQL生成に成功判定) SQL生成(OK) SQL生成(OK) SQLの検証(NG) SQLの検証(OK) SQLの実行(Empty) SQLの実行(Empty)
まとめ • NL2SQLの複雑な検索ルールにおける日本語検索はまだ厳しい • 最低限、高性能モデル(meta.llama-3.3-70b-instruct)の選択が必須 • 現状は外部のLLMの使用が現実的…です • プロンプト設計が命。特に凡例を追加は必須! • 生成SQLの精度、生成速度が向上する • 日本語キーワード検索の謎の不具合(文字セットエラー)の暫定対策になる • SQL生成速度さえ解決できれば十分に使用できると思います!