Azure OpenAI On Your Dataを使ってみた

# 初めに
こんにちは。すぎもんです:grinning:
Azure OpenAI On Your Dataは、企業や個人が所有する非公開データをChatGPTのような高度な言語モデルと組み合わせることができる機能です。この機能により、ユーザーは自社のドキュメントやデータを基にAIモデルの回答をカスタマイズし、より正確で関連性の高い情報を得ることができます。

本ブログでは、Azure OpenAI On Your Dataのセットアップ方法やAPI呼び出し方法について触れていきます。

この記事を通じて、読者の皆様がAzure OpenAI On Your Dataの潜在的な価値を理解し、自社のデータを活用した革新的なAIソリューションの構築に役立てていただければ幸いです


# 今回やること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/6ed70af6-27ad-73f9-56bb-408962fab4fe.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/02abf333-cbfc-ec30-e552-42d502746ad2.png)
チャットプレイグラウンドで質問した内容をBlobストレージにあるPDFファイルの内容から読み取り回答してもらう。


# 実施するのに必要な設定
1．Azure OpenAI
2．Blobストレージ
3．AI Search
4．インデックス
5. 実行してみる
6. コマンドで実行してみる

# Azureの設定

### 1．Azure OpenAI
#### ➀サービス登録
Open AIを作成します。
今回は下記を作成しました。

サービス名：`GPT`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/c003bde9-f9c8-01ec-0afb-934ad33553e5.png)


:::note info
**Azureポータルから新規作成します。**
※今回は「standard S0」を選びました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/cc08b715-42f3-08bd-92ae-ecb6fd585e50.png)
:::


作成したら
[Azure OpenAI Studio](https://oai.azure.com/)を開きます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/92094fc0-6b10-3ca8-2260-3f3686695551.png)



#### ➁デプロイ
Azure OpenAI Studioで「デプロイ」のタブに移動します。
下記をデプロイしました。

デプロイ名：`gpt-35`
デプロイモデル：`gpt-35-turbo-16k`
デプロイしたモデルによっては適していない場合もあるのでご注意ください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/d39c41af-82a2-2db4-8aff-3640c3d524d8.png)

:::note warn
**デプロイは「Standard」があるモデルを選ぶことを推奨します。
＊2024/9の段階ではgpt-4 を選択すると、Provisioned-Managed がデフォルトで選択されています。
選択したモデルによってAI searchに適していない場合やコストが高額になる場合があるのでご注意ください。**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/be63eb82-2508-77d0-4220-68bc1969309c.png" width=70%>
:::

:::note info
**エンドポイント確認**
デプロイしたモデルを押下すると
中が確認できるのでエンドポイント、APIキーを確認することが出来ます。
※APIキーは後程使います。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/18270ce1-9faf-6fac-bf07-dfa57f6f92a3.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/b4e5b759-2fdf-f848-bff1-3df045535a14.png)

:::

****セットアップ****
ここからセットアップ画面に沿って必要なものを設定していきます。

「チャット」タブに移動します。
「データを追加する」から
[`データソースの追加`]を開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/80080ad3-5edb-c03c-4a45-74024ca727ae.png)


**ここからが、Azure OpenAI On Your Dataを使う上での設定になります**
今回はBlobストレージにあるファイルを読み取ってくる設定をするので下記設定をします
➀：`Azure Blob Storage（プレビュー）`
➁～ の設定の詳細は次でご説明します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/f933bd1c-9ce0-1f8f-26f3-a5c5f79cdf43.png)


|項目 | 説明  |
|---|---|
|➀ |Blobストレージから読み取る指定をします　|
|➁ |読み取る対象のストレージとコンテナ名を指定します。  |
|➂ |「4.AI Search」で設定したものを指定します。 |
|➃ |インデックス名を新規で作成することが出来ます。  |
|➄ |インデックスを読み取るタイミングを指定出来ます。  |



### 2．Blobストレージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/ee039d0c-028c-2182-fba3-50470c70a638.png)

今回はBlobストレージにこちらのデータを格納します。
**[HULFT Square サービス仕様書.pdf](https://www.hulft.com/application/files/3917/1141/3653/hulft-square_service_specifications_v6_20240124.pdf)**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/04e01a8a-a6d7-b893-b3b5-4f141b5edd6f.png)


下記のBlobストレージ、コンテナーを作成しPDFファイルを格納します。
Blob Storage名 ： `0001blobstorag`
コンテナー名      ： `addyourdata`


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/d9a2bf0a-684f-dc45-8fcf-56d82c825ed5.png)



:::note info
**Azure OpenAI On Your Dataでは、以下のファイル形式がサポートされています**
.txt (テキストファイル)
.md (Markdownファイル)
.html (HTMLファイル)
.docx (Microsoft Wordファイル)
.pptx (Microsoft Powerpointファイル)
.pdf (PDFファイル)
:::


### 3．AI Search
「➂AI Search」に設定するためのリソースを作成します。ここは新しくポータル画面で作成が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/99f49a67-9910-dd07-1f8a-e6161849c6e0.png)

**➂AI Search**はAzureポータルから新規作成します。
今回は「standard」を選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/c1b3af30-90d7-0461-f94a-37f661df76bb.png)

今回は下記の名前で作成しました。
サービス名：`Search`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/7a4fa4ce-6cb0-b78a-593f-f95d623a0d45.png)

:::note warn
**AI SearchのエンドポイントとAPIキーは後に使いますので控えておいてください。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/b4c3a516-e996-1c1b-3f68-a9d41980bc67.png)
:::

### 4. インデックス
インデックスの設定をします。
今回は下記で設定します。
➃インデックス名：`addyourdata`
➄インデクサーのスケジュール：`Once`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/aa61bc7a-2506-f6e2-5966-355c0aae0a14.png)
※「➃インデックス名」はOn Your Data作成画面に名前を入れて保存すると「インデックス」の項目に自動で新規作成されます。

:::note info
**インデックスとは**
インデックスは、ユーザーがアップロードしたデータを効率的に検索可能な形式に変換するための構造です。具体的には、以下のような機能があります：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/c5021a59-e845-005b-de96-5b6d1aeaf1d5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/37ea5b12-8054-f338-23fa-b5c231f10594.png)
:::

:::note warn
**インデクサーとは**
インデックス作成にはインデクサーが使用されます。インデクサーは、指定されたデータソースから定期的に情報を取得し、変更があった場合にはインデックスを更新します。この機能により、最新の情報が常に反映されることが保証されます
ここでは下記が設定可能です。
Once   ・・・1 回
Hourly ・・・1 時間ごと
Daily  ・・・1 日ごと
:::
他は下記のように設定しました。
検索の種類：`キーワード`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/f5b19a40-d9ac-2aae-e20a-0fb3ded16fc1.png)

データ接続：`APIキー`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/f0edbf0a-5c17-0047-5c24-5e340ab32c5e.png)



全体を確認して保存をかけたらデプロイ出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/ef316d1b-e1a2-93f6-bbb4-8536faa5803e.png)

# 実際に試してみます
### 5. 実行してみる
画面で「HULFT Squareの稼働時間は？」と聞いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/57863e21-9dde-f948-25c2-2a95b77dcef9.png)

:::note info
[PDFファイル](https://www.hulft.com/application/files/3917/1141/3653/hulft-square_service_specifications_v6_20240124.pdf)の内容が読み込めていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/b4aff072-5569-cc9f-13bd-a52dfe0bb9fe.png)

:::

# コマンドで実行してみる

### 6. コマンドで実行してみる

APIでコマンドを使って実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/999d747c-5df2-219b-c2db-9ebfb24a1549.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/0e2013f7-b79c-1cfe-8900-76b6b3ef6ffa.png)

上記のサンプルコードは参考になりますが、そのままでは実行出来ません。
下記コードをお試しください。
```ruby:Windows PowerShell
$uri = "<➀YOUR_RESOURCE_NAME>/openai/deployments/<➁YOUR_DEPLOYMENT_NAME>/extensions/chat/completions?api-version=2023-06-01-preview"

$headers = @{
    "Content-Type: application/json" \
    "api-key: <➂YOUR_API_KEY>" \
    "chatgpt_url: <➃YOUR_RESOURCE_URL>" \
    "chatgpt_key: <➄YOUR_API_KEY>" \
}

$body = @{
    extensions = @()  # 必要に応じて適切な拡張機能を追加
    dataSources = @(
        @{
            type = "AzureCognitiveSearch"
            parameters = @{
                "endpoint": "'<➅YOUR_AZURE_COGNITIVE_SEARCH_ENDPOINT>'",
                "key": "'<➆YOUR_AZURE_COGNITIVE_SEARCH_KEY>'",
                "indexName": "'<➇YOUR_AZURE_COGNITIVE_SEARCH_INDEX_NAME>'"
            }
        }
    )
    messages = @(
        @{
            role = "user"
            content = "HULFT Squareの稼働時間は?"
        }
    )
    temperature = 0.7
    top_p = 0.95
    max_tokens = 800
    stop = $null
    stream = $false
}

$jsonBody = $body | ConvertTo-Json -Depth 10

$response = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body $jsonBody

# $responseを詳細に表示
$response | Format-List -Property *

# choicesキーから応答メッセージを抽出
$reply_message = $response.choices[0].messages | ForEach-Object { $_.content }
$reply_message
```



|プレースホルダー | 項目  | 説明 |
|---|---| ---|
|<➀YOUR_RESOURCE_NAME>|リソース名|チャットプレイグラウンドで出したサンプルコードに沿って設定してください。|
|<➁YOUR_DEPLOYMENT_NAME>|デプロイメント名| チャットプレイグラウンドで出したサンプルコードに沿って設定してください。|
|<➂YOUR_API_KEY>|APIキー（Content-Type）| 上記➀のAPIキーになります。|
|<➃YOUR_RESOURCE_URL>|リソースURL|「1．Azure OpenAI」でデプロイした「gpt-35-turbo-16k」のエンドポイントを使用ください。|
|<➄YOUR_API_KEY>|APIキー（chatgpt_key）|上記➃のキーになります。|
|<➅YOUR_AZURE_COGNITIVE_SEARCH_ENDPOINT>|Azure Cognitive Searchエンドポイント|「3．AI Search」のエンドポイントになります。|
|<➆YOUR_AZURE_COGNITIVE_SEARCH_KEY>|Azure Cognitive Searchキー|上記➅のキーになります。|
|<➇YOUR_AZURE_COGNITIVE_SEARCH_INDEX_NAME>|Azure Cognitive Searchインデックス名|「4. インデックス」で設定したインデックス名です。|

<➀YOUR_RESOURCE_NAME>と<➃YOUR_RESOURCE_URL>は設定するエンドポイントが似ていますがバージョンや、パスが若干異なるのでご注意ください。
※バージョンの[最新モデル](https://learn.microsoft.com/ja-jp/azure/ai-services/openai/reference)は公式ページからも確認出来ます。

:::note warn
「AI Search」の中で読み取った全てのデータの中から検索したい情報だけを「Azure OpenAI On Your Data」が回答してくれます。
実行すると1レコード目は「AI Search」のデータを吐き出し、2レコード目に「Azure OpenAI On Your Data」が欲しい情報を回答してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458288/14231269-92c4-1a90-4945-2a51571dc0ee.png)
※PDFの内容が長いので全体は移しませんが、「AI Search」がPDFの内容を読み取れていることが確認出来ます。
:::

# 最後に
最後までお読みいただき、ありがとうございます。

今回ご紹介した方法を用いることで、社内データを扱う際にBlobストレージに蓄積されているRAGから取得するため、社内データがAIの学習データとして蓄積される危険を回避し、安全にデータを活用できるのではないでしょうか。

個人的には、デプロイモデルのコスト体系の理解や、APIで実行する場合のエンドポイントの仕組みに苦労しました。Azure OpenAIは日々バージョンアップしているため、未知の部分も多いと感じます。しかし、本記事が皆様のAIに対する関心を高める一助になれば幸いです。

このブログでは、今後も様々なトピックや接続検証など、皆さんの参考になる記事を投稿していきたいと思います。どうぞお楽しみに！

それでは、またお会いしましょう！:raised_hand: