Gemini API × Reactでチャットボット的なアプリを作ってみた

## はじめに

Gemini API × Reactで簡単なチャットボット的なアプリを作ってみました。

## Reactアプリの環境構築をする

create-react-appでReactのアプリの環境を構築します。typescriptを利用できるように--templateでtypescriptを指定します。

```
$ npx create-react-app gemini-chat-bot --template typescript
```

Gemini APIを利用する際に必要なaxiosのライブラリをインストールしておきます。

```
$ npm install axios
```



## Gemini APIからAPI Keyを発行する

![スクリーンショット 2024-05-12 12.09.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242816/afb19905-270f-63f8-430e-a52294d6da1a.png)

https://aistudio.google.com/app/

Google AI Studioにログインし、「Create API Key」からAPI Keyを取得します。Keyは一度のみ表示されるので、コピーして保存しておきましょう。

![key.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242816/9a263dc3-03ad-cab4-8053-85f2f9d4fd8d.png)


Keyを保存したら、.envファイルを作成し以下のように環境変数を設定します。

creare-react-appで作ったプロジェクトはprocess.env.REACT_APP_から始まる変数を読み込みができるようになっています。

```.env
REACT_APP_GEMINI_API_KEY=key名
```


## Gemini APIの疎通確認

![api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242816/62a585b2-62bf-bc72-84bc-d473ba6fec1f.png)

実際にGemini APIとの疎通ができるか確認してみます。POSTする内容はGoogle AI StudioにあるAPI keyの下のcurlコマンドを参考します。

URLのkeyのところは先ほど設定した環境変数であるprocess.env.REACT_APP_GEMINI_API_KEYを指定します。まずは疎通確認のため、送信するテキストを「こんにちは」に固定します。

```ts
const response = await axios.post(
  `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${process.env.REACT_APP_GEMINI_API_KEY}`,
  {
    contents:[
      {
        parts:[
          {
            text: "こんにちは"
          }
        ]
      }
    ]
  },
  {
    headers: {
      "Content-Type": "application/json"
    }
  }
);
```


これで実行して、コンソールにレスポンスのデータを表示するようにすると以下のように「こんにちは」に対しての回答が格納されていることがわかります。


## テキストを入力したらGemini APIを通して返ってくるようにする

現状だと、「こんにちは」の固定文字になっているため、ユーザーが入力したテキストを送れるようにします。

HTMLにinputタグを追加し、onChangeで入力したらinputTextに値を格納するようにします。その流れで処理を実行している間はisLoading変数をtrueにして「現在、問い合わせ中です...」という文言を表示するようにしました。

また、react-markdownライブラリをインストールして、レスポンスデータをHTMLに変換して、表示するようにしました。

```ts
import axios from "axios";
import { useState } from "react";
import ReactMarkdown from "react-markdown";
import styles from "./styles.module.css"

const Chat = () => {
  const [responseMessage, setResponseMessage] = useState<string>("");
  const [inputText, setInputText] = useState<string>("");
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const sendMessage = async () => {
    setIsLoading(true);
    try {
      const response = await axios.post(
        `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${process.env.REACT_APP_GEMINI_API_KEY}`,
        {
          contents:[
            {
              parts:[
                {
                  text: inputText
                }
              ]
            }
          ]
        },
        {
          headers: {
            "Content-Type": "application/json"
          }
        }
      );
      
      const responseContent = response.data.candidates[0].content;
      const responseParts = responseContent.parts.map((part: { text: string }) => part.text).join("\n");
      setResponseMessage(responseParts);
      setIsLoading(false);
    } catch (error) {
      console.error(`Gemini API has error occured: ${error}`);
    }
  };

  return (
    <div>
      <h1>Gemini Chat Bot</h1>
      <div>
        { isLoading ? <p>現在、問い合わせ中です...</p> : null}
        <ReactMarkdown>{responseMessage}</ReactMarkdown>
      </div>
      <div>
        <input
          type="input"
          value={inputText}
          onChange={(e) => setInputText(e.target.value)}
        />
        <button onClick={sendMessage}>送信</button>
      </div>
    </div>
  )
}

export default Chat;
```

上記を実装すると、こんな感じになりました。

![スクリーンショット 2024-05-12 20.02.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242816/9ad51be1-5f08-0aff-f191-ec73990dff46.png)



## デザインをあてて完成

![スクリーンショット 2024-05-12 14.39.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242816/91c8284c-3d03-168a-fb2d-12056bfba9d7.png)

最後にデザインを当てます。せっかくなのでGeminiを使ってみました。

GeminiにHTMLのコードを渡して、チャット形式の良い感じのCSSを当ててと聞いて反映させると以下のようになりました。


## JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからライン登録お願いします👇

https://projisou.jp/