Markdown AI 活用術：5分でPython言語辞典を作成する方法

# 前置き

前回は「試験問題出題サイト」を作成しました。
↓こちらになります。

https://qiita.com/pdc-ujoy/items/81009936ddf843665e40

今回は何を投稿しようか…:thinking:？と考えた結果！

C#、Java、Python、Ruby、JavaScriptなど、複数の言語で開発していると、「あれ、この言語では…コードってどう書くんだっけ？」と悩むことがあります。
そういったときに、すぐに検索して教えてくれるサイトがあれば便利だと思い「Pythonの言語辞典」を作りました。

私は、Pythonの言語辞典サイトを作りましたが、AIモデルの**Prompt**の指示（日本語文）を変えるだけで、C#、Java、HTML、Ruby、JavaScriptなどの言語に変更することができるので、よかったら、参考にして作成してみてください！

# 言語辞典サイトの作成方法

**↓ 下記、作成したPython言語辞典のサイトになります。**

https://mdown.ai/content/ae5d2316-7e27-4089-9986-199f0c7552c9

## 作成の流れ

![python_mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828745/234ad56f-9237-541f-f548-e0c46e43a184.gif)

上記の通り、下記の手順を実施すると、5分ほどで作成できます！

## 作成手順

### ①ログインする

下記のMarkdown AIに（Googleアカウントで）ログインします。

https://mdown.ai/

### ②AIモデルの作成

画面左上の <img width="20" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828745/c92014c3-b5b9-639b-75af-3a03b9aed907.png"> ボタンをクリックして、Create Model画面を表示します。
次に、以下のAIモデルを入力してください。
入力が完了したら、[Create]ボタンをクリックしてAIモデルを登録します。

Select Model：gpt-4o-mini

:::note info
Select Modelの選択によって回答速度、内容が変わります。
バランスを重視する場合: gpt-4o-mini
短時間で精度が必要の場合: gpt-3.5-turbo
複雑なコードや例を重視する場合（一番高度だが処理速度が一番遅い）: gpt-4
:::

Memory：チェックあり
Model Name：Python言語　★←ここを作成する言語名のタイトルに変更します
Prompt：下記を登録する

```Markdown:Prompt
Role: Pythonの言語辞典として動作します。　★←ここを出力して欲しい言語名に変更します
Request: 指定された内容に基づいてコード例を出力してください。  
Rule: Markdown形式で記述してください。  
Reason: 説明は、全てコメント文で記述してください。
Recommend: 短いコードで、処理速度の良いコードを提示してください。 
```

### ③ページを作成

メイン画面に戻り、[Insert]ボタンをクリックした後、[Script]ボタンをクリックします。次に、上記で作成したAIモデルを[Insert]すると、以下のコードが追加され、AIモデルの番号を取得できます。
※AIモデルの番号を:writing_hand_tone2:メモしてから、作成されたAIモデルのコードを削除してください。

例）下記の「oqpn8zsgB1Gv91nmFAHZDE」が**AIモデル番号**になります。

```html:AIモデルの作成されたコード
<script>
(() => {
  const button = document.getElementById('button-1733704343');
  button.addEventListener('click', async event => {
    button.disabled = true;
  
    const serverAi = new ServerAI();
    const message = document.getElementById('text-1733704343').value;
    // ★下記のAIモデル番号「oqpn8zsgB1Gv91nmFAHZDE」をメモします。
    const answer = await serverAi.getAnswerText('oqpn8zsgB1Gv91nmFAHZDE', '', message);

    document.getElementById('answer-1733704343').innerText = answer;
    button.disabled = false;
  });
})();
</script>
```

下記の「**言語辞典サイトのソースコード**」をコピーし、該当のページ(ファイル）に貼り付けてください。その後、AIモデル番号を、ご自身が作成したAIモデルの番号に変更してください。

```html:AIモデルの番号を変更する箇所
  // ★↓ここを作成したAIモデルの番号に変更すること
  ai_model_id = '*************'
```

また、AIの回答時に使用する画像を変更する場合は、下記のhttps画像パスに置き換えてください。
新機能として **AI生成画像を作成して挿入する機能** が追加されていました。下記の「[AIによる画像生成の操作方法](#aiによる画像生成の操作方法)」を参考に作ってみてください！

```html:画像のURLを変更する箇所
  // ★↓ここを作成したAI画像のパスに変更すること
  ai_Img_src = 'https://storage.googleapis.com/topdowncom/content/6nl8ERRwCGQdm94Wnc2S0NVdKPi2/a663d664-e9ad-43ce-ad94-f837f0f47d40/99b137e7-668c-4c73-a595-b133ee5035aa'
```

#### ▶ 言語辞典サイトのソースコード

```html:言語辞典サイトのソースコード
## Python言語辞典

<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>

<div class="container-back" id="outputContainer"></div>

<div class="input_area">
  <textarea class="textarea_text"  id="instruction" placeholder="AIにメッセージを送信する"></textarea>
  <button type="button" class="btn_send" id="send_button">送信する</button>
</div>

<style>
.container-back{
  width: 100%;
  height: calc(100vh - 300px);
  overflow-y: auto;
  overflow-x: hidden;
  box-sizing: border-box;
  padding: 10px;
}
.back {
  width: 100%;
  padding: 8px 20px;
  text-align: right;
  font-size: 15px;
}
.left_area {
  width: 100%;
  margin: 10px 0;
  overflow: hidden;
}
.left_area .face_icon {
  float: left;
  margin-right: -50px;
  width: 50px;
}
.left_area .face_icon img{
  width: 100%;
  height: auto;
  border-radius: 50%;
}
.left_area .chatting {
  width: 100%;
  text-align: left;
}
.left_text {
  display: inline-block;
  position: relative;
  margin: 0 0 0 65px;
  padding: 18px;
  max-width: 80%;
  min-width: 1%;
  border-radius: 12px;
  background: #EBF2FA;
}
.left_text:after {
  content: "";
  display: inline-block;
  position: absolute;
  top: 3px;
  left: -19px;
  border: 8px solid transparent;
  border-right: 18px solid #EBF2FA;
  -webkit-transform: rotate(35deg);
  transform: rotate(35deg);
}
.left_text p {
  margin: 4px 0;
  padding: 0;
}
.right_text {
  margin: 10px 0;
}
.right_text p {
  display: inline-block;
  position: relative;
  margin: 0 10px 0 0;
  padding: 18px;
  border-radius: 12px;
  background: #f9f9f9;
  max-width: 80%;
  min-width: 1%;
}
.right_text p:after {
  content: "";
  position: absolute;
  top: 3px;
  right: -19px;
  border: 8px solid transparent;
  border-left: 18px solid #f9f9f9;
  -webkit-transform: rotate(-35deg);
  transform: rotate(-35deg);
}
.input_area{
  position: fixed;
  width: calc(100% - 100px);
  height: 150px;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  background-color: #f9f9f9;
  border-radius: 20px;
  border: 1px solid #e5e5e5;
  padding: 8px;
  box-sizing: border-box;
  display: flex;
  text-align: right;
}
.textarea_text{
  width: calc(100% - 110px);
  height: 100%;
  background-color: #f9f9f9;
  display: inline-block;
  vertical-align: top;
  padding: 8px;
  box-sizing: border-box;
  border-radius: 5px;
  border: none;
  outline: none;
  line-height: 1.6;
  resize: none;
  overflow-y: auto;
}
.btn_send {
  position: absolute;
  font-size: 1rem;
  bottom: 18px;
  right: 18px;
  border: none;
  border-radius: 10px;
  background-color: #006BBB;
  color: #FFF;
  padding: 8px 18px;
}
.btn_send:hover,
.btn_send:focus {
  color: #FFF;
  background-color: #444;
  background-image: none;
}
.btn_send:disabled {
  background: #ccc;
  color: #666;
  cursor: not-allowed;
  opacity: 0.7;
}
pre code {
    background-color: #fff;
    border: 1px solid #ccc;
    border-radius: 5px;
    padding: 15px;
    font-family: 'Courier New', Courier, monospace;
    font-size: 14px;
    line-height: 1.6;
    overflow-x: auto;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  }
pre {
    margin: 0;
    padding: 0;
  }
.hljs {
    background-color: #fff;
  }
</style>

<script>

(() => {
  // ★↓ここを作成したAIモデルの番号に変更すること
  ai_model_id = '*************'

  // ★↓ここを作成したAI画像のパスに変更すること
  ai_Img_src = 'https://storage.googleapis.com/topdowncom/content/OxTss0BvZQODZHRpcD5laT2E1n42/513644f4-5712-4c18-988a-2ad6299e9202/07c12c98-4f74-438f-bad8-fb7e295f67f1'

  // 送信ボタンクリックイベント
  const sendButton = document.getElementById('send_button');
  const message = document.getElementById("instruction");
  sendButton.addEventListener('click', async event => {
  sendButton.disabled = true;
  const serverAi = new ServerAI();
  const answer = await serverAi.getAnswerText(ai_model_id, '', message.value);
    if(message.value){
      messagContainer(marked.parse(answer), marked.parse(message.value));
      document.getElementById("instruction").value = "";
      hljs.highlightAll();
      // スクロールを一番下に設定
      const outputContainerDiv = document.getElementById('outputContainer');
      outputContainerDiv.scrollTop = outputContainerDiv.scrollHeight;
    }
   sendButton.disabled = false;
  });
})();

function messagContainer(aiInput, userInput) {
    // コンテナ要素
    const container = document.getElementById('outputContainer');
    // 大枠のdiv (back)
    const backDiv = document.createElement('div');
    backDiv.classList.add('back');
    // 右側のテキスト (right_text)
    const rightTextDiv = document.createElement('div');
    rightTextDiv.classList.add('right_text');
    const userParagraph = document.createElement('div');
    userParagraph.innerHTML = userInput;
    rightTextDiv.appendChild(userParagraph);
    // 左側のエリア (left_area)
    const leftAreaDiv = document.createElement('div');
    leftAreaDiv.classList.add('left_area');
    // 顔アイコン (face_icon)
    const faceIconDiv = document.createElement('div');
    faceIconDiv.classList.add('face_icon');
    const faceIconImg = document.createElement('img');
    faceIconImg.src = ai_Img_src;
    faceIconImg.alt = 'Face Icon';
    faceIconDiv.appendChild(faceIconImg);
    // チャットエリア (chatting)
    const chattingDiv = document.createElement('div');
    chattingDiv.classList.add('chatting');
    // 左側のテキスト (left_text)
    const leftTextDiv = document.createElement('div');
    leftTextDiv.classList.add('left_text');
    leftTextDiv.setAttribute('id', 'left_text_div');
    leftTextDiv.innerHTML = aiInput;
    // チャットエリアに要素を追加
    chattingDiv.appendChild(leftTextDiv);
    // 左側エリアに要素を追加
    leftAreaDiv.appendChild(faceIconDiv);
    leftAreaDiv.appendChild(chattingDiv);
    // 大枠に右テキストと左エリアを追加
    backDiv.appendChild(rightTextDiv);
    backDiv.appendChild(leftAreaDiv);
    // コンテナに生成したHTMLを追加
    container.appendChild(backDiv);
}
$(function () {
  // マークダウンをプレビュー画面に表示する
  marked.setOptions({
    langPrefix: '',
    breaks : true,
    sanitize: true,
  });
  $('#markdown_editor_textarea').keyup(function() {
    var html = marked(getHtml($(this).val()));
    $('#markdown_preview').html(html);
  });
  //マークダウンをHTMLに変換する
  var target = $('.item-body')
  var html = marked(getHtml(target.html()));
  $('.item-body').html(html);
  // 比較演算子が &lt; 等になるので置換
  function getHtml(html) {
    html = html.replace(/&lt;/g, '<');
    html = html.replace(/&gt;/g, '>');
    html = html.replace(/&amp;/g, '&');
    return html;
  }
});
</script>
```

### ③ページ（ファイル）を公開する

[View]ボタンをクリックすると、WEBに公開された際のイメージ画面が表示されます。
次に、[URL]ボタンをクリックすると「Create Public Link」のダイアログが表示されます。
[Publish]ボタンをクリックすることで、WEB上にページが公開されます。
公開先のURLは、[Link]ボタン内の<img width="25px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828745/3ee2678e-5f8f-bdd4-b436-cd87eda5e676.png">アイコンをクリックすることでコピーできます。

### 補足

AIモデルにMarkdown形式で回答を出力してもらって、「marked.js」のライブラリを使ってHTML形式に変換して表示しています。「highlight.js」のライブラリを使ってソースコードをきれいに表示しています。

:::note info
marked.jsとは
マークダウンテキストをHTMLに変換するためのJavaScriptライブラリのことです。
:::

:::note info
highlight.jsとは
HTMLにソースコードを表示するとき、キーワードなどを強調表示するためのJavaScriptライブラリのことです。
:::

# AIによる画像生成の操作方法

前回操作した際にはなかった新機能が追加されていたので、その操作方法を記載します。

画面上の[Insert]ボタンをクリックした後、[AI Image]ボタンをクリックします。
すると、以下の画面が表示されます。それぞれの選択肢の意味を簡単に説明します。（灰色の場合は「選択なし」を意味します）

![スクリーンショット 2024-12-09 10.09.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828745/5d825591-a8ef-30ff-844d-c9623f42c39e.png)

ロボットの画像を作成したかったため、以下の項目を選択し、生成ボタンをクリックしました。

![スクリーンショット 2024-12-09 23.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828745/450c3a8d-fc60-c0c1-316e-55e6a6f535a0.png)

すると、以下の画像が生成されました。（5回目で、いい感じの画像が生成されました）
[Insert]ボタンをクリックして画像を保存します。

※注意：AIで生成された画像は毎回異なるため、良い画像が生成された場合は、とりあえず[Insert]ボタンにて保存しておくことをおすすめします。

![スクリーンショット 2024-12-09 11.25.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828745/fd4e874f-5b02-595e-6d41-0ee9441c4511.png)

# 最後に

前回操作したときになかった、画像生成機能が追加されていたので試してみました。絵を選んで画像を作成するだけなので、小学生でも簡単に操作できると感じました。
「Ary Style」（画風）の設定は必須です！
この設定によって、写真風、ペン描き風、ドット絵風など、画像の仕上がりが大きく変わります。

以上、最後まで読んでいただき、ありがとうございました。