TiDBのChat2Query APIを使用してデータベースをAIに集計してもらおう

Chat2QueryはSQLの作成だけでない!APIを使用することで実行までやってくれます!
2024.04.17

ゲームソリューション部の えがわ です。

TiDB Cloudはデータベースのサービスですが、RESTful APIも提供しています。
Chat2Query APIはユーザーの要望をAIが解析し、実行結果を返すAPIとなっています。
今回はこのAPIを使用してデータを取得してみます。

TiDB Cloud は、指示を提供することで AI を使用して SQL ステートメントを生成および実行できる RESTful インターフェイスである Chat2Query API を提供します。その後、API はクエリ結果を返します。Chat2Query API には HTTPS 経由でのみアクセスできるため、ネットワーク上で送信されるすべてのデータは TLS を使用して暗号化されます。
Chat2Query データ アプリには、1 日あたり 100 リクエストのレート制限があります。

※2024/04/17時点でData ServiceはBETAの表記がついています。
機能や内容が変更される場合があります。

環境

  • TiDB Serverless (v7.1.1)

事前準備

TiDB Serverlessのクラスターを作成し、以下のデータを挿入しておきます。

TiDB Serverlessのデータ

以下のデータを追加しておきます。

CREATE TABLE users (
    id BIGINT AUTO_RANDOM PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE orders (
    id BIGINT AUTO_RANDOM PRIMARY KEY,
    user_id BIGINT,
    product_name VARCHAR(255) NOT NULL,
    quantity INT NOT NULL,
    order_date DATE NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com'),
('Charlie', 'charlie@example.com'),
('David', 'david@example.com'),
('Eve', 'eve@example.com'),
('Frank', 'frank@example.com'),
('Grace', 'grace@example.com'),
('Hannah', 'hannah@example.com'),
('Ivy', 'ivy@example.com'),
('Jack', 'jack@example.com');

INSERT INTO orders (user_id, product_name, quantity, order_date)
VALUES
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Laptop', 2, '2023-05-01'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Mouse', 3, '2023-05-02'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Keyboard', 1, '2023-05-03'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Monitor', 5, '2023-05-04'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'USB', 2, '2023-05-05'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Webcam', 4, '2023-05-06'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Headphones', 3, '2023-05-07'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Desk', 1, '2023-05-08'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Notebook', 6, '2023-05-09'),
    ((SELECT id FROM users ORDER BY RAND() LIMIT 1), 'Pen', 2, '2023-05-10');

API設定

クラスターのページに遷移し、Chat2Queryをクリックします。
右上隅の[...]をクリックし、 Access Chat2Query via APIを選択します。

New Chat2Query Data Appを押下します。

Data App Nameで名前を入力し、Link Data SourcesでTiDBのクラスターを選択しCreateを押下します。

Data Serviceが作成されました。

APIキーの発行

APIを実行するためのAPIキーを発行します。
AuthenticationセクションのCreate API Keyを押下します。

ロール(権限)や有効期間を設定できます。
今回はそのままで作成します。作成後はCopy ALLで保存しておきましょう。

エンドポイントのv1とv2について

作成したエンドポイントを確認すると、v1とv2があることがわかります。

v1/chat2dataと比較して、/v2/chat2dataでは、/v2/dataSummariesを呼び出して最初にデータベースを分析する必要があるため、/v2/chat2dataから返される結果は一般的に正確である。

v1/chat2dataに集計内容をリクエストに含め、レスポンスに結果が含まれています。
v2/dataSummariesでデータベースを分析し、/chat2dataで集計内容をリクエストし、/jobs/{job_id}で結果を取得する必要があります。

お手軽に使用する場合はv1、精度が必要な場合はv2を使用しましょう。

v1を実行

お手軽なv1を実行してみます。
v1のエンドポイントを選択し、Show Code Exampleをクリックします。

curlコマンドが表示されるので、PUBLIC_KEY、PRIVATE_KEY、table, instructionを置き換えて実行します。

データ取得

今回は最も売れた商品を取得してみます。
tablesも空で実行してみます。

curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://ap-northeast-1.data.tidbcloud.com/api/v1beta/app/chat2query-endpoint/endpoint/v1/chat2data'\
 --header 'content-type: application/json'\
 --data-raw '{
    "cluster_id": "{your cluster id}",
    "database": "cm_test",
    "tables": [],
    "instruction": "Find the one product that sold the most."
}'

レスポンス

{
    "type": "chat2data_endpoint",
    "data": {
        "columns": [
            {
                "col": "product_name",
                "data_type": "VARCHAR",
                "nullable": false
            }
        ],
        "rows": [
            {
                "product_name": "Notebook"
            }
        ],
        "result": {
            "code": 200,
            "message": "Query OK!",
            "start_ms": 1713238203946,
            "end_ms": 1713238206560,
            "latency": "2.614677848s",
            "row_count": 1,
            "row_affect": 0,
            "limit": 1000,
            "sql": "SELECT `product_name` FROM `orders` GROUP BY `product_name` ORDER BY SUM(`quantity`) DESC LIMIT 1;",
            "ai_latency": "2.58600483s"
        }
    }
}

Notebookが一番売れていると、問題なく取得できました。
SQLもレスポンスに含まれているのは親切ですね!

v2を実行

精度の高いv2を実行していきます。
サンプルのcurlコマンドははv1と同様に取得可能です
dataSummaries -> jobs -> chat2data -> jobsの順に実行していきます。

データ解析

/v2/dataSummariesを実行します。

curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://ap-northeast-1.data.tidbcloud.com/api/v1beta/app/chat2query-endpoint/endpoint/v2/dataSummaries'\
 --header 'content-type: application/json'\
 --data-raw '{
    "cluster_id": "your-cluster-id",
    "database": "cm_test"
}'

レスポンス

{
    "code": 200,
    "msg": "",
    "result": {
        "data_summary_id": 280516,
        "job_id": "datasummariesjobid"
    }
}

レスポンスにjob_idが含まれるので、/v2/jobsで情報を取得します。

curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request GET 'https://ap-northeast-1.data.tidbcloud.com/api/v1beta/app/chat2query-endpoint/endpoint/v2/jobs/datasummariesjobid'\
 --header 'content-type: application/json'

レスポンス

{
    "code": 200,
    "msg": "",
    "result": {
        "ended_at": 1713242373,
        "job_id": "datasummariesjobid",
        "reason": "",
        "result": null,
        "status": "done"
    }
}

statusdoneとなっているので、解析が完了したようです。

データ取得

/v2/chat2dataで集計内容をリクエストします。

curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request POST 'https://ap-northeast-1.data.tidbcloud.com/api/v1beta/app/chat2query-endpoint/endpoint/v2/chat2data'\
 --header 'content-type: application/json'\
 --data-raw '{
  "cluster_id": "yourclusterid",
  "database": "cm_test",
  "raw_question": "Find the one product that sold the most."
}'

レスポンス

{
    "code": 200,
    "msg": "",
    "result": {
        "data_summary_id": 280516,
        "job_id": "chat2datajobid",
        "session_context_id": 280881,
        "session_id": "xxxxxxxxxxxxxxxxxx"
    }
}

こちらもレスポンスにjob_idが含まれるので、/v2/jobsで情報を取得します。

curl --digest --user ${PUBLIC_KEY}:${PRIVATE_KEY} --request GET 'https://ap-northeast-1.data.tidbcloud.com/api/v1beta/app/chat2query-endpoint/endpoint/v2/jobs/chat2datajobid'\
 --header 'content-type: application/json'

レスポンス

{
    "code": 200,
    "msg": "",
    "result": {
        "ended_at": 1713331778,
        "job_id": "chat2datajobid",
        "reason": "",
        "result": {
            "feedback": "",
            "question_id": "560ea657-c9ad-4bbb-8f6c-230ec2117136",
            "raw_question": "Find the one product that sold the most.",
            "session_context_id": 280881,
            "task_tree": {
                "0": {
                    "assumptions": [],
                    "breakdown_type": "Resolve",
                    "chartOptions": {},
                    "clarified_task": "Find the product that sold the most.",
                    "columns": [
                        {
                            "col": "product_name"
                        },
                        {
                            "col": "total_sold"
                        }
                    ],
                    "created_at": 1713331777,
                    "description": "",
                    "level": 0,
                    "parent_task": "",
                    "parent_task_id": "",
                    "possibleExplanations": "",
                    "reason": "no proxy needed for task",
                    "recommendations": {},
                    "rows": [
                        [
                            "Notebook",
                            "6"
                        ]
                    ],
                    "sequence_no": 0,
                    "sql": "SELECT `product_name`, SUM(`quantity`) AS `total_sold` FROM `orders` GROUP BY `product_name` ORDER BY `total_sold` DESC LIMIT 1;",
                    "task": "Find the one product that sold the most.",
                    "task_id": "0"
                }
            },
            "time_elapsed": 3.994330406188965
        },
        "status": "done"
    }
}

Notebook, 6と必要な情報が集計ができています!

日本語で問い合わせてみる

上記では一番売れている商品を英語で問い合わせました。
日本語で「一番売れていない商品」を問い合わせてみます。

{
    "code": 200,
    "msg": "",
    "result": {
        "ended_at": 1713332260,
        "job_id": "nihongonojobid",
        "reason": "",
        "result": {
            "feedback": "",
            "question_id": "2aa73d80-10da-413e-aebd-730c17222856",
            "raw_question": "一番売れていない商品を教えて",
            "session_context_id": 280931,
            "task_tree": {
                "0": {
                    "assumptions": [],
                    "breakdown_type": "Resolve",
                    "chartOptions": {},
                    "clarified_task": "Find the least sold product.",
                    "columns": [
                        {
                            "col": "product_name"
                        },
                        {
                            "col": "total_sold"
                        }
                    ],
                    "created_at": 1713332259,
                    "description": "",
                    "level": 0,
                    "parent_task": "",
                    "parent_task_id": "",
                    "possibleExplanations": "",
                    "reason": "no proxy needed for task",
                    "recommendations": {},
                    "rows": [
                        [
                            "USB",
                            "1"
                        ]
                    ],
                    "sequence_no": 0,
                    "sql": "SELECT `product_name`, COUNT(*) AS `total_sold` FROM `orders` GROUP BY `product_name` ORDER BY `total_sold` ASC LIMIT 1;",
                    "task": "一番売れていない商品を教えて",
                    "task_id": "0"
                }
            },
            "time_elapsed": 3.391174077987671
        },
        "status": "done"
    }
}

レスポンスを確認すると英語に翻訳されてから実行されているようです。
"clarified_task": "Find the least sold product."

簡単な集計でしたが、日本語でも結果に問題はありませんでした!

最後に

Chat2QueryはSQL不要なため、誰でも簡単に集計作業を行うことができます。
TiDBはHTAPなため、TiFlashノードの追加で集計クエリも問題なく使用可能です。
集計作業もAIに頼める未来は近い!?