OpenAI APIを使用してESPr® Developer(ESP-WROOM-02開発ボード)で Web サーバーを実装し、ChatGPTを使用することについて解説しています。
■用意したもの
・ESPr® Developer(ESP-WROOM-02開発ボード)(https://amzn.to/3LG381X)
今回はスイッチサイエンスで購入したものを使用。
・Micro(マイクロ)USBケーブル1本(https://amzn.to/42bYhLk)
・OpenAIのアカウント
・OpenAIのAPIキー
■パソコン環境
・Windows11
・Arduino IDE Version 1.8.9(日本語対応済)
※なお、事前にESP8266 チップのサポートができるように「ESP8266 Arduino(https://github.com/esp8266/Arduino)」のインストールを行っています。
今回、設定しているボードは上記となります。
■新規ファイルを作成し、コードを記述する
「Arduino」を起動し、上部メニューの「ファイル」から「新規ファイル」をクリックします。
クリックすると、「sketch_***」というようなスケッチが表示されますので、このスケッチにWeb サーバーを起動し、HTMLページを表示させるコードを書いていきます。
■コード
- #include <ESP8266WiFi.h>
- #include <WiFiClientSecure.h>
- #include <ESP8266WebServer.h>
- #include <ArduinoJson.h>
- const char* ssid = “Wi-FiネットワークのSSID(ネットワーク名)”;
- const char* password = “Wi-Fiネットワークのパスワード”;
- const char* apiKey = “OpenAIのAPIキー”;
- ESP8266WebServer server(80);
- void handleRoot() {
- #今回は英語で「Where is the capital of Japan?」と質問
- String inputText = “Where is the capital of Japan?”;
- String url = “https://api.openai.com/v1/completions”;
- #今回はOpenAIの文章生成モデル「text-davinci-003」
- String payload = “{\”prompt\”:\”” + inputText + “\”,\”max_tokens\”:100, \”model\”: \”text-davinci-003\”}”;
- WiFiClientSecure client;
- client.setInsecure();
- if (!client.connect(“api.openai.com”, 443)) {
- Serial.println(“connection failed”);
- return;
- }
- client.println(“POST ” + String(url) + ” HTTP/1.1″);
- client.println(“Host: api.openai.com”);
- client.println(“Content-Type: application/json”);
- client.println(“Content-Length: ” + String(payload.length()));
- client.println(“Authorization: Bearer ” + String(apiKey));
- client.println(“Connection: close”);
- client.println();
- client.println(payload);
- while (client.connected()) {
- String line = client.readStringUntil(‘\n’);
- if (line == “\r”) {
- break;
- }
- }
- String response = “”;
- while (client.available()) {
- char c = client.read();
- response += c;
- }
- client.stop();
- DynamicJsonDocument jsonDoc(1024);
- deserializeJson(jsonDoc, response);
- String outputText = jsonDoc[“choices”][0][“text”];
- String page = “<html><body><h1>” + outputText + “</h1></body></html>”;
- server.send(200, “text/html”, page);
- }
- void setup() {
- Serial.begin(115200);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.println(“Connecting to WiFi…”);
- }
- Serial.println(“Connected to WiFi”);
- Serial.print(“Local IP: “);
- Serial.println(WiFi.localIP());
- server.on(“/”, handleRoot);
- server.begin();
- }
- void loop() {
- server.handleClient();
- }
■コードの備考
ESP8266WiFi.h : ESP8266のWi-Fiモジュールを制御するためのライブラリです。このライブラリを使用することで、ESP8266がWi-Fiネットワークに接続することができます。
WiFiClientSecure.h : Wi-FiモジュールからセキュアなHTTPS通信を行うためのクライアント機能を提供するライブラリです。このライブラリを使用することで、ESP8266がHTTPS通信を行うことができます。
ESP8266WebServer.h : ESP8266でWebサーバーを実装するためのライブラリです。このライブラリを使用することで、ESP8266でHTTPリクエストを受信し、レスポンスを返すことができます。
ArduinoJson.h : JSONデータの処理を行うためのライブラリです。このライブラリを使用することで、ESP8266がJSONデータを解析したり、JSONデータを生成したりすることができます。
※これらのライブラリはWebサーバーを実装するために必要なライブラリですので、事前にインストールを行っておく必要があります。
ESP8266WebServer server(80);は、ESP8266WebServerオブジェクトを定義。引数として80が渡されているため、Webサーバーはポート80でリクエストを受信するように設定。なお、ポート80は、HTTPプロトコルで使用される標準的なポート番号であり、Webブラウザからのリクエストは通常このポートを使用して送信されます。
void handleRoot()は、ESP8266WebServerオブジェクトで指定されたルート(/)に対するHTTP GETリクエストを処理するための関数です。HTTP GETリクエストは、WebブラウザがWebサイトのページを表示するために送信するリクエストの一種であり、指定されたURLに対応するWebページのコンテンツを取得。
WiFiClientSecureクラスは、ESP8266のWiFi接続を使用して、HTTPSを介してサーバーに接続するためのクラスです。このクラスは、暗号化された接続を確立するために、TLS/SSLプロトコルを使用。
client.setInsecure()は、HTTPS接続時に、証明書の検証を無効化するためのメソッドです。HTTPS接続を確立する場合、サーバーから送信されたデジタル証明書を検証し、証明書の情報とサーバー名が一致することを確認する。
・
- if (!client.connect(“api.openai.com”, 443)) {
- Serial.println(“connection failed”);
- return;
- }
api.openai.comのサーバーにHTTPS接続を確立しようとしています。client.connect()メソッドは、WiFiClientSecureクラスで提供されるメソッドであり、指定されたホストとポートに対してSSL/TLS接続を確立。
- while (client.available()) {
- char c = client.read();
- response += c;
- }
client.available()メソッドは、WiFiClientSecureクラスで提供されるメソッドであり、サーバーからの応答がまだ受信可能であるかどうかをチェック。whileループ内では、client.read()メソッドを使用して1バイトずつレスポンスを読み取り、response文字列に追加。このようにして、HTTP応答を受信し、必要な情報を抽出する。
- DynamicJsonDocument jsonDoc(1024);
- deserializeJson(jsonDoc, response);
- String outputText = jsonDoc[“choices”][0][“text”];
DynamicJsonDocumentクラスは、ArduinoJsonライブラリで提供されるクラスの1つで、JSONデータをメモリ内で解析および作成するためのものです。ここでは、1024バイトのメモリを使用して、jsonDocオブジェクトを作成しています。
deserializeJson関数は、ArduinoJsonライブラリで提供される関数の1つで、JSON文字列をJSONオブジェクトに変換します。ここでは、responseという文字列がJSONフォーマットであり、jsonDocオブジェクトに変換されます。
jsonDocオブジェクトは、JSONデータを解析し、JSONのプロパティにアクセスするために使用されます。この例では、jsonDoc[“choices”][0][“text”]のように、JSONオブジェクトの特定のプロパティにアクセスすることができます。jsonDocオブジェクト内のchoicesプロパティの最初の要素のtextプロパティの値が、outputText変数に割り当てられます。outputText変数には、OpenAI APIから返された応答のテキストが含まれます。
- String page = “<html><body><h1>” + outputText + “</h1></body></html>”;
- server.send(200, “text/html”, page);
- }
OpenAI APIから取得したテキストをHTMLページに表示する部分です。server.send関数を使用して、クライアントにHTMLページを送信します。server.send関数の最初の引数には、HTTPステータスコードを指定します。
- void setup() {
- Serial.begin(115200);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(1000);
- Serial.println(“Connecting to WiFi…”);
- }
ESP8266をWi-Fiに接続するためのセットアップを行う部分。シリアル通信を初期化し、シリアル通信のデータ転送レートを115200に設定しています。次に、指定されたSSIDとパスワードを使用してWi-Fiに接続します。これは、WiFi.begin()関数を使用して実行されます。whileループは、Wi-Fi接続が確立されるまで、1秒ごとにWiFi.status()を呼び出して、接続状態を確認します。WL_CONNECTEDの値は、Wi-Fi接続が確立されたことを示します。接続が確立されると、ループを継続する前に、「Connected to Wi-Fi」というメッセージをシリアルモニターに出力。なお、シリアル通信のデータ転送レートは、設定したボードのUpload Speedにあわせています。このように設定しないと、シリアルモニターに出力されない。
server.on(“/”, handleRoot);は、指定されたパスがリクエストされたときに、指定された関数を呼び出すようにWebサーバーを設定します。この場合、”/”が指定されているため、ルートパスに対するリクエストが受信された場合にhandleRoot関数が呼び出されます。
- void loop() {
- server.handleClient();
- }
ESP8266WebServerがクライアントからのHTTPリクエストを受信し、それに対する適切なレスポンスを返すためのループです。server.handleClient()は、クライアントからのリクエストを受け取り、それに対する適切なレスポンスを返すために必要な処理を実行します。これにより、Webサーバーが常に接続状態を維持し、クライアントからの要求に応答できるようになります。この無限ループを使用することで、ESP8266は常にWebサーバーとして機能し、リクエストに応答するために必要な処理を実行できます。
■コードを記述後、コードを保存します。
コードを記述した後は、コードを保存します。保存するためには、起動した「Arduino」の上部メニューの「ファイル」から「保存」をクリックします。
保存をクリックすると「すでに指定されているスケッチのフォルダの保存先」が表示されますので、保存する先に問題がなければ、ファイル名で名前を付け、ファイルの種類は「すべてのファイル(*.*)」と設定し「保存」ボタンをクリックします。これで今回記述したコードのファイルが保存されます。
■ESPr® Developer(ESP-WROOM-02開発ボード)にMicro(マイクロ)USBケーブルを接続し、PCにつなげる。
保存後、ESPr® Developer(ESP-WROOM-02開発ボード)に、Micro(マイクロ)USBケーブルを接続(USB(Micro-B)オス側)し、PCにつなげる(Micro(マイクロ)USBケーブルのUSB(A)オス側)。
■ESPr® Developer(ESP-WROOM-02開発ボード)とPCの接続を確認する
PCにつなげた後に、ESPr® Developer(ESP-WROOM-02開発ボード)とPCの接続を確認します。確認するために、起動した「Arduino」の上部メニューから「ツール」をクリックします。クリックすると、メニューが表示されますので、シリアルポートを確認します。
確認すると今回は「シリアルポート:”COM3”」と表示されています。さらにシリアルポートをクリックすると「COM3」にチェックが入っています。この状態が確認できれば、ESPr® Developer(ESP-WROOM-02開発ボード)とPCの接続確認作業は完了です。
■マイコンボード(ESPr® Developer(ESP-WROOM-02開発ボード))への書き込み
確認完了後、今回記述したコード(スケッチ)をマイコンボード(ESPr® Developer(ESP-WROOM-02開発ボード))へ書き込みします。
書き込みを行う際は、起動した「Arduino」の画面上で「→”右の矢印”(書込装置を使って書き込む)」ボタンをクリックします。クリックすると、書き込みが開始されます。
開始されると「Arduino」の画面下に「スケッチをコンパイルしています…」と表示されます。
次に「マイコンボードに書き込んでいます」と表示され、ESPr® Developer(ESP-WROOM-02開発ボード)への書き込みが行われます。
- Wrote 407856 bytes (299466 compressed) at 0x00000000 in 52.9 seconds (effective 61.6 kbit/s)…
- Hash of data verified.
- Leaving…
- Hard resetting via RTS pin…
その後「ボードへの書き込みが完了しました。」と表示されます。これでESPr® Developer(ESP-WROOM-02開発ボード)への書き込みが完了となります。
■シリアルモニタを確認する
完了後、シリアルモニタを確認します。確認する際は、起動した「Arduino」の画面上にある虫眼鏡のボタンをクリックします。
- Connecting to WiFi…
- Connecting to WiFi…
- Connecting to WiFi…
- Connected to WiFi
- Local IP: ***.***.***.**(IPアドレス)
クリックすると、シリアルモニタに上記が出力されます。
■Webサーバーが起動されているかの検証
出力された「Local IP: **.**.**.**(IPアドレス)」に表示されたIPアドレスの情報を保存しPC、もしくはスマートフォンでブラウザを使用し、アドレスバーにIPアドレスを入力します。入力後、アクセスを行います。
検証のために、PC(Windows11)からGoogleChromeを使用しアクセスした場合が上記になります。OpenAIの文章生成モデル「text-davinci-003」に対して、今回は「Where is the capital of Japan?(日本の首都はどこですか?)」と質問していますので回答として「The capital of Japan is Tokyo.(日本の首都は東京です。)」というテキストが生成され回答として出力。出力後、 Web サーバー上のHTMLに回答が表示されることが確認できました。
次にスマートフォン(OPPO Reno5 A)からChromeアプリを用いてアクセスした場合が上記になります。
これでOpenAI APIを使用してESPr® Developer(ESP-WROOM-02開発ボード)で Web サーバーを実装し、ChatGPTを使用する作業は完了となります。
コメント