Claude 3.5 Sonnetを使ってmermaid2drawioを試す

# 記事の概要

LLMが広まり、LLMが取り扱える図の表現方法として、mermaid記法も広まった。

https://qiita.com/kongo-jun/items/c446898ac301b62a5934

ただ、それに伴い、mermaid記法を人が修正するというのは、少し癖がある作業に感じている。

そこで、mermaid記法の図をdrawioの図に変換し、GUI操作で図を更新する手順を試す。

LLMは現状、Claude 3.5 Sonnet一択。
回数制限はあるが、無料で使えるので試してみてください。

https://claude.ai/

PowerPoint/Excelについても似たような手順を紹介していますが、見なくていいです。

https://qiita.com/kongo-jun/items/f891f048ac92ffaf8589

動画でも解説してます。

https://youtu.be/S0qnjUkdilI

# 環境構築

■VSCodeインストール

https://www602.math.ryukoku.ac.jp/Prog1/vscode-win.html

■VSCode拡張機能インストール

VSCodeを起動し、以下のキャプチャの一番下のアイコンを押下する。
![拡張機能.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/9d2e02b1-8a94-e6fa-42cc-7a480e455268.png)

検索窓で「Draw.io Integration」を検索し、インストールする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/290acf02-96f1-7c4e-5775-0acae6257102.png)

## mermaid2drawio

### プロンプト

Claudeで以下のようなプロンプトを実行する。
できるだけ、画像と一緒に入力した方が精度が上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/15f8a4a2-5412-8d13-c7cc-59349ced3c25.png)

以下がプロンプトの全体像。

```md
画像は以下のmermaid記法で作成された図です。この図をdrawioで出力するためのxmlを作成してください。
コードはコピペできるように全て出力してください。
エラーを出したら罰金です。
```mermaid
graph TB;
    subgraph local
        Dify
        Weaviate
        venv
    end

    subgraph groq[Groq Cloud]
        llama3[llama 3]
    end

    subgraph Dify[Dify Docker]
        q[質問]
        vector[ベクトル検索]
        RAG[RAG]
        output[回答]
    end

    subgraph Weaviate[Weaviate Docker]
        vectorDB
    end

    subgraph venv
        flask
    end

    q --> vector
    vector --> RAG
    RAG --> output

    vector --> |HTTPリクエスト|flask
    flask --> |ベクトル検索|vectorDB
    vectorDB --> flask
    flask --> vector

    RAG --> |テキスト生成|llama3
    llama3 --> RAG
   ```
   

以下が、mermaid記法の図。

```mermaid
graph TB;
    subgraph local
        Dify
        Weaviate
        venv
    end

    subgraph groq[Groq Cloud]
        llama3[llama 3]
    end

    subgraph Dify[Dify Docker]
        q[質問]
        vector[ベクトル検索]
        RAG[RAG]
        output[回答]
    end

    subgraph Weaviate[Weaviate Docker]
        vectorDB
    end

    subgraph venv
        flask
    end

    q --> vector
    vector --> RAG
    RAG --> output

    vector --> |HTTPリクエスト|flask
    flask --> |ベクトル検索|vectorDB
    vectorDB --> flask
    flask --> vector

    RAG --> |テキスト生成|llama3
    llama3 --> RAG

```

### LLMの出力

以下のような形式で出力される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/aa837fa8-1cb8-98b0-49b8-160ca81d0e47.png)

途中で途切れる場合は、「続きを出力」とかで続きを出力させると、２ページ目として出力される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/ec461522-abbe-4687-5ca3-8dc3a366c14e.png)

### VScodeで確認

「.xml」拡張子のファイルに、LLMが出力したxmlを保存する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/b35a2095-919f-e2f9-47f2-fc3f432f6244.png)

その後、拡張子を「.drawio」に変更することで、drawioの図が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/6335ed3e-4e8c-8c29-76e6-9e0c5bed354d.png)

一応、出力されたxmlの全容。

```xml
<mxfile host="app.diagrams.net" modified="2023-08-28T12:00:00.000Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" etag="123456789" version="14.9.8" type="device">
  <diagram id="prtHgNgQTEPvFCAcTncT" name="Page-1">
    <mxGraphModel dx="1422" dy="794" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
      <root>
        <mxCell id="0" />
        <mxCell id="1" parent="0" />
        <mxCell id="2" value="local" style="swimlane;startSize=20;horizontal=1;containerType=tree;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};" vertex="1" parent="1">
          <mxGeometry x="40" y="40" width="480" height="360" as="geometry" />
        </mxCell>
        <mxCell id="3" value="Dify Docker" style="swimlane;startSize=20;horizontal=1;containerType=tree;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};" vertex="1" parent="2">
          <mxGeometry x="20" y="40" width="280" height="300" as="geometry" />
        </mxCell>
        <mxCell id="4" value="質問" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="3">
          <mxGeometry x="20" y="40" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="5" value="ベクトル検索" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="3">
          <mxGeometry x="20" y="120" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="6" value="RAG" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="3">
          <mxGeometry x="20" y="200" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="7" value="回答" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="3">
          <mxGeometry x="160" y="200" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="3" source="4" target="5">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="3" source="5" target="6">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="3" source="6" target="7">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="11" value="Weaviate Docker" style="swimlane;startSize=20;horizontal=1;containerType=tree;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};" vertex="1" parent="2">
          <mxGeometry x="320" y="40" width="140" height="100" as="geometry" />
        </mxCell>
        <mxCell id="12" value="vectorDB" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="11">
          <mxGeometry x="20" y="40" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="13" value="venv" style="swimlane;startSize=20;horizontal=1;containerType=tree;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};" vertex="1" parent="2">
          <mxGeometry x="320" y="160" width="140" height="100" as="geometry" />
        </mxCell>
        <mxCell id="14" value="flask" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="13">
          <mxGeometry x="20" y="40" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="2" source="5" target="14">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="300" y="180" />
              <mxPoint x="300" y="220" />
            </Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="16" value="HTTPリクエスト" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="15">
          <mxGeometry x="0.2" y="2" relative="1" as="geometry">
            <mxPoint as="offset" />
          </mxGeometry>
        </mxCell>
        <mxCell id="17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="2" source="14" target="12">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="18" value="ベクトル検索" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="17">
          <mxGeometry x="-0.2" y="1" relative="1" as="geometry">
            <mxPoint as="offset" />
          </mxGeometry>
        </mxCell>
        <mxCell id="19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="2" source="14" target="5">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="280" y="220" />
              <mxPoint x="280" y="190" />
            </Array>
          </mxGeometry>
        </mxCell>
        <mxCell id="20" value="Groq Cloud" style="swimlane;startSize=20;horizontal=1;containerType=tree;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};" vertex="1" parent="1">
          <mxGeometry x="560" y="40" width="140" height="100" as="geometry" />
        </mxCell>
        <mxCell id="21" value="llama 3" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="20">
          <mxGeometry x="20" y="40" width="100" height="40" as="geometry" />
        </mxCell>
        <mxCell id="22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="21">
          <mxGeometry relative="1" as="geometry" />
        </mxCell>
        <mxCell id="23" value="テキスト生成" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="22">
          <mxGeometry x="-0.2" y="1" relative="1" as="geometry">
            <mxPoint as="offset" />
          </mxGeometry>
        </mxCell>
        <mxCell id="24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="21" target="6">
          <mxGeometry relative="1" as="geometry">
            <Array as="points">
              <mxPoint x="540" y="110" />
              <mxPoint x="540" y="310" />
            </Array>
          </mxGeometry>
        </mxCell>
      </root>
    </mxGraphModel>
  </diagram>
</mxfile>
```

最終成果物としては、少し修正が必要な状態だが、１から作成するよりは、かなり工数が削減できる。

## drawio2mermaid

### プロンプト

こんな感じのプロンプトで、mermaid記法に戻してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/ec81fc33-f6d7-e5f5-9a34-f713bf0815f0.png)

以下のような出力となった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/45f026a8-8778-53d9-d1b9-a5a0148bc4f2.png)

```
graph TB
    subgraph local
        subgraph "Dify Docker"
            A[質問] --> B[ベクトル検索]
            B --> C[RAG]
            C --> D[回答]
        end
        
        subgraph "Weaviate Docker"
            E[vectorDB]
        end
        
        subgraph venv
            F[flask]
        end
        
        B -->|HTTPリクエスト| F
        F -->|ベクトル検索| E
        F --> B
    end
    
    subgraph "Groq Cloud"
        G[llama 3]
    end
    
    C -->|テキスト生成| G
    G --> C
```

mermaidを図として表示すると、以下の状態。

```mermaid
graph TB
    subgraph local
        subgraph "Dify Docker"
            A[質問] --> B[ベクトル検索]
            B --> C[RAG]
            C --> D[回答]
        end
        
        subgraph "Weaviate Docker"
            E[vectorDB]
        end
        
        subgraph venv
            F[flask]
        end
        
        B -->|HTTPリクエスト| F
        F -->|ベクトル検索| E
        F --> B
    end
    
    subgraph "Groq Cloud"
        G[llama 3]
    end
    
    C -->|テキスト生成| G
    G --> C
```

可逆性のある結果となった。


# その他

以下も基本mermiadからxmlを一発で出力。

### AWSの画像も出力可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/a48762d6-f6be-36eb-fef4-4ac33180bd76.png)

### スケジュールも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/c680277b-1918-2943-b7b6-c59cd605d753.png)


### ERDも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/04fad2c6-109b-64aa-bed7-e9ea4f8a5d0c.png)


# 結果

正直、精度は取り扱う図にもよるが、例え修正が必要でも、１から作るよりは圧倒的に楽になることは想像できる。
図の複雑さにも左右されるが、mermaidとの可逆性があることも評価が高い。