OCI Generative AI Agent （生成AIエージェント）のSQLツールを試してみる



# はじめに
OCIから Generative AI Agent (以降、生成AIエージェント）の機能が新たに追加されました。すでにいくつかの記事がQiita上にも投稿されていますが、RAGツールを使ったものが多く、残念ながらSQLツールと関数呼び出しツールについては影が薄いようです。
というわけで、今回はOCI生成エージェントのSQLツールがどのようなものなのか確認してみます。また昨年から利用できるようになった SELECT AI との違いも見てみたいと思います。


# OCI生成AIエージェントのSQLツールとは
OCI生成AIエージェントのSQLツールは、生成AIエージェントに自然言語で問い合わせをすると、それをSQLに変換してくれるものです。

https://docs.oracle.com/ja-jp/iaas/Content/generative-ai-agents/sql-tool.htm

https://docs.oracle.com/ja-jp/iaas/Content/generative-ai-agents/sqltool-guidelines.htm

また、結果セットの取得（SQLの実行）を行わなければデータベースと接続している必要はなく、データベース・スキーマ情報およびテーブルと列の説明があればエージェントはSQLを生成してくれます。


# デモ用テーブルの構成
まず、今回のデモ用に以下のようなテーブルがある想定とします。
1. 売上データ（Sales）
2. 製品マスタ（Products）
3. 製品カテゴリマスタ（Cateogries）
4. 部署（店舗）マスタ（Departments）

また、テーブルの定義は以下のような想定です。

```SQL
CREATE TABLE Sales (
    RecordKey     INT PRIMARY KEY,
    FiscalYear    INT NOT NULL,
    SalesDate     DATE NOT NULL,
    DepartmentKey VARCHAR(50) NOT NULL,
    ProductKey    VARCHAR(50) NOT NULL,
    Quantity      INT NOT NULL,
    Amount        INT NOT NULL,
    FOREIGN KEY (ProductKey)    REFERENCES Products(ProductKey),
    FOREIGN KEY (DepartmentKey) REFERENCES Departments(DepartmentKey)
);

CREATE TABLE Products (
    ProductKey  VARCHAR(50) PRIMARY KEY,
    ProductId   VARCHAR(50) NOT NULL,
    ProductName VARCHAR(50) NOT NULL,
    CategoryKey VARCHAR(50) NOT NULL,
    FOREIGN KEY (CategoryKey)   REFERENCES Categories(CategoryKey)
);

CREATE TABLE Categories (
    CategoryKey  VARCHAR(50) PRIMARY KEY,
    CategoryId   VARCHAR(50) NOT NULL,
    CategoryName VARCHAR(50) NOT NULL
);

CREATE TABLE Departments (
    DepartmentKey  VARCHAR(50) PRIMARY KEY,
    DepartmentId   VARCHAR(50) NOT NULL,
    DepartmentName VARCHAR(50) NOT NULL
);
```
ここで大切なのは、しっかりと主キーおよび外部キーを定義しておくことです。エージェントがテーブル間のJOINをする上で必要な情報となります。

# SQLツールを作成してみる
実際にOCI生成AIエージェントでSQLツールを作成してみたいと思います。生成AIエージェントを使用できるリージョンは限られていますのでご注意ください。生成AIエージェントを利用できるリージョンは以下のドキュメントで確認できます。今回は大阪リージョンを使用しています。

https://docs.oracle.com/ja-jp/iaas/Content/generative-ai-agents/overview.htm#regions

#### エージェントの作成

OCIの画面から「アナリティクスとAI」を選択、その中の「AIサービス」から「生成AIエージェント」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/53a152bd-5d9f-4373-8899-f3e8040dd949.png)


エージェントをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/a9b221fb-85ed-4464-ad73-2d35540e7f37.png)


エージェントの作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/f88b27ab-11d0-48eb-abf3-145a6c42f15a.png)

名前を入力し、コンパートメントを選択して次をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/cc0af94c-1790-4cf8-8101-e6a14184e7ec.png)

#### SQLツールの作成

続けてツールの作成画面になるので、ツールの作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/faafe6b2-e0ae-4f1e-8eed-9d857a0e5d8b.png)

SQLをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/af5e1cea-049b-41b6-beab-1c6092f47383.png)

作成するSQLツールの名前と説明を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/b3f6ccdf-7741-41e1-8c91-e98d2690d2ce.png)


このツールのデータベース・スキーマ構成のインポートでインラインを選択します。データベース・スキーマには、先ほど記載した各テーブルのCREATE TABLE文を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/35b70a26-39d0-491f-b534-a28ad5ae8c01.png)

モデルのカスタマイズは今回は「小（コスト節約）」を選択します。言語はOracle SQLを選択します。コンテキスト内学習の例はいったん「なし」を選択します。データベース接続は今回行わないので未入力のままにしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/29e555b8-d053-4219-aaf0-09721d132843.png)


カスタム指示はエージェントの動作を変更するためのプロンプトです。今回はガイドラインの例をそのまま入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/39a32e2c-bfa7-4b58-9d2b-8d763f4c534f.png)


表と列の説明はインラインを選択します。テキストボックスが表示されるので、下記のように各テーブルとテーブルの各列の説明を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/fb3ec23b-2a86-45c1-ad10-288a251313a2.png)



```:表と列の説明
Description of the important tables in the schema:

Sales             Sales data, quantity and amount.
Categories        Category names and other information
Products          Product names and other information 
Departments       Department names and other information 

Description of the important columns of the tables in the schema:

SALES TABLE

sales.FiscalYear    A fiscal year of SalesDate column.
sales.SalesDate     sales date.
sales.Quantity      Quantity of sales.
sales.Amount        Amount of sales.

---------------------------------------------------------------------
CATEGORIES TABLE

categories.CategoryKey   Unique key that identifies the category of a product.
categories.CategoryName  Name of the category.

---------------------------------------------------------------------
PRODUCTS TABLE

products.ProductKey   Unique key that identifies the product.
products.ProductName  Name of the product.

---------------------------------------------------------------------
DEPARTMENTS TABLE

departments.DepartmentKey   Unique key that identifies the department.
departments.DepartmentName  Name of the department.

```

ツールの作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/56d17cc0-ca4c-4e9c-9f5d-2e6abc8f920d.png)


エージェント・エンドポイントの設定画面では、「このエージェントのエンドポイントの自動生成」にチェックが入っていることを確認します。その他の項目は今回デフォルトのままで、次をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/563f0be4-8d65-40d7-85bc-ab6137f4087d.png)

エージェントの作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/6ec715dd-12b6-4cab-85cb-12deeb6118c2.png)

Llama 3に関する確認画面が表示されたら、同意にチェックを入れて送信ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/c9e39d57-7eaa-4b81-976a-c5e3a6d9398d.png)


正常に作成されれば、以下の画面のようにエージェントが作成されアクティブになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/b3e7d2c0-ef55-42d5-b3e3-d3c0333a2374.png)


# チャットしてみる
それでは早速実際にチャットしてみたいと思います。今回はSDKを使わず、お手軽に試すことのできるOCI上のチャットのインターフェースで試してみたいと思います。

エージェントの画面で「チャットの開始」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/528f6ae2-7d85-4a6c-b35a-48585a3b44a7.png)

チャット画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/9a004064-174e-4624-8b2e-20fba8f4f6bb.png)


試しに「2024年4月から2024年9月までの製品カテゴリが食品の月別の売上金額の合計」と日本語で入力して送信してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/8700754d-42c2-48a2-8640-705e64288781.png)

日本語でも問題なくSQLが生成されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/aad13132-4303-4fa6-a7df-ece0a407e70e.png)

参照するテーブルと列、JOINの内容は問題ありません。しかし、月別と指定しましたが、SalesDateをそのまま使用しているので日別になってしまっています。
```SQL:生成されたSQL
SELECT 
    c.CategoryName, 
    s.FiscalYear, 
    s.SalesDate, 
    SUM(s.Amount) AS Total_Sales 
FROM 
    Sales s 
JOIN 
    Products p 
ON 
    s.ProductKey = p.ProductKey 
JOIN 
    Categories c 
ON 
    p.CategoryKey = c.CategoryKey 
WHERE 
    c.CategoryName = '食品' AND 
    s.FiscalYear = 2024 AND 
    TO_CHAR(s.SalesDate, 'MM') BETWEEN '04' AND '09' 
GROUP BY 
    c.CategoryName, 
    s.FiscalYear, 
    s.SalesDate 
ORDER BY 
    s.FiscalYear, 
    TO_CHAR(s.SalesDate, 'MM'); 

```

SQLツールの編集画面で、作成時に指定しなかったコンテキスト内学習の例に今回の質問と期待するSQLを回答として入力してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/3d39e5a4-87dc-49f0-ba94-3686e0e62f87.png)


SQLツールの更新内容を保存して、SQLツールがアクティブになったら再びエージェントのチャットで質問をしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091399/1be9790f-b649-4661-aedf-f03fd8c5e226.png)

コンテキスト内学習の例をもとにSQL文が期待するものになっています。データベース・スキーマに問題がなく、表と列の説明が十分な内容でも期待するようなSQLが生成されない場合は、コンテキスト内学習の例を登録することで結果の改善が期待できそうです。


# SELECT AI との違い
生成AIエージェントのSQLツールと同じように生成AIを活用したものとして、SELECT AIがありますが、簡単にこの２つの違いを見てみたいと思います。

SELECT AIも生成AIエージェントのSQLツールと同様、自然言語での問い合わせをSQLに変換してくれる機能です。すでにQiitaなどでSELECT AIについて解説している記事がありますので、詳しく知りたい方は以下の記事をご参照ください。

https://qiita.com/500InternalServerError/items/10d1af43a381514a51dd

https://qiita.com/marfujim/items/3e2fe1861a7b148e41b1

https://www.ashisuto.co.jp/db_blog/article/oracle-autonomous-database-23ai-select-ai-features.html


生成AIエージェントのSQLツールとSELECT AIの違いは以下のようになっています。

|  | 生成AIエージェントのSQLツール | SELECT AI |
|:-:|:--|:--|
| 実行場所  | SDKなどを使用して開発したチャットアプリ  | SQLを実行できる環境  |
| 実行方法  | チャットでエージェントに問い合わせ  | SELECT AI を使用可能なユーザーで Autonomous Database にログインし、先頭に「SELECT AI」を付けたクエリを実行  |
| 対応データベース(SQL)  | Oracleデータベース全般、SQLite  | Autonomous Database のみ  |
| テーブルなどの情報  | Create Table文や、表と列の説明を登録  | どのテーブルを使用できるかはAIプロファイル作成時に指定<br>表や列の説明についてはSQLのCOMMENT文で登録  |
| 機能  | 基本的にはSQLの生成<br>結果セットの取得もできるが、大きな結果セットの場合オブジェクトストレージに保存される場合がある<br>データベースと接続していなくても使える  | 基本的には結果セットを返す<br><br>オプションパラメータとして以下のものがある<br>runsql - 結果セットを返す（指定しない時のデフォルト）<br>showsql - 生成されたSQLを返す<br>narrate - 会話形式で結果を返す<br>chat - 一般的なAIチャット（データベースへの問合せは行わず、LLMから直接レスポンスを生成する）<br>explainsql - 生成されたSQLを自然言語で説明　<br><br>データの生成も可能（GENERATE_SYNTHETIC_DATAプロシージャ） |
| 使用するLLM  | 選べない  | AIプロファイルの作成時に選択可能<br>（OpenAI、Cohere、Azure OpenAI Service、Google、Anthropic、Hugging Face、Google Gemini、OCI生成AIサービス）  |
| 権限など  | SQLの実行まで含める場合はOCI上でデータベース接続の作成、動的グループの作成などおこなう必要あり  | 接続ユーザーにDBMS_CLOUD_AIパッケージの実行権限の付与が必要<br>CREATE_CREDENTIALプロシージャを使用して、生成AIサービスに接続するためのクレデンシャルを作成する必要あり  |



# まとめ
OCI生成AIエージェントのSQLツールは、今回のデモでは多少の間違いはあったものの、おおむね問題なくSQLを生成してくれました。ただし、やはり生成AIは完璧ではないので、生成されたSQLが正しいかの最終的なチェックについては人間が行う必要があると思います。

ポイントとしては

* 主キー、外部キーの定義をしておく
* 表および列の説明を作成する
* 期待通りの結果にならない場合はコンテキスト内学習の例で改善

の3つになると思います。

# 関連記事
実際にPythonでSDKを使用してOCIの生成AIエージェントと連携するアプリを構築しようと考えている方は、こちらの記事がとても参考になります。

https://qiita.com/naoto_naka/items/00a26882bbe4b2192745