MarkdownAIによるAIを用いたジェネレーティブアートの生成ツール

# はじめに
MarkdownAIというサービスを利用して、Webページの背景となりそうなジェネレーティブアートを生成してくれるサイトを制作してみました。

https://mdown.ai/content/3637e85d-564e-4edb-bef7-47d3ccdcd426

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/bd9b6dd7-57ea-51ff-7b78-f9b8d17e6e58.png)

上記のWebページにアクセスして数十秒ほど（10秒から1分くらいの幅があります）経過すると、画面の中央にアートが描画されます。

アートの内容は [Generate] ボタンを押して再びしばらく待機すると、変更されます。是非、様々なアートを鑑賞するような感覚でお楽しみください。

本記事では、上記のWebページの操作方法とおおまかな開発手順、MarkdownAIに対する所感についてまとめています。生成AIを導入したWebページ開発をされたい方はご参考ください。

# 制作したサイトについて
## ジェネレーティブアートとは？
ジェネレーティブアートは、アルゴリズムやコンピュータプログラムによって制作される作品のことです。

<div style="display: flex; justify-content: space-around;">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/749d220a-5ef6-1660-690e-ddceb2b063f4.jpeg" alt="Image 1" width="30%;">
  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/c56f4192-7706-1d37-06b0-3fa8955d917a.jpeg" alt="Image 2" width="30%;">
</div>

静止画だけでなく、次のようなアニメーションがついているものもあります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/12c5c3f8-3b72-bc16-c0ea-1e0aac0c663e.gif" alt="Image 2" width="50%">


宣伝: もし、私が制作したものにご興味をお持ちでしたら、次のページをご鑑賞ください。

https://openprocessing.org/user/384938?view=sketches&o=10

## 操作方法
### 基本操作
1. Webページにアクセスしてしばらくするとと、アートが生成されます。
1. 生成されたアートについて、[Description]ボタンを押すと、説明文が表示されます。
1. [Generate]ボタンを押すと、新たにアートが生成されます。

### 詳細な操作
#### アートの生成
Webページ中央にある[Good]ボタンおよび[Bad]ボタンを押すと、次の回答にフィードバックされます。AIに対して、[Good]ボタンを押すと回答が良質であったこと、[Bad]ボタンを押すと回答が期待したものではなかったことを教えることができます。

また、「Input more points」と記載されているテキストボックスに、AIに生成してほしいアートの特徴を指定することができます。いくつかの例を次に示します。

- 「インベーダーゲームを描いて。」

キーボードの矢印キーで左右の移動、Spaceキーで弾を発射することができます。

https://openprocessing.org/sketch/2482825

- 「3Dのスケッチを描いて。」

https://openprocessing.org/sketch/2482841

- 「流体シミュレーションを描いて。」

https://openprocessing.org/sketch/2482882


#### ソースコードの再利用
[Code]ボタンを押すと、[p5.js（後述）](#p5js)でアートを描画するソースコードが表示されます。表示されたソースコードをコピーして、Webエディタにペーストすると、リアルタイムなスケッチの編集、保存（アカウントが必要です）ができます。次にWebエディタのリンクを記します。

https://editor.p5js.org/


# 構成要素
使用している技術およびサービスについて、おおまかに説明します。

## MarkdownAI
MarkdownAIは、Markdown記法（とHTML、Javascript、CSS）で生成AIを用いたWebサイトを手軽に作成できるツールとなっています。制作したWebページの根幹的な要素です。詳細は次のWebサイトをご確認ください。

https://mdown.com/ja/

## p5.js
p5.jsは [Processing](https://processing.org/) というJavaベースのグラフィックス言語をJavascript上で動作できるように開発された描画ライブラリです。作成したWebページでは、アートを描画するために利用しています。

https://p5js.org/

# 開発手順
基本的に次のサイトの流れに沿りました。

https://qiita.com/mdown_ai_jpn/items/d3e281565c876a0bd64f

本記事では、主に制作したWebページにおける[AIの制作手順](https://qiita.com/mdown_ai_jpn/items/d3e281565c876a0bd64f#%E5%AE%9F%E9%9A%9B%E3%81%AB%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86ai%E5%88%B6%E4%BD%9C%E6%89%8B%E9%A0%86)について記載します。そのため、次の内容に関する説明は大きく省きます。

- [MarkdownAIを用いたサイトの公開手順](https://qiita.com/mdown_ai_jpn/items/d3e281565c876a0bd64f#%E5%AE%9F%E9%9A%9B%E3%81%AB%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86%E3%82%B5%E3%82%A4%E3%83%88%E5%85%AC%E9%96%8B%E6%89%8B%E9%A0%86)
  - サインアップ
  - プロジェクトの作成方法
  - サイトの公開方法
- Markdown記法の文法に関する説明
- 使用している描画ライブラリ p5.js に関する詳細説明

## 手順1．モデルの選択
2024/12/09時点で、MarkdownAIで利用できるAIは次の5種類です。各々の特徴について大雑把にまとめます。

|モデル|特徴|
|---|---|
|```GPT-4o-mini``` |特定の用途向けに最適化されていて、高速で軽量に推論できる|
|```GPT-3.5-turbo``` |高速で低コストなGPT-3.5の改良版|
|```GPT-4```|高性能な大規模言語モデルで複雑なタスクにも対応可能|
|```Claude``` |AnthropicによるAIで、安全性と倫理を重視|
|```Gemini``` |Google DeepMindが開発したAIモデル、マルチモーダル対応に注力されている|

それぞれ試してみた結果、最も綺麗かつ魅力的なアートを生成してくれるのは```Claude``` でした。

## 手順2．プロンプトの記入
AI に推論をさせるにあたりPromptを記入する必要があります。

### 5つのR
[Markdown AI社のチュートリアル](https://qiita.com/mdown_ai_jpn/items/d3e281565c876a0bd64f#%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88%E3%81%A8%E3%81%AF) によると、次の5要素（5つのR）を含むことが重要とされていました。

|要素|内容|
|---|---|
|Request（依頼）|AIに返答してほしいこと|
|Roll（役割）|AIが誰である想定なのか|
|Rule（ルール）|AIに守ってもらいたい規則や禁忌|
|Reason（推論）|Request（依頼）に関する詳細な説明|
|Recommend（推奨）|例|

- Request（依頼）、Reason（推論）
AIにしてほしい依頼は「Webページの背景となりそうなジェネレーティブアートの制作」です。
そして、その返答は描画ライブラリで実装されたプログラムであることを求めます。

- Roll（役割）
AIには「p5.jsでジェネレーティブアートを制作できるプロのアーティスト」になってもらいます。

- Rule（ルール）、Recommend（推奨）
Webサイトを作成するにあたり、ここが一番重要に感じました。私はAIからの返答でアートを描画するプログラムと、その挙動に関する説明文を受け取って実装しています。

プログラムはWebページ上でアートを表示するとき、説明文は[Description]ボタンを押したときにユーザへ提示するときにそれぞれ必要です。それらを取得するにあたり、Webページのプログラムで処理できるように、AIには次のようなJSON形式で返答するように指定しました。

```JSON：AIの返答として期待する形式
{
  "code"          : "アートを描画するプログラム", 
  "description"   : "アートの挙動に関する説明文"
}
```

### プロンプトの内容
最終的に次をプロンプトにしようとしました。

```:プロンプト
あなたはp5.jsでジェネレーティブアートを制作するプロのアーティストである。
次の要素を3つ以上もつクリエイティブなWebページの背景となるp5.jsのソースコードを作成せよ。
- 視覚的に魅力的である
- ユーザが見ていて飽きない
- 流動的な動きがある
- ellipse()，point()以外を使っている
- インタラクティブであり、次のどちらかでユーザと対話できる動的な要素がある
  - 例: マウスカーソルの動きに合わせた反応がある
  - 例: マウスカーソルの座標で色が変わるのはダメ

次の点を厳守せよ。
- コメントアウトはつけるな
- キャンバスの大きさは必ず(windowWidth * 0.9, windowHeight * 0.9)にして、リサイズの処理も実装せよ
- 常にアニメーションを含んでいる
- 返答については可能な限り高速にせよ
- 他にもWebページを閲覧しているユーザの気分を害するようなデザインやコンテンツは厳禁である。

なお、出力は次のようなJSON形式で答えよ。
{
  "code"          : "アートを描画するプログラム", 
  "description"   : "アートの挙動に関する説明文"
}
```

しかし、プレビューでAIを動かそうとしたところ次のようなエラーが出力されました。

```
SyntaxError: Unexpected token 'I', "Internal S"... is not valid JSON
```

どうやら、Prompt の箇所に次のようなJSONを含むとサーバ側のデータ処理で異常が生じるみたいです。

```
{
  "code"          : "アートを描画するプログラム", 
  "description"   : "アートの挙動に関する説明文"
}
```

そこで、AIを制作するページではなく、マークダウンのスクリプト上で前述のプロンプトを入力してみました。

```javascript: プロンプトに関するプログラム
let message = `あなたはp5.jsでジェネレーティブアートを制作するプロのアーティストである。
次の要素を3つ以上もつクリエイティブなWebページの背景となるp5.jsのソースコードを作成せよ。
- 視覚的に魅力的である
- ユーザが見ていて飽きない
- 流動的な動きがある
- ellipse()，point()以外を使っている
- インタラクティブであり、次のどちらかでユーザと対話できる動的な要素がある
  - 例: マウスカーソルの動きに合わせた反応がある
  - 例: マウスカーソルの座標で色が変わるのはダメ

次の点を厳守せよ。
- コメントアウトはつけるな
- キャンバスの大きさは必ず(windowWidth * 0.9, windowHeight * 0.9)にして、リサイズの処理も実装せよ
- 常にアニメーションを含んでいる
- 返答については可能な限り高速にせよ
- 他にもWebページを閲覧しているユーザの気分を害するようなデザインやコンテンツは厳禁である。

なお、出力は次のようなJSON形式で答えよ。
{
  "code"          : "アートを描画するプログラム", 
  "description"   : "アートの挙動に関する説明文"
}`;

// インスタンスを生成する
const serverAi = new ServerAI();

// 回答を取得する（`getAnswerText`メソッドが事前に正しく定義されている必要がある）
const answer = await serverAi.getAnswerText(
  "serverAiのID（MarkdownAIの編集ページでInsertボタンを押すと自動的に入力される）",
  "",
  message
);
```

こうすると、エラーが発生せずに次のような回答を得ることができました（正確には次のテキストを「`` ```json ``」もしくは「`` ```javascript ``」と「`` ``` ``」で囲まれた文字列が返されるので、```.replace()```メソッドでそれらを除く必要があります）。

```json: AIの回答例
{
  "code": "let particles = []; function setup() { createCanvas(windowWidth * 0.9, windowHeight * 0.9); for (let i = 0; i < 100; i++) { particles.push(new Particle(random(width), random(height))); } } function draw() { background(240, 240, 250); for (let p of particles) { p.update(); p.display(); } } class Particle { constructor(x, y) { this.position = createVector(x, y); this.velocity = createVector(random(-1, 1), random(-1, 1)); this.size = random(5, 15); } update() { this.position.add(this.velocity); if (this.position.x > width || this.position.x < 0) this.velocity.x *= -1; if (this.position.y > height || this.position.y < 0) this.velocity.y *= -1; } display() { fill(100, 150, 200, 150); noStroke(); ellipse(this.position.x, this.position.y, this.size); } } function windowResized() { resizeCanvas(windowWidth * 0.9, windowHeight * 0.9); }",
  "description": "このアートは、ランダムに動く粒子を描画します。粒子はキャンバスの端に達すると反射し、流動的な動きを持っています。ユーザーがマウスを動かすと、粒子の動きがわずかに変化し、インタラクティブな体験を提供します。"
}
```

# MarkdownAIに関する所感
今回、はじめて私はMarkdownAIを使ってみました。そこで体感した良かった点と、恐れ多いですが改善していただきたい点をまとめたいと思います。

## 良かった点
- Webページの公開、生成AIの利用が非常に簡易である

これが一番、大きなメリットでした。本来であれば、管理する必要があるサーバの概念に対して気を遣う必要がないというのはかなりのストレスフリーです。生成AIを無料で使えるというのも、とても大きい利点です。

- WebページをMarkdown、HTML、Javascript、CSSで構成できる

簡単なWebページであればマークダウンで制作を完結できるというのはとても楽です。今回制作したWebページではほとんどがJavascriptで実装しており、この点を上手に活かすことはできませんでしたが、、、。

## 改善してほしい点
- テキストエディタのデザイン

こちらがWebページの制作画面となっているのですが、入力されたテキストはこのように黒色で統一されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/bd620819-bed5-919a-19ac-8e3cc89c75ca.png)


VSCodeのように行数やシンタックスハイライトがあると、より作業がしやすいように感じました。さらにわがままを言うと、入力する内容（マークダウン、HTML、Javascript、CSSの構文）の補足機能があると最良ですが、、、。

![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/b35955b1-ba40-4140-baf8-acb77e8788e9.png)

筆者はVSCodeで実装して、それらをコピペでWebページのテキストエディタに写していました。

- リファレンス

私の調査が甘い可能性はあるのですが、生成AIを利用するにあたってリファレンスを発見することができませんでした。それにより、Javascriptのプログラムで理解できない箇所がありました。例えば、```ServerAI```クラスの```.getAnswerText()```メソッドについて、第二引数にどういう役割があるのか説明されている文書を見つけることができませんでした。

また、単に私の技術力の問題で解決できる問題かもしれませんが、Javascriptの処理が2回実行されます。これにより、1回の会話につきAIの返答が2個となり、Webページの挙動が狂うことがあります。

![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/0ef5b3ea-6bb9-108a-5b88-815c9de4886c.png)

# さいごに
この記事では、MarkdownAIを活用したジェネレーティブアートの生成ツールの開発について紹介しました。MarkdownAIは無料で生成AIが利用できる魅力的なツールです。特に、シンプルな構成のWebページを作成することに対しては有効に感じました。


# 参考

https://mdown.com/ja/

https://qiita.com/mdown_ai_jpn/items/d3e281565c876a0bd64f#request%E4%BE%9D%E9%A0%BC

https://qiita.com/coke_kouichi/items/8f869dcbddf9fccf4cde



https://qiita.com/Damien/items/5f8d4691723b01f370b9