今回は、Pascalと生成AI(ChatGPT)を組み合せてみましょう。Pascalは視認性が高く、厳密な型システムを持っています。画面デザインが自由にできるLazarusの良さを活かしたAI秘書アプリを作ってみましょう。

  • AI秘書アプリを作ってみよう

最初に新規プロジェクトを作成して保存しよう

今回はWindowsで動くプログラムにしています。こちらからプロジェクト全体をダウンロードできます。

Lazarusを起動して新規プロジェクトを始めましょう。通常、Lazarusを起動すると新規プロジェクトの状態なのですが、明示的にプロジェクトを新規作成するには、メニューから[プロジェクト > 新規プロジェクト]をクリックします。そして、「アプリケーション」を選択して「OK」ボタンを押します。

  • Lazarusで新規プロジェクトを作成したところ

この時点でプロジェクトを保存しましょう。メニューから[プロジェクト > プロジェクト保存]をクリックして、分かりやすいフォルダを選んで「AIChat」などの名前でプロジェクトを保存しましょう。次いで、ユニットやフォームの名前を指定するダイアログが開きますが、デフォルトの名前のまま保存してください。

  • プロジェクトを保存したところ

最新のcurlコマンドをダウンロードしよう

ChatGPTの良いところは、どんなプログラミング言語からでも、Web APIを経由してその機能を利用できる点にあります。OpenAIは公式にPascalをサポートしているわけではありませんが、Pascalからcurlコマンドを実行して、手軽にChatGPTのAPIにアクセスできます。

curlコマンドは、Windows 10 バージョン1803以降では標準でインストールされていますが、それ以前のバージョンを使っていたり、最新のcurlコマンドを利用する方が安心です。Windowsを使っている場合には、こちら から最新のcurlをダウンロードしましょう。ZIPファイルを解凍したら、ファイル一式を、先ほど作成したLazarusのプロジェクトフォルダにコピーしましょう。

API経由でChatGPTを使う方法

次に、ChatGPTを自作アプリに組み込むために、OpenAIのAPIキーを取得しましょう。ChatGPTのAPIを使うために、こちらのOpenAIの開発者プラットフォームにアクセスしましょう。

はじめての場合は、画面右上の「Sign up」からアカウントを作成しましょう。最初は無料枠があるので、気軽に始めることができます。

そして、ログインしたら、APIキーを取得するには、画面上部のダッシュボード(Dashboard)をクリックし、画面左側の「API Keys」をクリックします。そして、画面上部にある「+ Create new secret key」をクリックします。すると、「sk-xxxxx」のようなAPIキーが生成されます。なお、APIキーは作成後一度しか表示されないので、必ず、このAPIキーを覚えておきましょう。

  • OpenAIのAPIキーを取得しよう

APIキーを環境変数に登録しよう

そして、取得したAPIキーは、環境変数「OPENAI_API_KEY」に登録しましょう。

Windowsであれば、Windowsメニューにある検索ボックスに「システム環境変数の編集」と入力して表示される「システムのプラパティ」で「環境変数」ボタンを押します。そして、「新規」ボタンをクリックし、変数名に「OPENAI_API_KEY」、変数値に「sk-xxxxxxxx」のようなAPIキーを指定します。

  • Windowsの環境変数にOPENAI_API_KEYを追加しよう

Lazarusで画面をデザインしよう

Lazarusに戻って、チャット画面をデザインしましょう。雰囲気をだすために適当な画像を貼り付けましょう。本連載1回目の内容を参考にして、コンポーネントパレットから、コンポーネントを貼り付けていきましょう。次のような画面になるようにします。

  • Lazarusで画面デザインしよう - 完成形

なお、次のように、コンポーネントパレットの[Additional]タブからTImageを貼り付け、そこに任意のJPEG画像を貼り付けます。そして、[Standard]タブからTButtonや、TMemoを貼り付けて、nameプロパティにコンポーネントの名前を設定します。

  • 貼り付けたコンポーネントの詳細 - 配置手順

今回のプログラムで重要なコンポーネントの名前は次の表の通りです。

コンポーネント名 種類 説明
memoLog TMemo チャットのログを表示するエディタ
memoUser TMemo ユーザーの発言内容を入力するエディタ
btnSend TButton 送信ボタン

なお、送信ボタンのbtnSendは、Captionプロパティを「送信」と指定し、memoLogのScrollBarsを「ssAutoBoth」と指定しましょう。

プログラムを記述しよう

こちらに、curlコマンドを使ってChatGPTにアクセスするライブラリ(Unitファイル)をアップロードしています。これをダウンロードします。

そして、プロジェクトファイルに「ChatGPTUnit.pas」という名前でコピーします。続いて、LazarusのIDEを次のように操作します。

- (1) [ファイル > 開く]でファイル「ChatGPTUnit.pas」を開きます。
- (2) [プロジェクト > プロジェクトに編集中のファイルを追加]をクリックします。
- (3) ソースエディタでUnit1を選択した状態で [ソース > ユニットをUses節に追加]をクリックします。
- (4) 「ChatGPTUnit」を選んで「実装部」に追加します。
  • ChatGPTUnitを追加しよう

ソースエディタで、Unit1を表示すると、「implementation」と書かれている部分のすぐ下に、次のような宣言が追加されているのを確認できるでしょう。

implementation
uses ChatGPTUnit; // ← ユニットが追加された

それでは、プログラムを記述していきましょう。まず、メニューから[表示 > ソースエディタ]をクリックしましょう。そして、エディタ上部の[Unit1]をアクティブにします。

最初に送信ボタン(btnSend)をクリックした時の処理を記述しましょう。Lazarusのフォーム上でbtnSendをダブルクリックして、クリックイベントを設定しましょう。

procedure TForm1.btnSendClick(Sender: TObject);
var
  result: string;
begin
  // 以下のコードを追加
  btnSend.Enabled := False;
  try
    result := CallChatGPTAPI(memoUser.Text); // ChatGPTを呼び出す
    memoLog.Text := '> ' + memoUser.Text + #13#10 +
        '------------------------------' + #13#10 +
        result + #13#10 +
        '==============================' + #13#10 +
        Trim(memoLog.Text); // 結果をmemoLogに追加
    memoUser.Text := '';
  finally
    btnSend.Enabled := True;
  end;
end;

以上で完了です。実行ボタンを押してプログラムを実行しましょう。画面上部にある実行ボタン「▶」をクリックするか、メニューから「実行 > 実行」をクリックしましょう。はじめて実行する際には、デバッグレベルを指定するダイアログが出ますが、[OK]ボタンを押すとコンパイルが行われ、プログラムが実行されます。

  • AI秘書アプリを実行したところ

プログラムが実行されたら、画面下部にAI秘書に尋ねたいことを記述して「送信」ボタンを押します。すると、ChatGPT APIにアクセスして結果を取得し、結果が画面上部のログに表示されます。

ChatGPTを呼び出すプログラムを確認しよう

上記の手順では、ユニット「ChatGPTUnit.pas」を追加しただけでしたが、このライブラリは160行程度で、もそれほど難しいものではないので、内容を確認してみましょう。curlコマンドを使って、ChatGPTのAPIを呼び出し、その戻り値を解析して返すだけです。

以下のプログラムは、curlコマンドを呼び出すコマンドを作成している部分です。

// リクエストJSON作成 --- (*1)
JsonRequest := TJSONObject.Create;
try
  JsonRequest.Add('model', MODEL_NAME);
  JsonRequest.Add('messages', TJSONArray.Create([
    TJSONObject.Create(['role', 'user', 'content', Prompt])
  ]));
  JsonRequest.Add('temperature', 0.7);
  SaveToFile(jsonfile, JsonRequest.AsJSON); // リクエストをファイルに保存
finally
  JsonRequest.Free;
end;
ctype := 'Content-Type: application/json';
auth :=  'Authorization: Bearer ' + APIKey;
// コマンドを構築 --- (*2)
cmd := Format('"%s" %s -H "%s" -H "%s" -d @"%s" > "%s"', [
    curl, API_URL, ctype, auth, jsonfile, resfile]);
// バッチファイルに保存 --- (*3)
SaveToFile(batfile, cmd);
// 実行 --- (*4)
ProcessExecuteHide(batfile, []);
// 実行結果を読みだす --- (*5)
body := LoadFromFile(resfile);
Result := ParseChatGPTResponse(body);

プログラムの(*1)で、ChatGPTに送信するデータをJSON形式で作成します。(*2)ではcurlコマンドを構築します。Format関数を使うことで、長いパラメータを効率的に組み立てます。そして、(*3)ではバッチファイルにコマンドを保存します。(*4)ではバッチファイルを実行して、(*5)で実行結果を読み出します。

Pascalは型に厳格であるため、JSON形式を扱うのは、ちょっと面倒なのですが、fpjsonというユニットが標準で添付しているため、これを使ってJSONデータの読み書きが可能となっています。

まとめ

以上、今回は、LazarusでAI秘書アプリを作ってみました。やはり生成AIは面白いです。自作のプログラムから生成AIを利用することで、生成AIの出力を自由に加工することもできますし、何より愛着が沸きますね。

主要プログラミング言語であれば、OpenAIからChatGPT APIを利用するための公式のライブラリが提供されています。しかし、Pascal用のものはないので自分でなんとかしなくてはなりません。今回はcurlコマンドを使うことで、手軽にChatGPTのAPIを利用できることを利用したプログラムを作ってみました。

なければ自分で作ったり、既にあるものを活用すれば良いだけです。むしろ、プログラミングの楽しみが増えるというものです。これからもLazarusで楽しくアプリを開発しましょう。

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。これまで50冊以上の技術書を執筆した。直近では、「大規模言語モデルを使いこなすためのプロンプトエンジニアリングの教科書(マイナビ出版)」「Pythonでつくるデスクトップアプリ(ソシム)」「実践力を身につける Pythonの教科書 第2版」「シゴトがはかどる Python自動処理の教科書(マイナビ出版)」など。