ChatBI は、自然言語から SQL へ (NL2SQL) 技術を使用して、自然言語クエリからレポートを生成します。このトピックでは、架空のレストラン管理システム「Ali Xiang」を使用して ChatBI の主要な特徴を説明し、サービスを迅速かつ効率的に使用するのに役立ちます。
PolarDB for AI 機能の有効化
AI ノードを追加し、そのデータベースアカウントを設定します。詳細については、「PolarDB for AI 機能の有効化」をご参照ください。
説明クラスターの購入時に AI ノードを追加した場合は、AI ノードのデータベースアカウントを直接設定できます。詳細については、「標準アカウントの作成」をご参照ください。
アカウントには、ターゲットデータテーブルにアクセスし、ChatBI が必要とするデータベース操作を実行するための読み取りおよび書き込み権限が必要です。
PolarDB クラスターに [クラスターエンドポイント] を使用して接続します。詳細については、「PolarDB for AI へのログイン」をご参照ください。
説明コマンドラインからクラスターに接続する場合は、
-cオプションを追加してください。デフォルトでは、DMS は [プライマリエンドポイント] を使用してクラスターに接続します。手動でエンドポイントを [クラスターエンドポイント] に変更する必要があります。その後、現在の SQL ウィンドウを閉じて新しいウィンドウを開き、SQL 文を実行します。
データ準備
「Ali Xiang」は架空のレストラン会社です。その請求管理システムには、以下に示す 3 つのテーブルが含まれており、ダウンロードできます。
テーブルスキーマに基づいて、テーブルと列にコメントを追加します。これにより、大規模言語モデル (LLM) がデータをより良く認識し理解できるようになり、データ処理と分析中のモデルの精度と効率が向上します。
CREATE TABLE restaurant_info (
id INT COMMENT 'アウトレット ID',
position VARCHAR(128) COMMENT 'アウトレットの場所',
PRIMARY KEY (id)
) COMMENT='アウトレットテーブル';
CREATE TABLE menu_info (
id INT COMMENT '料理 ID',
name VARCHAR(64) COMMENT '料理名',
type INT COMMENT '料理の種類',
unit_price INT COMMENT '料理の単価',
PRIMARY KEY (id)
) COMMENT='メニューテーブル';
CREATE TABLE bill_info (
id INT COMMENT '請求書 ID',
items VARCHAR(512) COMMENT '注文された料理',
actural_amount INT COMMENT '実際の支払額',
restaurant_id INT COMMENT '食事のアウトレット',
waiter VARCHAR(16) COMMENT 'ウェイター',
diner_count INT COMMENT '食事客の数',
pay_time DATE COMMENT '注文時間',
PRIMARY KEY (id)
) COMMENT='請求書テーブル';ChatBI の使用
これで、PolarDB for AI の NL2SQL モデル を使用して、ユーザーの質問に対応する SQL 文を生成できます。
テーブルスキーマインデックスの作成
次の SQL 文を実行して、schema_index という名前のテーブルスキーマインデックステーブルを作成します。このテーブルは、LLM にテーブルスキーマ情報を提供します。
/*polar4ai*/CREATE TABLE schema_index(id integer, table_name varchar, table_comment text_ik_max_word, table_ddl text_ik_max_word, column_names text_ik_max_word, column_comments text_ik_max_word, sample_values text_ik_max_word, vecs vector_768,ext text_ik_max_word, PRIMARY key (id));このテーブルはデータベースに直接表示されません。その情報を表示するには、次の SQL 文を実行します。
/*polar4ai*/SHOW TABLES;次に、次の SQL 文を実行して、データテーブルスキーマを schema_index インデックステーブルにインポートします。
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_text2vec, SELECT '') WITH (mode='async', resource='schema') INTO schema_index;文を実行すると、PolarDB for AI は現在のデータベース内のすべてのテーブルをベクトル化し、デフォルトで列の値をサンプリングします。
文を実行すると、バックグラウンドタスクの task_id (例:bce632ea-97e9-11ee-bdd2-492f4dfe0918) が返されます。次の SQL 文を実行してタスクのステータスをクエリします。taskStatus が finish になると、インデックス構築は完了です。
/*polar4ai*/SHOW TASK `bce632ea-97e9-11ee-bdd2-492f4dfe0918`;NL2SQL モデルを使用した質問への回答
次の SQL 文を実行して、LLM ベースの NL2SQL 機能をオンラインで使用します。この例では、ユーザーの質問は「今週の総収入はいくらですか」で、テーブルスキーマインデックスは schema_index です。
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2sql, select 'What is the total income for this week') WITH (basic_index_name='schema_index');データベースがリクエストを処理し、LLM から応答を取得するには時間がかかります。期待される結果は以下のとおりです。

上記の例に基づいて、他の典型的な質問をすることができます。これらの質問は、GROUP BY、複数テーブルの JOIN、ORDER BY、数式など、さまざまなシナリオをカバーしています。
質問 No. | ユーザーの質問 | NL2SQL の戻り値 |
1 | 収入順にアウトレットを並べ替える |
|
2 | 上海で最も収入が高いアウトレットはどれですか? |
|
3 | 上海の一人当たりの平均消費額はいくらですか? |
|
4 | 今月最も注文された料理トップ 10 は何ですか? |
|
5 | 今月の前月比の収入増加率は何パーセントですか? |
|
6 | 上海で最も顧客トラフィックが多いアウトレットはどれですか? |
|
LLM ベースの NL2SQL モデルはユーザーの質問にうまく答えますが、一部の応答は期待どおりではない場合があります。たとえば、2 番目の質問では、ユーザーはアウトレット名を求めています。質問を「上海で最も収入が高いアウトレットはどれですか?アウトレット名を返してください。」と言い換えると、モデルは次の SQL 文を返します:SELECT r.name FROM bill_info b JOIN restaurant_info r ON b.restaurant_id = r.id WHERE r.position = 'Shanghai' ORDER BY b.actural_amount DESC LIMIT 1;。モデルをファインチューニングして精度を向上させることもできます。次のセクションでは、これらの問題に対処する方法について説明します。
モデルのファインチューニング
質問テンプレートの設定
一般的な質問テンプレートを使用してモデルをガイドできます。これらのテンプレートは、モデルが SQL 文を生成するのに役立つ特定の知識を提供します。
次の SQL 文を実行して、質問テンプレートテーブル
polar4ai_nl2sql_patternを作成します。CREATE TABLE `polar4ai_nl2sql_pattern` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主キー', `pattern_question` text COMMENT 'テンプレートの質問', `pattern_description` text COMMENT 'テンプレートの説明', `pattern_sql` text COMMENT 'テンプレートの SQL', `pattern_params` text COMMENT 'テンプレートのパラメーター', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;テーブル名は
polar4ai_nl2sql_patternで始まる必要があります。テーブルスキーマには、`CREATE TABLE` 文の 5 つの列が含まれている必要があります。次に、質問テンプレートのインデックステーブル
pattern_indexを作成します。/*polar4ai*/CREATE TABLE pattern_index(id integer, pattern_question text_ik_max_word, pattern_description text_ik_max_word, pattern_sql text_ik_max_word, pattern_params text_ik_max_word, pattern_tables text_ik_max_word, vecs vector_768, PRIMARY key (id));モデルをファインチューニングするには、2 番目の質問のテンプレートを設定します。目標は、アウトレットの名前を返すことです。
次の SQL 文を実行して、新しいパターンを追加します。
INSERT INTO polar4ai_nl2sql_pattern (id, pattern_question, pattern_description, pattern_sql, pattern_params) VALUES ( 1, "Which outlet in #{position} has the highest income?", "Which outlet in [location] has the highest income?", "SELECT r.position FROM bill_info b JOIN restaurant_info r ON b.restaurant_id = r.id WHERE r.position LIKE '%#{position}%' ORDER BY b.actural_amount DESC LIMIT 1;", '[{"table_name":"bill_info","param_info":[{"param_name":"#{position}","value":["Shanghai"]}], "explanation": "消費場所"}]' );パターンはスロットを使用して複数の場所を照合します。
pattern_sql列に、正しい SQL 文を入力し、スロットを#{}でマークします。pattern_params列は、テーブル情報の追加の後処理に使用されますが、ここでは無視できます。次に、質問テンプレート情報をインデックステーブルにインポートします。
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_text2vec, SELECT '') WITH (mode='async', resource='pattern') INTO pattern_index;schema_indexテーブルの構築プロセスと同様に、タスク ID が返されます。/*polar4ai*/show task 'xxx-xxx-xxx'を実行してタスクのステータスを確認できます。説明polar4ai_nl2sql_patternテーブルのデータが更新された場合は、pattern_indexを再作成し、データを再度インポートする必要があります。次の SQL 文を使用して、古いインデックステーブルを削除します。/*polar4ai*/DROP TABLE pattern_index;問題のある SQL 文を再実行し、
pattern_indexヒントワードを追加します。/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2sql, select 'Which outlet in Shanghai has the highest income?') WITH (basic_index_name='schema_index',pattern_index_name='pattern_index');
設定テーブルの作成
質問を前処理したり、生成された SQL を後処理したりする場合は、設定テーブルを使用できます。
語彙の意味のヒント
6 番目の質問では、LLM は「customer traffic」という用語を正確に解釈できません。polar4ai_nl2sql_llm_config テーブルを設定して、この用語を前処理できます。
CREATE TABLE `polar4ai_nl2sql_llm_config` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主キー',
`is_functional` int(11) NOT NULL DEFAULT '1' COMMENT '有効かどうか',
`text_condition` text COMMENT 'テキスト条件',
`query_function` text COMMENT 'クエリ処理',
`formula_function` text COMMENT '数式情報',
`sql_condition` text COMMENT 'SQL 条件',
`sql_function` text COMMENT 'SQL 処理',
PRIMARY KEY (`id`)
);設定項目を挿入して、大規模言語モデル (LLM) に「customer traffic」または「customer flow」を食事客の数としてカウントするように指示できます。
INSERT INTO polar4ai_nl2sql_llm_config (id, is_functional, text_condition, query_function, formula_function, sql_condition, sql_function) VALUES (
1,
1,
"customer traffic||customer flow",
"",
"Customer traffic or customer flow is counted as the sum of the number of diners",
"",
""
);is_functional の値が 1 の場合、設定項目がアクティブであることを示します。text_condition フィールドの値「customer traffic||customer flow」は、「customer traffic」または「customer flow」のいずれかを含む質問に一致します。formula_function フィールドは、テキストまたは数式を使用して、LLM に技術用語の意味を説明します。
この場合、インデックステーブルを構築したり、ベクトル化を実行したりせずに、SQL 生成を直接実行できます。結果は以下のとおりです。

あいまい検索のヒント
3 番目の質問では、= オペレーターで地名を照合すると失敗する可能性があります。次の設定項目を追加して、地名の照合にあいまい検索を使用するようにヒントを与えることができます。
INSERT INTO polar4ai_nl2sql_llm_config (id, is_functional, text_condition, query_function, formula_function, sql_condition, sql_function) VALUES (
2,
1,
"",
"",
"Matching for the outlet location 'position' requires a fuzzy search",
"",
""
);ここで、text_condition は空です。これは、設定項目がグローバルに適用されることを意味します。注意して使用してください。
結果は以下のとおりです。場所の照合は、正しくあいまい検索を使用するようになりました。

同様に、5 番目の質問では、「前月比」と「前年比」の計算式を polar4ai_nl2sql_llm_config テーブルに追加できます。これにより、生成される SQL の精度が向上します。挑戦として、ご自身で試してみてください。
チャート出力
NL2SQL が SQL 文を生成した後、クエリ結果を縦棒グラフ、折れ線グラフ、円グラフなどのチャートとして可視化できます。PolarDB NL2Chart 機能は、質問と SQL 文からチャートベースのレポートを生成できます。この機能は、縦棒グラフ、円グラフ、折れ線グラフをサポートしています。
NL2SQL へのクエリが次のようであると仮定します。
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2sql, select 'Merchant type statistics') WITH (basic_index_name='schema_index',pattern_index_name='pattern_index');次の SQL 文が生成されます。SQL 文が実行され、空でない結果が返されることを確認してください。
SELECT merchtype AS merchant_type,COUNT(*) AS product_count FROM hkrt_merchant_info GROUP BY merchtype;NL2Chart の使用:
構文
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2chart, <SQL_statement>) WITH (usr_query = <usr_query>, result_type = <result_type>);パラメーターの説明
パラメーター
説明
例
usr_query
ユーザーの質問。これにより、チャートを生成するための要件が明確になります。
「2023 年の四半期ごとの売上統計」
result_type
結果タイプを指定します。現在、
'IMAGE'のみがサポートされています。'IMAGE'SQL statement
データを取得するために NL2SQL モジュールによって生成された SQL クエリ文。
SELECT quarter, sales FROM sales_data WHERE year = 2023例:生成された SQL 文のクエリ結果をチャートに変換する
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2chart, SELECT merchtype AS merchant_type, COUNT(*) AS merchant_count FROM hkrt_merchant_info GROUP BY merchtype) WITH (usr_query = 'Merchant type statistics', result_type='IMAGE');結果は次のとおりです。
説明返されるリンクは 90 分間有効な画像 URL です。
http://db4ai-xxx-xx-xxxx-xxx-xxxx.aliyuncs.com/pc-bpze47ma2c515087l6/OSSAccessKeyId=xxxxxxx&Expires=1716130199&Signature=KvPFzfMebIEmqxPIXURurwwbsXM%3D
(オプション) チャートタイプの選択または強制
モデルは、ユーザーの質問とデータの理解に基づいて適切なチャートを選択します。ユーザーの質問の表現方法によってモデルをガイドできます。
次の表は、質問タイプとチャートタイプのマッピングを示しています。
質問タイプ
チャートタイプ
ユーザーの質問の例
説明
数量統計
縦棒グラフ
「都市別の売上統計を提供してください」
数量、合計金額、頻度など、異なるカテゴリ間の数値の比較を示します。
トレンド変化
折れ線グラフ
「過去 1 年間のユーザー増加トレンドを示してください」
データが時間とともに、または順序付けられたカテゴリにわたってどのように変化するかを示し、連続性を強調します。
割合分布
円グラフ
「各製品ラインの売上比率を示してください」
全体に対する部分の比例関係を示すのに適しています。データはカテゴリ別であり、明確な合計が必要です。
usr_queryパラメーターを変更することで、特定のチャートタイプを強制できます。usr_queryパラメーターの末尾に追加のコマンドを追加します。-- 出力 SQL を nl2chart に入力して折れ線グラフを描画 /*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2chart, SELECT merchtype AS merchant_type, COUNT(*) AS merchant_count FROM hkrt_merchant_info GROUP BY merchtype ) WITH (usr_query = 'Merchant type statistics, draw a line chart', result_type='IMAGE');
-- 出力 SQL を nl2chart に入力して円グラフを描画 /*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2chart, SELECT merchtype AS merchant_type, COUNT(*) AS merchant_count FROM hkrt_merchant_info GROUP BY merchtype ) WITH (usr_query = 'Merchant type statistics, draw a pie chart', result_type='IMAGE');
詳細については、「自然言語からインテリジェントチャートへ (NL2Chart)」をご参照ください。
モデルの再トレーニングとファインチューニング
モデルがビジネス要件を満たさない場合は、モデルを再トレーニングし、内部パラメーターをファインチューニングして、より良い結果を得ることができます。
条件
この機能は、AI ノードの仕様が polar.mysql.x8.2xlarge.gpu (16 コア、125 GB、GU100 1 基) のクラスターでのみサポートされます。
一度にトレーニングできるモデルは 1 つだけです。
一度にデプロイできるモデルは 1 つだけです。
手順
モデルのトレーニング
/*polar4ai*/CREATE MODEL udf_qwen14b WITH (model_class='qwen-turbo', model_parameter=(basic_index_name='schema_index', pattern_index_name='pattern_index',training_type='efficient_sft')) as (SELECT '')パラメーターの説明
パラメーター | 説明 | デフォルト | 有効値/範囲 |
model_class | モデルタイプ。現在、「qwen-14b-chat」と「qwen-turbo」がサポートされています。 | なし | {'qwen-14b-chat', 'qwen-turbo'} |
model_parameter | モデルパラメーターの設定。必須パラメーターとオプションパラメーターが含まれます。 | なし | なし |
basic_index_name | トレーニングデータ内のデータベース情報がサンプリングされるインデックステーブルの名前。これはデータベースインデックステーブルである必要があります。 | なし | なし |
pattern_index_name | トレーニングデータ内の質問テンプレート情報がサンプリングされるインデックステーブルの名前。これは質問テンプレートインデックステーブルである必要があります。 | なし | なし |
training_type | トレーニングタイプ。有効値は「efficient_sft」と「sft」です。「efficient_sft」は効率的なトレーニングを示し、通常は LoRa を使用します。「sft」はフルパラメーター トレーニングを示します。 | なし | {'efficient_sft', 'sft'} |
n_epochs | エポック数。これは、トレーニング中にモデルがデータセットから学習する回数です。1 から 3 の範囲が推奨されますが、必要に応じて調整できます。 | 3 | [1, 200] |
learning_rate | 学習率。これは、各データ更新の増分パラメーターの重みを表します。学習率が大きいほど、パラメーターの変更が大きくなり、モデルへの影響が大きくなります。 | '3e-4' | なし |
batch_size | バッチサイズ。これは、モデルパラメーターを更新するためのデータステップサイズを表します。16 または 32 のバッチサイズが推奨されます。 | 16 | {8, 16, 32} |
lr_scheduler_type | 学習率スケジューラのタイプ。これは、トレーニング中に重みを更新するときに使用される学習率を動的に変更します。 | 'linear' | {'linear', 'cosine', 'cosine_with_restarts', 'polynomial', 'constant', 'constant_with_warmup', 'inverse_sqrt', 'reduce_lr_on_plateau'} |
eval_steps | モデル検証の間隔ステップサイズ。これは、トレーニングの精度と損失を定期的に評価するために使用されます。 | 50 | [1, 2147483647] |
sequence_length | トレーニングデータのシーケンス長。これは、単一サンプルの最大長です。この長さを超えるデータは自動的に切り捨てられます。 | 2048 | [500, 2048] |
lr_warmup_ratio | ウォームアップステップの総トレーニングステップ数に対する比率。 | 0.05 | (0, 1) |
weight_decay | L2 正則化。過学習を減らすのに役立ちます。 | 0.01 | (0, 0.2) |
gradient_checkpointing | GPU メモリを節約するためにグラデーションチェックポイントを有効または無効にします。 | 'True' | {'True', 'False'} |
use_flash_attn | Flash Attention を使用するかどうかを指定します。 | 'True' | {'True', 'False'} |
lora_rank | LoRa トレーニングのランク。これは、トレーニングデータがモデルに与える影響の度合いに影響します。 | 8 | {2, 4, 8, 16, 32, 64} |
lora_alpha | LoRa トレーニングのスケーリングファクター。これは、初期トレーニングの重みを調整するために使用されます。 | 32 | {8, 16, 32, 64} |
lora_dropout | トレーニング中にランダムにドロップするニューロンの比率。これにより、過学習が防止され、モデルの汎化能力が向上します。 | 0.1 | (0, 0.2) |
lora_target_modules | ファインチューニングのためにモデルの特定のモジュールを選択します。 | 'ALL' | {'ALL', 'AUTO'} |
モデルの表示
/*polar4ai*/SHOW model udf_qwen14bモデルの削除
/*polar4ai*/DROP model udf_qwen14bすべてのモデルの表示
/*polar4ai*/SHOW modelsモデルのデプロイメント
トレーニング済みのモデルは、NL2SQL で使用する前にデプロイする必要があります。
/*polar4ai*/deploy model udf_qwen14bデプロイメントの表示
/*polar4ai*/SHOW deployment udf_qwen14bデプロイメントの削除
/*polar4ai*/DROP deployment udf_qwen14bすべてのデプロイメントの表示
/*polar4ai*/SHOW deploymentsデプロイされたモデルを自然言語から SQL に使用する
/*polar4ai*/SELECT * FROM PREDICT (MODEL _polar4ai_nl2sql, SELECT 'What is the content for id 1?') WITH (basic_index_name='schema_index', llm_model='udf_qwen14b')パラメーターの説明
パラメーター | 説明 |
basic_index_name | 必須。現在の質問に関連するデータベース情報のインデックステーブル。 |
llm_model | オプション。これを空のままにすると、システムは NL2SQL のファインチューニングなしでモデルを呼び出します。値を指定する場合は、「serving」状態にあるデプロイメントの名前であることを確認してください。完全にデプロイされていないモデルは使用できません。 |