【MarkdownAI】おもろいやん。きみ。

![スクリーンショット 2024-12-19 10.10.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/98b4f3b2-91a1-3a31-2723-a562c74d37b6.png)
今回はMarkdownAIで[「調べ物をしたらなんかいい感じに答えてくれるサイト」](https://mdown.ai/content/de44ea7c-e877-4b30-8531-e1865f9f6f57)を作りました。
実装までを解説したいと思います!

## 【序章】出会い、そして別れ
2024年 あれは5月の中頃でしょうか。
記事を書き始めてQiitaを見る習慣がついてたんですよね。
その時出会ったんです。　
同じように記事投稿イベントで。　
この子に

最初の印象ですか？
パッとしなかったですね、、、だってAIなかったんだもん
正直他のMarkdownサービスの方が使いやすかったですからね。

その時は予想できなかったなぁ、、、まさかこんなことになるなんて、、、

## 【第１章】再会と感動。そして困惑
序盤で離脱しないために今回作ったものを最初にドン
https://mdown.ai/content/de44ea7c-e877-4b30-8531-e1865f9f6f57

前々回くらいのMarkdownAIの投稿イベントで知ったきりだったので久しぶりに開いてみたらなんかボタンが増えてました。しかも可愛い。
![スクリーンショット 2024-12-17 10.55.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/965ae832-59fa-0387-36f5-a873ed8ea42e.png)

新しいおもちゃを触る気分でウキウキしながら触ってみて率直な感想。

「すごい！！！指示出したらAIの回答が描画される！！！」

と感動してふと我に帰り思いました。

「。。。何用？」

具体的なユースケースが思いつかなかったのが最初の印象です。
「一体何に使えばいいんだ？」「やってることはすごいんだけど活用方法がわからん」
そんなことを考えながら作ったのがこちらです。

https://mdown.ai/content/de44ea7c-e877-4b30-8531-e1865f9f6f57
「AI機能がある広辞苑のHP」

正直広辞苑なんて小学校以来使ってないですが、「広辞苑をPRしてるのにAIで調べれるHPがあったらおもろい」という理由で作りました。
広辞苑ごめん。　ほんとに

作成するにあたってMarkdownAIでできることを次の章で解説します。

## 【第２章】おもろいやん。きみ。
使っていくうちに色々できることがわかったのでざざっと出していきます。

### マークダウンが書ける(当たり前か）
マークダウンで文字が書けます。以上

### マークアップでもいける
HTMLも書けるみたい。
HTML書いてできたことは
- cssが書ける（styleタグで直接書いたら動いた）
- jsが書ける（scriptタグで直接書いたら動いた）
- iframeがおける（ということはYoutubeが乗っけれる）
- imgタグも使える（ということは画像をおける）

### 画像のアップロード
「＋」ボタンから画像をアップロードできます。
マークダウンでアップロードされますが、画像のパスが入ってるので、そのパスをそのまま
```<img src="${画像のパス}">```
で読み込んだら普通に扱えました。（やったらダメとかだったらごめん）

### AIをおける
「＋」ボタンからAIを置けます。
scriptで入ってくるようで、中身を見てみると、inputに文字列を入力しボタンを押下で非同期でAIサービスにリクエストを送っているようです。
レスポンスはinnerTextで特定のIDのDOMの中に生成されるようです。

**ということは、、、ここをinnerHTMLに変えればDOMを直生成できる！？！？！？！**

ここは何気に今回の実装のポイントです。

### AIをカスタマイズできる
AIが流行っているのであまり解説はいらないかもしれないですが、AIにはプロンプトと呼ばれる、**どのように書き出してほしいかなどをあらかじめ指示しておく**ことができます。
MarkdownAIでもこの機能が使えるます。ちなみにファイルもAIに食べさせることができるようです。（何気にすごいな）

使い方は左上のロボットボタンを押下

ここでAIのカスタマイズができます。複数のAIセット？みたいなのを作れるので、それぞれに別々のプロンプトを設定したAIを作れます。
回答をHTMLタグで囲ってくれというふうに指示を出してみたところ、HTMLタグで囲う＋クラスもつけることができました。
超動的HPが作れますね！！！！

カスタマイズしたAIのセットは+ボタンのScriptから選択できます。

### 外部サービスの取り込み
若干HTMLと被りますが、HTMLが行けるということは外部サービスの取り込みもいけます。

codepenのアレとか
Youtubeの動画埋め込みとか

今回の本開くやつは[LottieFiles](https://lottiefiles.com/)というwebアニメーションサービスを使ってます。（拡大しても荒くないですよね！！）

※基本は公式ドキュメントを参照してください。
公式HP：https://mdown.ai/
公式ドキュメント(Qiita)：https://qiita.com/yusuke_s_yusuke/items/aa0df11e81e110a46415

## 【第３章】
ここからは自己満。みたい人はどうぞ
どういう手順で作っていったかざっと気持ちを組み込みながら書いていきます。
主に伝えたかったのは第２章なのでここからは広辞苑HPの制作までのあゆみをひたすら書いていきます。

### DOMの実装
今回は「HPを作る」という想定なのでMarkdownAIなのにHTMLでマークアップしていきます。（別に喧嘩売ってるわけじゃない）
MarkdownモードでそのままHTMLコーディングをデータをぶち込みます。
![image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/163c382e-3a26-5e45-5d33-05b183e7debf.png)

[vite](https://ja.vite.dev/)を使ってscssとjsで実装したものをコピペしてます。
scssはコンパイルしたものをそのままstyleタグにコピーしましたが、javascriptはAIへのAPIが実装されているのでほぼ直書きでデバックしながらやりました。

### 画像の挿入
いい感じの画像をモデリングしてinsertからアップロードします。
HTMLとして認識させるために一度insertで画像アップロードした後にパスをそのままsrc属性へコピーします。
![image03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/ccff483f-018e-bcea-ce5b-0e96ac2c6868.png)

### AIの挿入
いよいよメイン機能AIの実装です。

まず新しく追加されたアイコンのロボットくんからAIの設定ページへ遷移します。
![スクリーンショット 2024-12-18 17.56.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/3f54be5f-a009-32e2-2d0d-343385f4698e.png)

今回はAIに最初に聞かれた内容に対するキーワードをランダムで５つ出した後に、回答を表示して欲しいのでPromptのところに以下のように記述しました。
![image04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/5504fd88-2c51-cb08-33f8-7aa22bdc5670.png)
【プロンプト内容】
```
関連するキーワードをはじめに５つ書き出した後に、回答を入力してください
５つのキーワードはそれぞれdivタグで囲い、クラス名にkeywordをつけてください。
回答もdivタグで囲いクラス名にanswerをつけてください。回答は200文字程度に収まるようにしてください
```で囲わないでください
```
こうすることでAIの回答のレスポンスがHTMLタグで囲われた状態で返ってきます。

そしたら適当に名前つけてページの一番したの「Update」ボタンで保存します。（初回は「Save」だったかな？）
「Upload」ボタンと間違えまくったのはいい思い出。

そしたら戻ってinsertからscriptを選択。
![スクリーンショット 2024-12-18 18.05.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/11ab1e6f-b64a-4433-ce14-854e7ff2c30c.png)

さっき作ったAIを入れたら。。。
![スクリーンショット 2024-12-18 18.05.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/4f660ee3-8330-4c70-15c4-3a42cf7f982e.png)

おおできたできた。
![スクリーンショット 2024-12-18 18.07.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/ae525d52-c8f9-13df-cdbb-61b982319839.png)


そしたら自動的に下記のコードが生成されるので、最後のinnerTextをinnerHTMLに変更。
``` HTML
<div style="display: inline-block;">
  <input type="text" id="text-1734512736" style="width: 200px;" value="Teach me about Markdown.">
  <button type="button" id="button-1734512736">Run AI</button>
</div>
<div id="answer-1734512736"></div>
  
<script>
(() => {
  const button = document.getElementById('button-1734512736');
  button.addEventListener('click', async event => {
    button.disabled = true;
  
    const serverAi = new ServerAI();
    const message = document.getElementById('text-1734512736').value;
    const answer = await serverAi.getAnswerText('9XhDw11EZ6JvmJyYX9JmzZ', '', message);
     - document.getElementById('answer-1734512736').innerText = answer; // ここを変える
     + document.getElementById('answer-1734512736').innerHTML = answer; // こんな感じに
    button.disabled = false;
    // ここに任意のコードを書くと、AI回答後に処理が走る。
  });
})();
</script>
```

最後に、ボタンを押すと非同期で生成してくれるので、await serverAi.getAnswerTextの行より下でいい感じにコーディングしたら、、、、

![コンポ 1_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/e0c64b80-0cc3-04de-f5db-97afc3468699.gif)

## 【最終章】おもろいやん。きみ。
結局マークダウンとしてではなくHTMLベースのHPサービスの一環として使ってしまいました。。。
時々Notionで会社のHP作ってるところがあったり、情報をただ乗っけるだけのHPでいいみたいなケースにはとても使えるなと思います。

scriptかけたりcss当てれたりできるので知識がある人なら結構なんでもできそうな印象です。
AIのAPIを無料で使える（正規版はわからないけど、、、）のも今回はおもしろ実装になりましたけど、最近よく見るチャットベースのカスタマーサービスとかを手軽に開発できるなと感じたりしました。