Azure OpenAI Service（GPT-4o）で構成図からBicepのコードを生成（RAGの利用）

今回、Azure OpenAI Service（GPT-4o）+RAGで構成図からBicepのコードを生成してみましたので、その内容を投稿します。

## 概要
### 試したこと
以下の以前の記事では、Azureの構成図を生成AIにインプットして、Bicepのコードを生成させることを試してみました。

https://qiita.com/meldmia/items/aa564ce760e044b0ba01

その結果、 誤りそうな部分をユーザプロンプトやシステムプロンプトで明示的に対応方法を指示することで、構成図からデプロイ可能なBicepのコードを1回の指示のみで生成することが確認できました。
ただ、毎回ユーザプロンプトで細かく指示するのは面倒なため、今回は、RAGを使ってこれをうまく解決できないかを試してみました。

対象とする構成は、前回と同じくAzure Container Appsを作成して、ログをBlob Storageに出力する構成です。
Container Appsはフロントエンド用とバックエンド用の2つを作成します。

![input.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/49f5e9b3-4ea9-df4c-aded-f5bea3195af2.png)

### 検証環境
- Azure OpenAI Service(GPT-4o)
- Azure AI Studio

## Bicepのコード生成時の注意点でRAGを実装
### RAGの実装手順
[前回の検証](https://qiita.com/meldmia/items/aa564ce760e044b0ba01)では、Azure Container AppsのBicepのコードを作成するときの注意点を、毎回ユーザプロンプトで入力する必要がありました。
今回は、この注意点をワードファイルにして、RAGを実装しました。その際、これだけではつまらないので、Azure App Serviceの場合の注意点も同じようにワードファイルに記載して、2つのファイルでRAGを実装することにしました。  

- 「ContainerApps作成時の注意点.docx」の内容  
  > Azure Container Appsを作成するBicepのコードを作成する際には、以下の6つのルールを必ず守ること。  
    1.リソースグループはデプロイコマンドで指定するように作成すること。  
    2."AppLogsConfiguration.Destination"は、azure-monitorにすること。  
    3.Container Appsのcpuで10 進数の値を指定する場合、 json() 関数を使用すること。  
    4.APIのバージョンがサポートされているバージョンか確認すること。  
    5.特に指定がない場合は、Container Appsは既定のイメージを利用して作成すること。  
    6.診断設定（リソースログの設定）でContainer Apps環境のログをストレージに出力するように設定すること。  

    ![word1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/c56fb27b-ce8a-8bb8-b444-f921c182a467.png)

- 「AppService作成時の注意点.docx」の内容  
:::note warn
こちらの内容は生成AIで作成したダミーの情報です。記載内容が技術的に正しいかどうかは確認していません。
:::
  > Azure App Serviceを作成するBicepのコードを作成する際には、以下の6つのルールを必ず守ること。  
   1.リソースグループはデプロイコマンドで指定するように作成すること。  
   2."AppServicePlan"を指定すること。  
   3.アプリケーション設定（App Settings）を適切に設定すること。  
   4.APIのバージョンがサポートされているバージョンか確認すること。  
   5.特に指定がない場合は、App Serviceは既定のランタイムスタックを利用して作成すること。  
   6.診断設定（リソースログの設定）でログをAzure Monitorに出力するように設定すること。  

   ![word2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/2434a4e1-35ed-ebb5-9128-2701226774ae.png)

上記の2つのワードファイルをAzure AI Studioのチャットプレイグラウンドの「データを追加する」からアップロードしてRAGを実装しました（「Azure OpenAI On Your Data」の機能）。
- 「データを追加する」から、
![onyourdata1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/69edb509-108b-3140-8ddb-cbe664ee4864.png)
- 2つのワードファイルを追加
![onyourdata2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/968f4f59-a967-6ec6-f3dd-a8e041b0ac8b.png)

### RAGの実装結果
RAGの実装結果を確認します。  
Container Appsについて聞いたときは、「ContainerApps作成時の注意点.docx」の内容が、App Serviceについて聞いたときは、「AppService作成時の注意点.docx」の内容が正しく参照できています。  
- Container Appsについて質問した結果  
![onyourdatachat1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/7e8e4cb2-bb44-59a5-fdaf-fb1004fdd777.png)
- App Serviceについて質問した結果
![onyourdatachat2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/f00759ca-f757-4bad-6523-0a098ef0c766.png)

しかし、この「Azure OpenAI On Your Data」機能でRAGを実装すると、チャットプレイグラウンドで、画像等のファイルを添付してチャットができなくなることがわかりました。 

:::note warn
2024年8月時点の動作です。正確な情報は見つけられなかったため、環境や手順によっては動作が異なるかもしれません。
:::
- RAGを実装していないチャットプレイグラウンド  
ファイル添付ができます。
![chat_file1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/46861e78-9035-a6f0-b369-ae4135bc2fdd.png)
- 「Azure OpenAI On Your Data」機能でRAGを実装した後のチャットプレイグラウンド  
ファイル添付ができなくなっています。
![chat_file2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/128e5ac0-6cf1-1034-0aaf-92efc885c037.png)

本当は、[前回の検証](https://qiita.com/meldmia/items/aa564ce760e044b0ba01)と同じく、ここで構成図を添付して、構成図から直接Azure Bicepのコードを生成させたかったのですが、ちょっと簡単にはできそうになかったため、今回はそれはあきらめて、以降の方法で動作を確認しました。  

:::note info
この辺は、Azureの今後の機能更新にも期待です。
:::

## Bicepのコード生成の確認
前述の通り、チャットプレイグラウンドで構成図のファイルを添付してチャットができなかったため、今回は、以下の方法で動作を確認することにしました。

1. 「RAGを実装していないチャットプレイグラウンド」で生成AIに構成図を文章で説明させる
1. 1.で得られた情報を「RAGを実装したチャットプレイグラウンド」にインプットし、Azure Bicepのコードを生成する

### 「RAGを実装していないチャットプレイグラウンド」で生成AIに構成図を文章で説明させる。
Azure AI StudioのRAGを実装していないチャットプレイグラウンドでGPT-4oのモデルを利用して、以下のように、ユーザプロンプトで、構成図を添付して指示しました。
> この図のAzureの構成が、図がなくても伝わるように文章で説明してください。  

実際の入力画面は以下の通りです。
![noragchat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/e287390d-d390-b641-83e9-4846eed10d9f.png)

以下の通り図の説明が作成できました。  
> このAzureの構成は以下のようになっています：  
1.Azure上に「Container Apps環境」が存在します。  
2.Container Apps環境内には2つのアプリケーションがあります：  
　・「frontendapp0603」  
　・「backendapp0603」  
3.「frontendapp0603」はHTTPSを通じてアプリ利用者と通信します。  
4.「frontendapp0603」と「backendapp0603」は内部通信を行います。  
5.「backendapp0603」はリソースログを「logblob0603」に保存します。  
6.この構成はクイックスタートイメージを基に作成されています。  
この構成により、利用者はHTTPSを通じてフロントエンドアプリケーションにアクセスし、フロントエンドアプリケーションはバックエンドアプリケーションと連携し、バックエンドアプリケーションはリソースログを保存する仕組みになっています。

リソースログの出力については、「backendapp0603」のみでなく、Container Apps環境全体のリソースログを出力させる構成を意図していたので、少し解釈が間違っているようですが、他は正しく認識されています。

### 「RAGを実装したチャットプレイグラウンド」でAzure Bicepのコードを生成する。

前述の項目5を正しく修正し、以下の内容をRAGを実装したチャットプレイグラウンドで指示しました。
> 以下の構成をAzureにデプロイできるAzure Bicepのコードを注意点を考慮して作成してください。          
\-----            
1.Azure上に「Container Apps環境」が存在します。            
2.Container Apps環境内には2つのアプリケーションがあります：            
　・「frontendapp0603」            
　・「backendapp0603」            
3.「frontendapp0603」はHTTPSを通じてアプリ利用者と通信します。            
4.「frontendapp0603」と「backendapp0603」は内部通信を行います。            
5.「Container Apps環境」のリソースログは「logblob0603」に出力します。            
6.この構成はクイックスタートイメージを基に作成されています。            
この構成により、利用者はHTTPSを通じてフロントエンドアプリケーションにアクセスし、フロントエンドアプリケーションはバックエンドアプリケーションと連携します。

なお、システムメッセージ（システムプロンプト）には念のため以下を設定しました。
> あなたは、作成対象のAzureリソースの作成時の注意点に全て従ってAzure Bicepのコードを生成します。注意点はRAG化されています。

結果は以下の通りです。
![result1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/9bbb6129-7ba5-7ecc-4cfa-66a21369c1ea.png)
![result2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835827/1b12709d-a352-ac43-d8c3-d566bbabb127.png)

「ContainerApps作成時の注意点.docx」の内容をふまえてコードを生成してくれています。  

:::note warn
ただし、実際には、毎回意図した動作をしてくれるとは限りません。
:::

### 生成されたBicepのコード
結果として後述のBicepのコードが生成されました。 

なお、このコードはデプロイはできますが、frontendapp0603が正常には動作しません。
targetPort: 443と設定されていますが、Container Appsのクイックスタートイメージでは、targetPort: 80と設定する必要があります。外部通信はHTTPS通信という設定を指示しているのでなかなか難しいのかもしれません。この点も注意点として追加すればうまくいくかもしれません。  
なお、今回、何回か再生成をしてみましたが、残念ながら1回の指示のみですべて正しいコードを出力させることはできませんでした。

:::note warn
このコードは、生成AIが作成したものです。毎回同じコードが生成されるとは限りません。
:::

<details><summary>生成されたBicepのコード</summary>

```bicep  
param location string = resourceGroup().location  
param logStorageAccountName string = 'logblob0603'  
  
resource containerAppEnv 'Microsoft.App/managedEnvironments@2022-03-01' = {  
  name: 'containerAppEnv0603'  
  location: location  
  properties: {  
    appLogsConfiguration: {  
      destination: 'azure-monitor'  
    }  
  }  
}  
  
resource logStorageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' = {  
  name: logStorageAccountName  
  location: location  
  sku: {  
    name: 'Standard_LRS'  
  }  
  kind: 'StorageV2'  
}  
  
resource frontendApp 'Microsoft.App/containerApps@2022-03-01' = {  
  name: 'frontendapp0603'  
  location: location  
  properties: {  
    managedEnvironmentId: containerAppEnv.id  
    configuration: {  
      ingress: {  
        external: true  
        targetPort: 443  
        transport: 'auto'  
      }  
    }  
    template: {  
      containers: [  
        {  
          name: 'frontendapp0603'  
          image: 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'  
          resources: {  
            cpu: json('0.5')  
            memory: '1.0Gi'  
          }  
        }  
      ]  
    }  
  }  
}  
  
resource backendApp 'Microsoft.App/containerApps@2022-03-01' = {  
  name: 'backendapp0603'  
  location: location  
  properties: {  
    managedEnvironmentId: containerAppEnv.id  
    configuration: {  
      ingress: {  
        external: false  
      }  
    }  
    template: {  
      containers: [  
        {  
          name: 'backendapp0603'  
          image: 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'  
          resources: {  
            cpu: json('0.5')  
            memory: '1.0Gi'  
          }  
        }  
      ]  
    }  
  }  
}  
  
resource diagnosticSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {  
  name: 'containerAppEnvDiagnostics'  
  scope: containerAppEnv  
  properties: {  
    storageAccountId: logStorageAccount.id  
    logs: [  
      {  
        category: 'ContainerAppConsoleLogs'  
        enabled: true  
        retentionPolicy: {  
          enabled: false  
          days: 0  
        }  
      }  
    ]  
  }  
}  

```  
</details>
<br>

### デプロイ結果

前述のAzure Bicepのコードで、frontendapp0603のtargetPortを80に修正し、デプロイしました。
結果は、[前回のデプロイ結果](https://qiita.com/meldmia/items/aa564ce760e044b0ba01#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E7%B5%90%E6%9E%9C)と同じ環境ができました。

## まとめ
今回は、Azure OpenAI Service（GPT-4o）で構成図からBicepのコードを生成するという内容について、RAGを活用する方法を検証しました。  

[前回の検証](https://qiita.com/meldmia/items/aa564ce760e044b0ba01)では、ユーザプロンプトで生成時の注意点を毎回入力していました。  
今回は、注意点の情報でRAGを実装することで、自動で必要な注意点を考慮してBicepのコードを生成してくれることが確認できました。

意図したコードを生成してくれるときもあれば、そうでないときも多いというのが現状ですが、生成されたコードに人が手を加える前提であれば便利ではないかと思います。