はじめに
先日Select AI(NL2SQL)で使用可能な新機能であるSelect AI Feedbackがリリースされたので試してみました。
Feedback機能を使うと、Select AIを使用して生成されたSQLクエリ・結果セットに対して、フィードバックを与えることが出来ます。
例えば、期待していたSQLクエリが生成されなかった場合に、どのようなクエリにしてほしいか伝えることで、生成されたSQLクエリをアップデートし、次回以降問い合わせをするときに反映されます。
期待していたSQLクエリが生成された場合にも、ポジティブなフィードバックを行うことによって、正しいSQLクエリが生成されたことをLLMに伝えることが出来る為、精度向上につながります。
システムの開発者がフィードバックを行うだけでなく、適切なユーザー・インターフェース作成することで、エンドユーザーがフィードバックを提供することもできるので、時間の経過とともに、より回答の精度を向上させることが出来ます。
Feedback機能の利点
精度の向上:
期待していたSQLクエリが生成されなかった際に、自然言語でフィードバックを送信する事が出来ます。正しいクエリを生成するための考え方や、ビジネス定義を提供することが出来るため、よりパーソナライズされ、コンテキストに応じて正確なクエリを作成することが出来るようになります。
継続的な学習:
送信したフィードバックは、セッションが変わっても保持されるため、フィードバックを将来のクエリ生成のヒントとして使用することができます。
Select AI Feedbackを試してみる
以下の表を使ってFeedback機能を試してみたいと思います。
環境は、111: SELECT AIを試してみようの環境設定まで実施してある状態です。
HIGHSCHOOLS表:
| ID | SCHOOL_NAME | TOTAL_STUDENTS | SEATS | APPLICANTS | … | LANGUAGE_CLASSES |
|---|---|---|---|---|---|---|
| 1 | メトロポリタン・ディプロマ・プラス高校 | 217 | 25 | 7 | … | スペイン語 |
| 2 | 金融技術研究所 | 684 | 23 | 242 | … | スペイン語 |
| 3 | ブルックリンスタジオ中等学校 | 942 | 28 | 215 | … | アメリカ手話、イタリア語、スペイン語 |
| … | … | … | … | … | … | … |
| 427 | オーガスト・マーティン高校 | 334 | 167 | 180 | … | スペイン語 |
1.HIGHSCHOOLS表に対して、「倍率が高い高校10校」を問い合わせてみます。
-- 入力
select ai showsql 倍率が高い高校10校;
-- 出力
SELECT
"HIGHSCHOOLS".*,
ROWNUM AS "row_num"
FROM
(SELECT
"ADMIN"."HIGHSCHOOLS".*
FROM "ADMIN"."HIGHSCHOOLS"
ORDER BY "APPLICANTS" / "SEATS" DESC) "HIGHSCHOOLS"
WHERE ROWNUM <= 10
APPLICANTS(出願者数)をSEATS(席数・募集人数)で割って算出しています。
生成されたSQLクエリを実行すると、APPLICANTS、SEATSがNULLの高校が表示されてしまっています。
2.倍率を計算するときに、APPLICANTS、SEATSがNULLの高校を表示しないようにフィードバックをしてみます。
-- 入力
select ai feedback for query "select ai runsql 倍率が高い高校10校", 倍率を計算するときにnull値がある場合、その高校は表示しないで;
-- 出力
Based on your feedback, the SQL query for prompt "倍率が高い高校10校" is successfully refined. The refined SQL query as following:
SELECT
"HIGHSCHOOLS".*,
ROWNUM AS "row_num"
FROM
(SELECT "ADMIN"."HIGHSCHOOLS".*
FROM "ADMIN"."HIGHSCHOOLS"
WHERE "APPLICANTS" IS NOT NULL AND "SEATS" IS NOT NULL AND "SEATS" != 0
ORDER BY "APPLICANTS" / "SEATS" DESC) "HIGHSCHOOLS"
WHERE ROWNUM <= 10
フィードバックを基に、「倍率が高い高校10校」と問い合わせた時に生成されるSQLクエリがアップデートされました。
↑で使用したSelect AI Feedback <自然言語でのフィードバック>;の場合は、自然言語でのフィードバックを基に、LLMが再度クエリを生成し直します。
後ほど紹介するDBMS_CLOUD_AI.FEEDBACK()を使用すると、期待するクエリと自然言語のフィードバック(任意)の両方を送信することが出来ます。
期待するクエリをそのままフィードバックとして送信することで、どのようなクエリが期待されているのか、明確にLLMに伝えることができるので、複雑なクエリ生成が上手くいかない場合に非常に有効です。
生成されたSQLクエリを実行してみると、APPLICANTS、SEATSがNULLの高校は表示されず、倍率が高い高校の上位10校が表示されています。
ベクトル索引が作成されているはずなので、確認してみます。
select * from PROF_SCHOOL_FEEDBACK_VECINDEX$VECTAB;
上記のクエリを実行すると、以下の結果が表示されました。
「倍率が高い高校10校」という問い合わせに対応するSQLクエリも確認することが出来ます。
| CONTENT | 倍率が高い高校10校 |
| ATTRIBUTES | {"response":"SELECT "HIGHSCHOOLS"., ROWNUM AS "row_num" FROM (SELECT "ADMIN"."HIGHSCHOOLS". FROM "ADMIN"."HIGHSCHOOLS" WHERE "APPLICANTS" IS NOT NULL AND "SEATS" IS NOT NULL AND "SEATS" != 0 ORDER BY "APPLICANTS" / "SEATS" DESC) "HIGHSCHOOLS" WHERE ROWNUM <= 10","feedback_type":"negative","sql_id":"fy2w9079hh0qg","sql_text":"select ai runsql 倍率が高い高校10校","feedback_content":"倍率を計算するときにnull値がある場合、その高校は表示しないで"} |
| EMBEDDING | [-2.63786316E-003,-9.44519043E-003,-5.54504395E-002,-7.98950195E-002,-5.70678711E-002,-3.405<中略>172E-002,4.38537598E-002,7.41577148E-002,1.37023926E-002,1.8157959E-002] |
3.それでは再度、「倍率が高い高校10校」を問い合わせてみます。
-- 入力
select ai showsql 倍率が高い高校10校;
-- 出力
SELECT
"HIGHSCHOOLS".*,
ROWNUM AS "row_num"
FROM
(SELECT "ADMIN"."HIGHSCHOOLS".*
FROM "ADMIN"."HIGHSCHOOLS"
WHERE "APPLICANTS" IS NOT NULL AND "SEATS" IS NOT NULL AND "SEATS" != 0
ORDER BY "APPLICANTS" / "SEATS" DESC) "HIGHSCHOOLS"
WHERE ROWNUM <= 10
アップデートされたSQLクエリが生成されるようになりました。

4.最後に、質問文を変えて高校を問い合わせてみます。
-- 入力
select ai showsql 中国語のクラスがある学校を教えてください。入試の倍率が高い順に3校教えてください。;
-- 出力
SELECT
"HIGHSCHOOLS".*,
ROWNUM AS "row_num"
FROM
(SELECT "ADMIN"."HIGHSCHOOLS".*
FROM "ADMIN"."HIGHSCHOOLS"
WHERE UPPER("LANGUAGE_CLASSES") LIKE UPPER('%中国語%')
AND "APPLICANTS" IS NOT NULL AND "SEATS" IS NOT NULL
AND "SEATS" != 0 ORDER BY "APPLICANTS" / "SEATS" DESC) "HIGHSCHOOLS"
WHERE ROWNUM <= 3
質問文が変わっていても、倍率を計算するときのロジック(NULL値は無視する)が適用されています。
生成されたSQLクエリを実行してみると、中国語のクラスがある学校の内、倍率が高い学校の上位3校が表示されました。
LLMを使用したクエリ生成のため、使用するLLMやEmbeddingモデルによって精度が変わります。また、同じモデルを使用した場合でも、本記事とは結果が異なる場合もあります。
Select AI Feedbackの動き
Select AI Feedbackは以下のような流れで動いています:
-
Select AI(NL2SQL)を使用し、SQLクエリを生成(例:
Select AI 昨年度の〇〇の売上は?;) -
Select AI Feedbackを使用し、生成されたSQLクエリに対してフィードバックを送信(例:
Select AI Feedback 昨年度は2024年6月1日から2025年5月31日までです;) -
LLMを使用し、ユーザーからのフィードバックを基にSQLクエリを改良
-
ユーザープロンプト(例:昨年度の〇〇の売上は?)をベクトル化
-
ベクトル化されたユーザープロンプトと、それに対応する改良されたSQLクエリをベクトルデータベースに保存
-
次回以降のクエリ生成の際に、ユーザープロンプトに最も類似した過去のユーザープロンプトとSQLクエリを検索
-
ベクトル検索の結果、現在のユーザープロンプトに類似したプロンプトを特定
-
最も一致した結果を拡張プロンプトの一部としてLLMに送信し、ヒントとして活用
この機能をサポートするため、Select AI Feedbackを初めて使用する際に、ベクトル索引が自動で作成されます。このベクトル索引は、「<使用しているAIプロファイル名>_FEEDBACK_VECINDEX」という名前が付けられます。AIプロファイル毎にフィードバックが蓄積されます。
ベクトル索引のsimilarity_thresholdとmatch_limitはデフォルト値になっていますが、DBMS_CLOUD_AI.UPDATE_VECTOR_INDEXプロシージャで変更することが出来ます。
Oracle AI Vector Search を使用しているため、フィードバック機能には Oracle Autonomous Database 23ai が必要です。
Select AI Feedbackの使い方
Select AIではいくつかのアクション・キーワードを提供していますが、その内runsql、showsql、explainsqlのアクション・キーワードを使用した問い合わせに対してフィードバックを送信することが出来ます。
フィードバックを送信できる問い合わせの例:
・ Select AI <自然言語の問い合わせ>
・ Select AI runsql <自然言語の問い合わせ>
・ Select AI showsql <自然言語の問い合わせ>
・ Select AI explainsql <自然言語の問い合わせ>
フィードバックを送信する方法として、「Feedbackというアクション・キーワードを使用する方法」、「PL/SQLプロシージャを使用する方法」の2つの方法があります。
Feedbackアクションを使用する場合:
以下の様に、プロンプトを記載することで、特定の問い合わせに対してフィードバックをすることが出来ます。
select ai feedback for query "Select AI showsql <自然言語の問い合わせ>", <生成されたSQLクエリに対してのフィードバック>;
-- ネガティブなフィードバックの例:
select ai feedback for query "select ai showsql 視聴履歴は全部で何件ですか", countの代わりにsumを使ってください;
-- ポジティブなフィードバックの例:
select ai feedback for query "select ai showsql 視聴履歴は全部で何件ですか", 生成されたSQLクエリは正しいです;
SQLクエリを指定する際に、SQL IDを使用して指定することも出来ます。IDを複数指定することは出来せん。
select ai feedback <生成されたSQLクエリに対してのフィードバック> for sql_id <特定の問い合わせのSQL ID>;
-- ネガティブなフィードバックの例:
select ai feedback countの代わりにsumを使ってください for sql_id 35f45z1fs83sf;
-- ポジティブなフィードバックの例:
select ai feedback 生成されたSQLクエリは正しいです for sql_id 35f45z1fs83sf;
プロンプトやSQL IDで指定をせずに、一番最後(直近)のプロンプトに対してフィードバックを付与することもできます。
この方法でフィードバックを行う際には、フィードバックを行うユーザーに対して、v$sessionとv$mapped_sqlへのアクセス権を付与する必要があります。また、サーバー出力をOFFにするように設定が必要です。
-- ネガティブなフィードバックの例:
select ai feedback countの代わりにsumを使ってください;
-- ポジティブなフィードバックの例:
select ai feedback 生成されたSQLクエリは正しいです;
PL/SQLプロシージャを使用する場合:
DBMS_CLOUD_AI.FEEDBACKを使用し、フィードバックを行う事も出来ます。
DBMS_CLOUD_AI.FEEDBACK(
profile_name IN VARCHAR2,
sql_id IN DBMS_ID,
feedback_type IN VARCHAR2 DEFAULT NULL,
response IN CLOB DEFAULT NULL,
feedback_content IN CLOB DEFAULT NULL,
operation IN VARCHAR2 DEFAULT 'ADD'
);
DBMS_CLOUD_AI.FEEDBACK(
profile_name IN VARCHAR2,
sql_text IN CLOB,
feedback_type IN VARCHAR2 DEFAULT NULL,
response IN CLOB DEFAULT NULL,
feedback_content IN CLOB DEFAULT NULL,
operation IN VARCHAR2 DEFAULT 'ADD'
);
・profile_name:使用するAIプロファイル。指定しない場合は、セッションで設定されたデフォルトのプロファイル。必須。
・sql_id:V$MAPPED_SQLで確認可能なSQL ID。sql_id、sql_textのどちらかが必須。
・sql_text:プロンプト(例:Select AI 昨年度の〇〇の売上は?;)
・feedback_type:フィードバックの種類。使用可能な値は以下の通り:
・ positive: 生成された結果に対してポジティブなフィードバックを行う場合。
・ negative: 生成された結果に対してネガティブなフィードバックを行う場合。
・response:ユーザーが期待する正しいSQLクエリ結果を記載。
・feedback_content:SQLクエリ・結果セットに対してのフィードバック。responseと併用することも可能。
・operation:実行する操作を指定。指定できる値は以下の通り:
・ add(デフォルト): フィードバックを付与。
・ delete: フィードバックを削除。
それぞれのsql_idに対して1つのフィードバックのみ付与できるため、同じsql_idのクエリに対して追加のフィードバックを付与すると以前のフィードバックが新しいフィードバックに置き換えられます。
DBMS_CLOUD_AI.FEEDBACKを使用し、ポジティブなフィードバックを行う例:
BEGIN
DBMS_CLOUD_AI.FEEDBACK(
profile_name => 'OCI_FEEDBACK1',
sql_id=> '852w8u83gktc1',
feedback_type=>'positive',
operation=>'add');
END;
/
DBMS_CLOUD_AI.FEEDBACKを使用し、ネガティブなフィードバックを行う例:
BEGIN
DBMS_CLOUD_AI.FEEDBACK(
profile_name => 'OCI_FEEDBACK1',
sql_text=> 'select ai showsql 視聴履歴は全部で何件ですか',
feedback_type=> 'negative',
response=>'SELECT SUM(1) FROM "ADMIN"."WATCH_HISTORY"',
feedback_content=>'countの代わりにsumを使ってください');
END;
/
付与したフィードバックを削除する例:
BEGIN
dbms_cloud_ai.feedback(
profile_name => 'OCI_FEEDBACK1',
sql_id => '3b5qy8u514r38',
operation => 'delete');
END;
/


