ProcessingでChatGPTを動かす

# はじめに
本記事は、[Processing Advent Calendar 2023](https://adventar.org/calendars/8532)参加記事です。
この記事では、Processing（Java）でChatGPT（GPTのAPI）を使ったコードを紹介します！
![sketch.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/929801/fdb20234-bf61-742f-1466-4199525e71da.gif)

# 必要な準備
## OpenAI APIキーの取得
GPT（ChatGPT）のAPIを利用するためには、APIキーを作る必要があります。
作り方は↓のサイトを参考にしてください。

参照：

https://notai.jp/openai-get-api-key/

> APIの使用は従量課金制です。利用料金等をよく確認してから使用しましょう。また、2023年12月現在は、最初の3ヶ月間にのみ使える無料利用枠が存在します。

## ライブラリのインポート
この記事のコードでは、テキストボックスの作成にControlP5を使います。
インポートの方法は↓のサイトなどを参考にしてください。

参照：

https://blanche-toile.com/tools/processing-library

# プログラムコード
```Java
// APIを呼び出す用
import org.apache.http.HttpEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

// テキストボックス用
import javax.swing.*;
import java.awt.*;
import controlP5.*;

// テキストボックス
ControlP5 cp5;
JLayeredPane pane;
JTextField jt1;

// GPT
GPT gpt;
String output = "";

void setup() {
    size(800, 600);
    
    PFont font = createFont("Meiryo", 24);
    textFont(font);
    cp5 = new ControlP5(this);
    ControlFont cf1 = new ControlFont(font, 24);
    cp5.setFont(cf1);
    java.awt.Canvas canvas =
            (java.awt.Canvas) surface.getNative();
    pane = (JLayeredPane) canvas.getParent().getParent();
  
    jt1 = new JTextField();
    jt1.setBounds(10, 10, 400, 40);
    pane.add(jt1);
    
    cp5.addBang("enter",420,10,60,40)
        .setCaptionLabel("入力")
        .getCaptionLabel()
        .align(ControlP5.CENTER, ControlP5.CENTER)
        ;

    // 一つ目の引数にOpenAIのAPIキーを入れる
    gpt = new GPT("<あなたのAPIキー>", "あなたは5才の子供です。私の質問に元気に答えてね。");
}

void draw() {
  background(255);
  fill(0);
  for (int i = 0; i < output.length(); i += 30) {
    String line = output.substring(i, min(output.length(), i + 30));
    text(line, 10, 100 + i / 30 * 30);
  }
}

void enter() {
  String input = jt1.getText();
  jt1.setText("");
  println(input);
  if (input != "") {
    output = gpt.getResponse(input);
    println(output);
  }
}

public class GPT {
    String API_KEY;
    String system;

    public GPT (String API_KEY, String system) {
        this.API_KEY = API_KEY;
        this.system = system;
    }

    public String getResponse (String message) {
        JSONObject jobject = new JSONObject();
        jobject.setString("model", "gpt-3.5-turbo-1106");
        JSONArray messages = new JSONArray();
        JSONObject system = new JSONObject();
        system.setString("role", "system");
        system.setString("content", this.system);
        JSONObject user = new JSONObject();
        user.setString("role", "user");
        user.setString("content", message);
        messages.setJSONObject(0, system);
        messages.setJSONObject(1, user);
        jobject.setJSONArray("messages", messages);
        jobject.setInt("max_tokens", 500);
        jobject.setFloat("temperature", 0.01);

        String output = "";
        for (int i = 0; i < 5; i++) {
            try {
                HttpPost httpPost = new HttpPost("https://api.openai.com/v1/chat/completions");
                httpPost.setHeader("Content-Type", "application/json; charset=UTF-8");
                httpPost.setHeader("Authorization", "Bearer " + this.API_KEY);
                
                StringEntity entity = new StringEntity(jobject.toString(), "UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
                
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpResponse response = httpClient.execute(httpPost);

                HttpEntity rentity = response.getEntity();
                if (rentity != null) {
                    String rstring = EntityUtils.toString(rentity, "UTF-8");
                    JSONObject rjson = parseJSONObject(rstring);
                    output = rjson.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
                    EntityUtils.consume(rentity);
                }

                httpClient.getConnectionManager().shutdown();

                break;
            } catch (Exception e) {
                println("[postHttpRequest]" + e);
            }
        }

        return output;
    }
}
```

> 今後解説を追記していきます。