Azure OpenAI を使って自然言語で Mermaid のコードを生成する方法を試してみました。その過程で得られた知見やコツをブログにまとめてみます。
Mermaid とは、Markdown ライクで図を描くことができるツールです。しかし、文法を覚えるのは面倒です。
そこで、Azure OpenAI に書かせてみました。
Azure OpenAI の使い方は先日レビューしたこちらの本や、様々なブログ記事があるので今回はシステム メッセージ (システム プロンプト) をどのように工夫したかをメモしていきます
※温度などのパラーメータは今回は扱いません
AOAI のドーナツ本の感想を言い隊 – クラウドを勉強し隊
目指す出力
サブスクリプションや、リソースグループ、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

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

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