見出し画像

EC2にChatGPTのチャットボット実装してみた

分析屋の中田(ナカタ)です。
EC2でChatGPTのAPI呼び出しを行うWebアプリを実装してみました。
実装自体の説明は少なくして、用語の1つ1つをかなり丁寧にまとめました。




EC2とは

AWSが提供する仮想コンピューティングサービスです。
要はAmazonからインターネット経由でコンピュータを借りるようなサービスです。
借りてきた実体のことをインスタンスと呼びます。


ChatGPTとは

現在話題の、AIによる対話側チャットサービスです。
Web画面から対話することも可能ですが、プログラミングによる呼び出し(APIの利用)も可能です。


Webアプリとは

Web上で利用するアプリケーションです。
端末にダウンロードする必要がないアプリケーションです。

Webアプリを公開するためには、Webアプリの内容を書いたファイルを持ったコンピュータ(サーバー)が必要です。
今回はEC2インスタンスをサーバーとして利用します。


今回やること

EC2インスタンスをWebアプリケーションサーバーとして利用します。
EC2インスタンスに、HTMLファイルとPythonファイルを配置します。
このようにして外部のユーザーが利用できる状態にすることをデプロイと言います。
外部のユーザーは、このEC2インスタンスに接続することでWebアプリを利用することができます。
PythonでChatGPTのAPI呼び出しを行います。


事前準備

AWSのアカウント登録、EC2インスタンスの作成とキーペアの作成、
ChatGPTの登録とAPIキーの取得などは事前に完了しているものとして進めます。
EC2関連の手順は、調べるとすぐ見つかります。
ChatGPTのAPIについては別記事で少し触れています。
参考リンク

AWS環境について、東京リージョンを使用しております。
EC2インスタンスはAmazonLinux2023 AMIでt2.microです。


①EC2に接続

EC2インスタンス作成時にキーペアを作成した場合、○○.pemというファイルがローカルPCにダウンロードされています。
テキストエディタで開くと訳の分からぬ英数字が羅列されています。
これがEC2接続時の鍵情報となりますので紛失厳禁です。

環境によって、EC2インスタンスへの接続手順が若干異なります。
以下はWindows環境で、PowerShellで接続する場合の例です。

カレントディレクトリに上記のpemファイルがある状態で
PowerShellを開き、以下のコマンドを入力します。

ssh -i ******.pem ec2-user@**.***.***.***

******.pemは、pemファイルの名前を入れてください。
ec2-user@**.***.***.***は、@の前にあるのがデフォルトのユーザー名です。
特にユーザーの作成や削除をしていなければこれでいけるはずです。
@の後ろは接続先のEC2インスタンスのパブリックIPアドレスを指定します。

EC2インスタンスのパブリックIPアドレスを固定にしていなければ
ここはインスタンス起動のたびに変わることになります。

上記のコマンド実行後
ほんまに接続するんか?という旨の、以下の表示が出ていれば「yes」を入力してEnterです。

Are you sure you want to continue connecting (yes/no/[fingerprint])?

そうすると鳥が羽ばたくはずです。
これでローカル環境のPowerShellから、EC2インスタンスに接続ができました。

もしpermissonsがどうとかエラーが発生している場合は、pemファイルへの読み取り権限を付与する手順が必要になります。
PowerShellの場合は以下のコマンドを先に実行してください。

$path = ".\******.pem"
icacls.exe $path /reset
icacls.exe $path /GRANT:R "$($env:USERNAME):(R)"
1行目の******.pemの部分はpemファイル名を指定してください。


②Pythonライブラリのインストール

EC2インスタンス作成時に、AmazonLinux2023AMIを選択している場合は
デフォルトでPython3がインストールされています。

Webアプリ開発のため、以下のコマンドでライブラリをインストールしておきます。

まずはpip自体のインストール

sudo yum install python-pip

Webアプリ開発で有名なFlaskと
ChatGPTのAPI利用で必要なopenaiのインストール

sudo pip3 install Flask
sudo pip3 install openai


③必要ファイルの作成

Webアプリをデプロイするにあたり、いろいろとファイル作成が必要です。
まずはファイル置き場のディレクトリを作成します。

デフォルトではEC2インスタンス接続時には /home/ec2-user という場所にいます。
以下のコマンドで確認できます。

pwd

ここに、以下のコマンドでファイル置き場を作成します。

mkdir sample

mkdirはメイクディレクトリ、要はフォルダを作るよ的な意味です。
sampleは好きな名前にしてOKです。

んでもって以下のコマンドでsampleディレクトリに移動します。

cd sample

さらに以下のコマンドで、app.pyという名前のPythonファイルを新規作成します。

vi app.py

viはLinuxのテキストエディタです(.pyはただのテキストファイルです)。
キーボードの i を押下すると、INSERTモードになり編集できます。

操作感がデスクトップのテキストエディタとは異なるので
メモ帳などで書いておいて、貼り付けてもいいです。
貼り付けCtrl + VでもShift + Insertでもなく右クリックです。
また、貼り付け後にインデントがずれていれば修正してください。

以下のコードをベースに適宜アレンジしてください。
openai.api_key = '********' の部分はChatGPTのAPIキーをハードコーディングしています。
有料版のChatGPT plusを使用しており、モデル部分はgpt-4としています。

from flask import Flask, render_template, request, jsonify
import openai

app = Flask(__name__)
openai.api_key = '********'

@app.route('/')
def index():
    return render_template('index.html')

@app.route("/send-message", methods=["POST"])
def send_message():
    user_input = request.json.get("user_input")
    messages =  [{"role": "user", "content": user_input}]
    response = openai.chat.completions.create(
                                            model="gpt-4",
                                            messages=messages,
                                            temperature=0
                                            )
    answer = response.choices[0].message.content
    return jsonify({"answer": answer})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

簡素なものではありますが、これでChatGPTのAPIを利用するロジック部分はできました。
説明は割愛しますが、丸ごとChatGPT先生にぶん投げて質問すれば解説してくれます。
さらに、Web画面の枠組みを作るためHTMLファイルを作成します。

カレントディレクトリは /home/ec2-user/sample になっているはずです。
ここで以下のコマンドを順次実行していきます。

HTMLファイル置き場のディレクトリを作ります。

mkdir templates

作ったディレクトリに移動します。

cd templates

HTMLファイルを作ります。
app.py同様にviエディタで作ります。

vi index.html

内容は以下の通りです。
<script>部分はJavaScriptで記述しています。
HTMLファイルは貼り付け後にインデントが崩れても実行可能です。

<!-- index.html -->

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ChatGPT_bot</title>
</head>
<body>
    <div id="chat-container">
    <div id="chat-log"></div>
        <input type="text" id="user-input" placeholder="メッセージを入力">
        <button onclick="sendMessage()">送信</button>
    </div>

  <script>
        function sendMessage() {
            let user_input = document.getElementById('user-input').value;
            let chat_log = document.getElementById('chat-log');
   chat_log.innerHTML += '<div class="user-message">A: ' + user_input + '</div>';
     fetch('/send-message', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    user_input: user_input,
                }),
            })
            .then(response => response.json())
            .then(data => {
                chat_log.innerHTML += '<div class="bot-message">B: ' + data.answer + '</div>';
            })
            .catch(error => console.error('Error:', error));
            
            document.getElementById('user-input').value = '';
        }
    </script>
</body>
</html>

app.pyの作成手順と同様、ESCキーからの:wq!で保存完了です。
これですべての準備が整いました!


④デプロイ&アクセス

以下のコマンド実行で、Pythonモジュールを起動します。

まずはapp.pyを置いているディレクトリに戻ります。
1つ上の階層のはずです。

cd ..

app.pyを起動します。

sudo python3 app.py

Webブラウザを開いて、URLバーに以下のアドレスを入力します。

https://**.***.***.***

**.***.***.*** には、EC2インスタンスのパブリックIPアドレスを指定します。
ちゃんとするならドメインを取得しますが、今回は金銭コストを抑えてお試しするため、直接パブリックIPアドレスを指定して接続します。

接続後はテキストボックスとボタンが表示されているはずです。
以下は試しに「元気ですか」と入力した画面です。

見た目が淡泊ですが、適宜CSSファイルを追加してみてください。


最後に

ここまでのお試しはインスタンスの起動時間に応じて金銭コストが発生しますので
使用後はインスタンスの停止(一時停止)や終了(リソース削除)を忘れずに実行してください。




ここまでお読みいただき、ありがとうございました!
この記事が少しでも参考になりましたら「スキ」を押していただけると幸いです!

株式会社分析屋について

弊社が作成を行いました分析レポートを、鎌倉市観光協会様HPに掲載いただきました。

ホームページはこちら。

noteでの会社紹介記事はこちら。

【データ分析で日本を豊かに】
分析屋はシステム分野・ライフサイエンス分野・マーケティング分野の知見を生かし、多種多様な分野の企業様のデータ分析のご支援をさせていただいております。 「あなたの問題解決をする」をモットーに、お客様の抱える課題にあわせた解析・分析手法を用いて、問題解決へのお手伝いをいたします!

【マーケティング】
マーケティング戦略上の目的に向けて、各種のデータ統合及び加工ならびにPDCAサイクル運用全般を支援や高度なデータ分析技術により複雑な課題解決に向けての分析サービスを提供いたします。

【システム】
アプリケーション開発やデータベース構築、WEBサイト構築、運用保守業務などお客様の問題やご要望に沿ってご支援いたします。

【ライフサイエンス】
機械学習や各種アルゴリズムなどの解析アルゴリズム開発サービスを提供いたします。過去には医療系のバイタルデータを扱った解析が主でしたが、今後はそれらで培った経験・技術を工業など他の分野の企業様の問題解決にも役立てていく方針です。

【SES】
SESサービスも行っております。