Added model selector

master
M66B 2 weeks ago
parent 3e5abc7e20
commit 7f26f9d6f2

@ -35,6 +35,7 @@ import org.jsoup.nodes.Document;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public class AI { public class AI {
@ -243,4 +244,13 @@ public class AI {
Document doc = HtmlHelper.sanitizeView(context, JsoupEx.parse(html), false); Document doc = HtmlHelper.sanitizeView(context, JsoupEx.parse(html), false);
return HtmlHelper.fromDocument(context, doc, null, null); return HtmlHelper.fromDocument(context, doc, null, null);
} }
static List<String> getModelList(Context context) throws JSONException, IOException {
if (OpenAI.isAvailable(context)) {
List<String> models = OpenAI.getModelList(context);
Collections.sort(models);
return models;
} else
return new ArrayList<>();
}
} }

@ -19,6 +19,8 @@ package eu.faircode.email;
Copyright 2018-2026 by Marcel Bokhorst (M66B) Copyright 2018-2026 by Marcel Bokhorst (M66B)
*/ */
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -39,6 +41,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.cardview.widget.CardView; import androidx.cardview.widget.CardView;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -80,6 +83,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
private EditText etOpenAi; private EditText etOpenAi;
private TextInputLayout tilOpenAi; private TextInputLayout tilOpenAi;
private EditText etOpenAiModel; private EditText etOpenAiModel;
private ImageButton ibOpenAiModel;
private EditText etOpenAiMaxTokens; private EditText etOpenAiMaxTokens;
private SwitchCompat swOpenMultiModal; private SwitchCompat swOpenMultiModal;
private TextView tvOpenAiTemperature; private TextView tvOpenAiTemperature;
@ -157,6 +161,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
etOpenAi = view.findViewById(R.id.etOpenAi); etOpenAi = view.findViewById(R.id.etOpenAi);
tilOpenAi = view.findViewById(R.id.tilOpenAi); tilOpenAi = view.findViewById(R.id.tilOpenAi);
etOpenAiModel = view.findViewById(R.id.etOpenAiModel); etOpenAiModel = view.findViewById(R.id.etOpenAiModel);
ibOpenAiModel = view.findViewById(R.id.ibOpenAiModel);
etOpenAiMaxTokens = view.findViewById(R.id.etOpenAiMaxTokens); etOpenAiMaxTokens = view.findViewById(R.id.etOpenAiMaxTokens);
swOpenMultiModal = view.findViewById(R.id.swOpenMultiModal); swOpenMultiModal = view.findViewById(R.id.swOpenMultiModal);
tvOpenAiTemperature = view.findViewById(R.id.tvOpenAiTemperature); tvOpenAiTemperature = view.findViewById(R.id.tvOpenAiTemperature);
@ -429,6 +434,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("openai_enabled", checked).apply(); prefs.edit().putBoolean("openai_enabled", checked).apply();
etOpenAiModel.setEnabled(checked); etOpenAiModel.setEnabled(checked);
ibOpenAiModel.setEnabled(checked);
etOpenAiMaxTokens.setEnabled(checked); etOpenAiMaxTokens.setEnabled(checked);
swOpenMultiModal.setEnabled(checked); swOpenMultiModal.setEnabled(checked);
sbOpenAiTemperature.setEnabled(checked); sbOpenAiTemperature.setEnabled(checked);
@ -513,6 +519,50 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
} }
}); });
ibOpenAiModel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new SimpleTask<List<String>>() {
@Override
protected List<String> onExecute(Context context, Bundle args) throws Throwable {
return AI.getModelList(context);
}
@Override
protected void onExecuted(Bundle args, List<String> data) {
String current = prefs.getString("openai_model", null);
CharSequence[] models = new CharSequence[data.size()];
int selected = -1;
for (int i = 0; i < data.size(); i++) {
String model = data.get(i);
models[i] = model;
if (current != null && current.equals(model))
selected = i;
}
new AlertDialog.Builder(v.getContext())
.setIcon(R.drawable.twotone_search_24)
.setTitle(R.string.title_advanced_openai_model)
.setSingleChoiceItems(models, selected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String model = models[which].toString();
etOpenAiModel.setText(model);
dialog.dismiss();
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
@Override
protected void onException(Bundle args, Throwable ex) {
}
}.execute(FragmentOptionsIntegrations.this, new Bundle(), "ai:models");
}
});
etOpenAiMaxTokens.addTextChangedListener(new TextWatcher() { etOpenAiMaxTokens.addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {

@ -169,6 +169,17 @@ public class OpenAI {
return choices; return choices;
} }
static List<String> getModelList(Context context) throws JSONException, IOException {
JSONObject jresponse = call(context, "GET", "models", null);
List<String> models = new ArrayList<>();
JSONArray data = jresponse.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
JSONObject item = data.getJSONObject(i);
models.add(item.getString("id"));
}
return models;
}
private static String getUri(Context context) { private static String getUri(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String endpoint = prefs.getString("openai_uri", BuildConfig.OPENAI_ENDPOINT); String endpoint = prefs.getString("openai_uri", BuildConfig.OPENAI_ENDPOINT);

@ -663,10 +663,21 @@
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:inputType="text" android:inputType="text"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@id/ibOpenAiModel"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvOpenAiModel" /> app:layout_constraintTop_toBottomOf="@id/tvOpenAiModel" />
<ImageButton
android:id="@+id/ibOpenAiModel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:contentDescription="@string/title_search"
android:tooltipText="@string/title_search"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/etOpenAiModel"
app:srcCompat="@drawable/twotone_search_24" />
<TextView <TextView
android:id="@+id/tvOpenAiMaxTokens" android:id="@+id/tvOpenAiMaxTokens"
android:layout_width="wrap_content" android:layout_width="wrap_content"

Loading…
Cancel
Save