14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

はじめに

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

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

key.png

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

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

.env
REACT_APP_GEMINI_API_KEY=key名

Gemini APIの疎通確認

api.png

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

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

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に変換して、表示するようにしました。

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

デザインをあてて完成

スクリーンショット 2024-05-12 14.39.35.png

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

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

JISOUのメンバー募集中

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

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

14
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?