JavaScriptを有効にしてください

Azure OpenAI を使って Mermaid を使った Azure 構成図を作り隊

 ·   7 分で読めます  ·   Kento

Azure OpenAI を使って自然言語で Mermaid のコードを生成する方法を試してみました。その過程で得られた知見やコツをブログにまとめてみます。

Mermaid とは、Markdown ライクで図を描くことができるツールです。しかし、文法を覚えるのは面倒です。

そこで、Azure OpenAI に書かせてみました。
Azure OpenAI の使い方は先日レビューしたこちらの本や、様々なブログ記事があるので今回はシステム メッセージ (システム プロンプト) をどのように工夫したかをメモしていきます
※温度などのパラーメータは今回は扱いません

AOAI のドーナツ本の感想を言い隊 – クラウドを勉強し隊

Azure OpenAI Serviceの日本語記事まとめ

目指す出力

サブスクリプションや、リソースグループ、Vnet など図の中で箱として扱うものはサブグラフとして表現します
Vnet Peering や VPN, Private Link などは矢印で関係性を表現します
色分けして見やすくするために以下のように表示します

要素
ネットワーク系
VM や NIC (Private Endpoint) オレンジ
PaaS

例として ハブ&スポークのトポロジでは以下のように表現します

---
title: ハブ&スポークの例
---
graph TB;
 
%%グループとサービス
subgraph hub_Vnet[hub-Vnet]
end

subgraph Spoke1["Spoke 1"]
end

subgraph Spoke2["Spoke 2"]
end

subgraph Spoke3["Spoke 3"]
end

 
%%サービス同士の関係
hub_Vnet <-- "ピアリング" --> Spoke1
hub_Vnet <-- "ピアリング" --> Spoke2
hub_Vnet <-- "ピアリング" --> Spoke3

 
%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class hubsub,sub1,sub2,sub3 subG
 
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hub_Vnet,Spoke1,Spoke2,Spoke3 VnetG

この図は mermaid では以下のように記述しています

---
title: ハブ&スポークの例
---
graph TB;
 
%%グループとサービス
subgraph hub_Vnet[hub-Vnet]
end

subgraph Spoke1["Spoke 1"]
end

subgraph Spoke2["Spoke 2"]
end

subgraph Spoke3["Spoke 3"]
end

 
%%サービス同士の関係
hub_Vnet <-- "ピアリング" --> Spoke1
hub_Vnet <-- "ピアリング" --> Spoke2
hub_Vnet <-- "ピアリング" --> Spoke3

 
%%サブグラフのスタイル 
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hub_Vnet,Spoke1,Spoke2,Spoke3 VnetG

ここに VM や Storage Account (PaaS) サブスクリプションが追加されるとこのようになります

---
title: ハブ&スポークの例 | VM, PaaS, Subscription の追加
---
graph TB;
 
%%グループとサービス
subgraph hubsub["Hub Subscription"]
    subgraph hub_Vnet[hub-Vnet]
        VM1("VM")
    end
end

subgraph sub1["Spoke Subscription"]
    subgraph Spoke1["Spoke 1"]
    end
    ST1{{"fa:fa-folder Storage Account"}}
end

subgraph sub2["Spoke Subscription"]
    subgraph Spoke2["Spoke 2"]
    end
end

subgraph sub3["Spoke Subscription"]
    subgraph Spoke3["Spoke 3"]
    end
end

 
%%サービス同士の関係
hub_Vnet <-- "ピアリング" --> Spoke1
hub_Vnet <-- "ピアリング" --> Spoke2
hub_Vnet <-- "ピアリング" --> Spoke3

 
%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class hubsub,sub1,sub2,sub3 subG
 
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hub_Vnet,Spoke1,Spoke2,Spoke3 VnetG

%%ノードのスタイル
classDef SCP fill:#e83,color:#fff,stroke:none
class VM1,VM2 SCP

classDef PaaSG fill:#46d,color:#fff,stroke:#fff
class ST1 PaaSG

---
title: ハブ&スポークの例 | VM, PaaS, Subscription の追加
---
graph TB;
 
%%グループとサービス
subgraph hubsub["Hub Subscription"]
    subgraph hub_Vnet[hub-Vnet]
        VM1("VM")
    end
end

subgraph sub1["Spoke Subscription"]
    subgraph Spoke1["Spoke 1"]
    end
    ST1{{"fa:fa-folder Storage Account"}}
end

subgraph sub2["Spoke Subscription"]
    subgraph Spoke2["Spoke 2"]
    end
end

subgraph sub3["Spoke Subscription"]
    subgraph Spoke3["Spoke 3"]
    end
end

 
%%サービス同士の関係
hub_Vnet <-- "ピアリング" --> Spoke1
hub_Vnet <-- "ピアリング" --> Spoke2
hub_Vnet <-- "ピアリング" --> Spoke3

 
%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class hubsub,sub1,sub2,sub3 subG
 
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hub_Vnet,Spoke1,Spoke2,Spoke3 VnetG

%%ノードのスタイル
classDef SCP fill:#e83,color:#fff,stroke:none
class VM1 SCP

classDef PaaSG fill:#46d,color:#fff,stroke:#fff
class ST1 PaaSG

このような図を Azure OpenAI を使って作成するのが今回の目的です

システム メッセージに入れる内容

システムメッセージには以下の内容を入れます

あなたは Mermaid を使って Azure の構成図を書くことが得意です。
サブスクリプションや、リソースグループ、Vnet など図の中で箱として扱うものは subgraph として表現します。
Vnet Peering や VPN, Private Link などは矢印で関係性を表現します。
色分けして見やすくするために以下のように表示します。
- サブスクリプション:fill:none,color:#345,stroke:#345
- ネットワーク関連:fill:none,color:#0a0,stroke:#0a0
- VM、Private Endpoint:fill:#e83,color:#fff,stroke:none
- PaaS:fill:#46d,color:#fff,stroke:#fff
ユーザーからのリクエスに対して 上記のルールに従って Mermaid のフローチャートで回答を出力してください。
リソースグループやサブスクリプションは指定された場合のみ回答に含めて、それ以外の場合は回答に含めないでください。
インデント以外の、余計な半角スペースは入れないでください。

例の部分では上記に入れた例を書いておきます

例1:ハブ&スポークの構成

ユーザー

ハブ&スポークの構成です。
スポークは3つあります。

アシスタント

---
title: ハブ&スポークの構成
---
graph TB;
 
%%グループとサービス
subgraph hub_Vnet[hub-Vnet]
end

subgraph Spoke1["Spoke 1"]
end

subgraph Spoke2["Spoke 2"]
end

subgraph Spoke3["Spoke 3"]
end

 
%%サービス同士の関係
hub_Vnet <-- "ピアリング" --> Spoke1
hub_Vnet <-- "ピアリング" --> Spoke2
hub_Vnet <-- "ピアリング" --> Spoke3

 
%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class hubsub,sub1,sub2,sub3 subG
 
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hub_Vnet,Spoke1,Spoke2,Spoke3 VnetG

例2:ハブ&スポークの構成にいくつかコンポーネントを追加

ユーザー

ハブ&スポークの構成です。
スポークは3つあります。
ハブとスポークはすべて異なるサブスクリプションにデプロイされています。
ハブには VM が1台あります。
1つのスポーク用サブスクリプションには Storage Account があります。

アシスタント

---
title: ハブ&スポークの例 | VM, PaaS, Subscription の追加
---
graph TB;
 
%%グループとサービス
subgraph hubsub["Hub Subscription"]
    subgraph hub_Vnet[hub-Vnet]
        VM1("VM")
    end
end

subgraph sub1["Spoke Subscription"]
    subgraph Spoke1["Spoke 1"]
    end
    ST1{{"fa:fa-folder Storage Account"}}
end

subgraph sub2["Spoke Subscription"]
    subgraph Spoke2["Spoke 2"]
    end
end

subgraph sub3["Spoke Subscription"]
    subgraph Spoke3["Spoke 3"]
    end
end

 
%%サービス同士の関係
hub_Vnet <-- "ピアリング" --> Spoke1
hub_Vnet <-- "ピアリング" --> Spoke2
hub_Vnet <-- "ピアリング" --> Spoke3

 
%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class hubsub,sub1,sub2,sub3 subG
 
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hub_Vnet,Spoke1,Spoke2,Spoke3 VnetG

%%ノードのスタイル
classDef SCP fill:#e83,color:#fff,stroke:none
class VM1 SCP

classDef PaaSG fill:#46d,color:#fff,stroke:#fff
class ST1 PaaSG

例3:サブスクリプション構成

ユーザー

サブスクリプションとリソースグループの階層構成を出力してください。
サブスクリプションは1つ。リソースグループは3つです。
それぞれのリソースグループにはリソースが2つ含まれています。

アシスタント

---
title: サブスクリプション全体構成
---
graph TD
sub1[サブスクリプション] --> rg1[リソースグループ1]
sub1 --> rg2[リソースグループ2]
sub1 --> rg3[リソースグループ3]
rg1 --> r1[リソース1]
rg1 --> r2[リソース2]
rg2 --> r3[リソース3]
rg2 --> r4[リソース4]
rg3 --> r5[リソース5]
rg3 --> r6[リソース6]

試してみる

実際にいくつか試してみました。

検証1

ユーザー

ハブ&スポークの構成。

回答

---  
title: ハブ&スポークの構成  
---  
   
graph TB;  
   
%%グループとサービス  
subgraph hubsub["Hub Subscription"]  
    subgraph hubRG["Hub Resource Group"]  
        hubVnet("Hub VNet")  
        hubVM("Hub VM")  
    end  
end  
   
subgraph spokeSub1["Spoke 1 Subscription"]  
    subgraph spokeRG1["Spoke 1 Resource Group"]  
        spoke1Vnet("Spoke 1 VNet")  
        spoke1VM("Spoke 1 VM")  
    end  
end  
   
subgraph spokeSub2["Spoke 2 Subscription"]  
    subgraph spokeRG2["Spoke 2 Resource Group"]  
        spoke2Vnet("Spoke 2 VNet")  
        spoke2VM("Spoke 2 VM")  
    end  
end  
   
subgraph spokeSub3["Spoke 3 Subscription"]  
    subgraph spokeRG3["Spoke 3 Resource Group"]  
        spoke3Vnet("Spoke 3 VNet")  
        spoke3VM("Spoke 3 VM")  
    end  
end  
  
   
%%サービス同士の関係  
hubVnet <-- "ピアリング" --> spoke1Vnet  
hubVnet <-- "ピアリング" --> spoke2Vnet  
hubVnet <-- "ピアリング" --> spoke3Vnet  
  
   
%%サブグラフのスタイル  
classDef subG fill:none,color:#345,stroke:#345  
class hubsub,spokeSub1,spokeSub2,spokeSub3 subG  
   
classDef VnetG fill:none,color:#0a0,stroke:#0a0  
class hubVnet,spoke1Vnet,spoke2Vnet,spoke3Vnet VnetG  
   
%%ノードのスタイル  
classDef SCP fill:#e83,color:#fff,stroke:none  
class hubVM, spoke1VM, spoke2VM, spoke3VM SCP
portal01
検証1 の実行例:

mermaid で出力

最後の行に余計な半角スペースがあったりするので、そのまま使うというわけにはいきませんが、少し手直しした内容が下になります
Vnet の外に VM が存在しているので多少の修正は必要そうですが、下書きとしては十分です

---  
title: ハブ&スポークの構成  
---  

graph TB;

%%グループとサービス
subgraph hubsub["Hub Subscription"]
    subgraph hubRG["Hub Resource Group"]
        hubVnet("Hub VNet")
        hubVM("Hub VM")
    end
end

subgraph spokeSub1["Spoke 1 Subscription"]
    subgraph spokeRG1["Spoke 1 Resource Group"]
        spoke1Vnet("Spoke 1 VNet")
        spoke1VM("Spoke 1 VM")
    end
end

subgraph spokeSub2["Spoke 2 Subscription"]
    subgraph spokeRG2["Spoke 2 Resource Group"]
        spoke2Vnet("Spoke 2 VNet")
        spoke2VM("Spoke 2 VM")
    end
end

subgraph spokeSub3["Spoke 3 Subscription"]
    subgraph spokeRG3["Spoke 3 Resource Group"]
        spoke3Vnet("Spoke 3 VNet")
        spoke3VM("Spoke 3 VM")
    end
end 


%%サービス同士の関係
hubVnet <-- "ピアリング" --> spoke1Vnet
hubVnet <-- "ピアリング" --> spoke2Vnet
hubVnet <-- "ピアリング" --> spoke3Vnet


%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class hubsub,spokeSub1,spokeSub2,spokeSub3 subG
   
classDef VnetG fill:none,color:#0a0,stroke:#0a0
class hubVnet,spoke1Vnet,spoke2Vnet,spoke3Vnet VnetG
   
%%ノードのスタイル
classDef SCP fill:#e83,color:#fff,stroke:none
class hubVM,spoke1VM,spoke2VM,spoke3VM SCP

検証2

ユーザー

外部ロードバランサーのバックエンドに VM が3台。
VM は同じ VNet にデプロイされています。
外部ロードバランサーにはパブリック IP アドレスが紐づいています。

回答

graph TB;

%%グループとサービス
subgraph VNet["VNet"]
VM1("VM")
VM2("VM")
VM3("VM")
end

subgraph LB["Load Balancer"]
LB1("External Load Balancer")
PIP1("Public IP")
end

%%サービス同士の関係
VM1 --> LB1
VM2 --> LB1
VM3 --> LB1
LB1 --> PIP1

%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class VNet, LB subG

classDef VMG fill:#e83,color:#fff,stroke:none
class VM1, VM2, VM3 VMG

classDef LBG fill:#0a0,color:#fff,stroke:none
class LB1, PIP1 LBG
portal01
検証2 の実行例:

mermaid で出力

同じく半角スペースの修正をしたものがこちらになります
ロードバランサーの箱が少し余計な気がしますが、こちらも下書きとしては十分なレベルです

--- 
title: 外部ロードバランサーの構成
---
graph TB;

%%グループとサービス
subgraph VNet["VNet"]
    VM1("VM")
    VM2("VM")
    VM3("VM")
end

subgraph LB["Load Balancer"]
    LB1("External Load Balancer")
    PIP1("Public IP")
end

%%サービス同士の関係
VM1 --> LB1
VM2 --> LB1
VM3 --> LB1
LB1 --> PIP1


%%サブグラフのスタイル
classDef subG fill:none,color:#345,stroke:#345
class VNet,LB subG
   
classDef VMG fill:#e83,color:#fff,stroke:none
class VM1,VM2,VM3 VMG
   
classDef LBG fill:#0a0,color:#fff,stroke:none
class LB1,PIP1 LBG

まとめ

Azure OpenAI を使って mermaid を出力できるシステム メッセージを考えてみました
下書きとしては十分なレベルが出力できました
これを使うことで、ブログの執筆スピードも上がると嬉しいなーと思ってます

参考

共有

Kento
著者
Kento
2020年に新卒で IT 企業に入社. インフラエンジニア(主にクラウド)として活動中