はじめに
近頃のトレンドのChatGpt。Androidの環境でOpenAi APIを叩いてみた。
既に同じような記事は存在するが、AnroidのJavaっていう点では少ないので記載。
準備
まずはAPIを呼び出せるように設定を行います。
https://platform.openai.com/overview
上記URLでアカウントを作成し、ログインしましょう。APIを利用するには、別途料金が必要になってきます。
アプリ概要
テキストに入力した内容をボタンで送信。バックグランドでOpenAPIに要求し、アウトプット用テキストに出力する簡単な仕組み。
実装
依存関係
必要な依存関係をビルドシステム(gradle)に記載
依存関係を確認する際には下記サイトを参照。OpenAi API Javaの一覧が記載されている。
https://mvnrepository.com/artifact/com.theokanning.openai-gpt3-java
初心者のために行っておくが、依存関係でOpenAi APIを取り込まないとクラスなども呼べない。
dependencies {
// https://mvnrepository.com/artifact/com.theokanning.openai-gpt3-java/api
implementation group: 'com.theokanning.openai-gpt3-java', name: 'api', version: '0.2.0'
// https://mvnrepository.com/artifact/com.theokanning.openai-gpt3-java/service
implementation group: 'com.theokanning.openai-gpt3-java', name: 'service', version: '0.14.0'
// https://mvnrepository.com/artifact/com.theokanning.openai-gpt3-java/client
implementation group: 'com.theokanning.openai-gpt3-java', name: 'client', version: '0.16.0'
}
ソースコード
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private EditText mInputText, mOutputText;
private Button mRequestBtn;
private ChatGptService mChatGptService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInputText = findViewById(R.id.inputText);
mOutputText = findViewById(R.id.outputText);
mRequestBtn = findViewById(R.id.requestBtn);
mChatGptService = new ChatGptService(getApplicationContext());
}
@Override
protected void onResume() {
super.onResume();
// 回答内容を要求
mRequestBtn.setOnClickListener(view -> {
Log.i(TAG, "onClick()");
String inputText = mInputText.getText().toString();
mChatGptService.requestChatGpt(inputText, new ChatGptService.Callback() {
@Override
public void onRequest() {
mRequestBtn.setEnabled(false);
}
@Override
public void onFinishedRequest(String result) {
mOutputText.setText(result);
mRequestBtn.setEnabled(true);
}
});
});
}
}
ChatGpServiceクラス
OpenAi APIをバックランドで叩くクラスです。
バックランドとのやり取りには、handlerThreadを作成して、 Handlerでやり取りを行う。ここに関しては本題から外れるので詳しく話しません。OpenAi AIPを叩くには、ネットワーク通信が必要になってきます。バックグランドでの実行を行うようにしましょう。
それに伴いPermissionの設定も必要になってきます。
<uses-permission android:name="android.permission.INTERNET" />
/**
* バックグランドでOpenAi APIをコールするクラス
*/
public class ChatGptService {
private static final String TAG = ChatGptService.class.getSimpleName();
private final Object mObject = new Object();
private HandlerThread mHandlerThread;
private ChatGptHandler mChatGptHandler;
private Callback mCallback;
// TODO:key-codeの保存方法は変更する
private static final String key_token = "自分のtoken";
private OpenAiService mOpenAiService;
private SharedPreferences mPhrasingSettingPrefs;
private static final int DELAY_TIME = 60;
private static final String DEFAULT_MODE ="通常通り";
public ChatGptService(Context context) {
// スレッドはrequestChatGptの時に作成
mOpenAiService = new OpenAiService(key_token, Duration.ofSeconds(DELAY_TIME));
}
/**
* リクエストを要求する
* @param inputText
*/
public void requestChatGpt(String inputText, Callback callback) {
if (mCallback == null) {
mCallback = callback;
}
mCallback.onRequest();
if (mHandlerThread == null) {
mHandlerThread = new HandlerThread("ChatGptService");
mHandlerThread.start();
}
mChatGptHandler = new ChatGptHandler(mHandlerThread.getLooper() ,inputText, mPhrasingSettingPrefs.getString(PHRASING_MODE, DEFAULT_MODE));
//バックグランドにMessage送信
Message message = new Message();
message.what = ChatGptHandler.REQUEST_MSG;
mChatGptHandler.sendMessage(message);
}
class ChatGptHandler extends Handler {
private static final int REQUEST_MSG = 0;
private String mInputText;
private String mContent;
private ChatMessage mChatMessage;
private List<ChatMessage> mMessages;
private ChatMessage mUserMessage;
ChatGptHandler(Looper looper, String inputText) {
super(looper);
mInputText = inputText;
// TODO
mContent = "";
mMessages = new ArrayList<>();
mChatMessage = new ChatMessage("system", mContent);
mMessages.add(mChatMessage);
mUserMessage = new ChatMessage("user", mInputText);
mMessages.add(mUserMessage);
}
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case REQUEST_MSG:
Log.i(TAG, "handleMessage:" + "REQUEST_MSG");
requestChatGpt();
break;
default:
Log.w(TAG, "Nothing message");
break;
}
}
/**
* inputされたchat内容を返答する
*/
private void requestChatGpt() {
ChatCompletionRequest chatCompletionRequest =
ChatCompletionRequest.builder()
.model("gpt-3.5-turbo-0613")
.messages(mMessages)
.maxTokens(2048)
.build();
ChatCompletionResult chatCompletionResult = mOpenAiService.createChatCompletion(chatCompletionRequest);
String resultText = chatCompletionResult.getChoices().get(0).getMessage().getContent();
Log.i(TAG, "result:" + resultText);
notifyFinishedRequest(mCallback, resultText);
}
private void notifyFinishedRequest(ChatGptService.Callback callback, String result) {
final Handler handler = new Handler(Looper.getMainLooper());
final ChatGptService.Callback callbackImpl = callback;
if (callbackImpl == null) {
Log.w(TAG, "Callback is null");
return;
}
synchronized (mObject) {
handler.post(new Runnable() {
@Override
public void run() {
callbackImpl.onFinishedRequest(result);
}
});
}
}
}
interface Callback {
/**
* リクエストが始まった時のコールバック
*/
void onRequest();
/**
* リクエスト結果を返すコールバック
* @param result 結果内容
*/
void onFinishedRequest(String result);
}
}
ActivtiyのLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/phrasingSettingText"
android:layout_width="0.0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"/>
<Button
android:id="@+id/phrasingSettingsBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/phrasingChange"/>
</LinearLayout>
<EditText
android:id="@+id/inputText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/requestBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="30dp"
android:text="@string/request" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/outputText"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</ScrollView>
</LinearLayout>
まとめ
簡単なOpenAI APIを利用する簡易アプリを作成してみました
最近では、AIと英会話をするようなアプリも作成されており、そのようなアプリもOpenAI APIを利用してるのでしょうかね。次回はそのようなアプリの作成をしてみたいと思います。