diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java
index 688a294c0a..7f788f3a2c 100644
--- a/app/src/main/java/eu/faircode/email/FragmentCompose.java
+++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java
@@ -2790,8 +2790,9 @@ public class FragmentCompose extends FragmentBase {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String model = prefs.getString("gemini_model", "gemini-pro");
+ float temperature = prefs.getFloat("gemini_temperature", 0.5f);
- return Gemini.generate(context, model, new String[]{Gemini.truncateParagraphs(body)});
+ return Gemini.generate(context, model, new String[]{Gemini.truncateParagraphs(body)}, temperature);
}
@Override
diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java b/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java
index 4aa3ef593a..b4e57f40c8 100644
--- a/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java
+++ b/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java
@@ -106,9 +106,10 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
return sb.toString();
} else if (Gemini.isAvailable(context)) {
String model = prefs.getString("gemini_model", "gemini-pro");
+ float temperature = prefs.getFloat("gemini_temperature", 0.5f);
String prompt = prefs.getString("gemini_summarize", Gemini.SUMMARY_PROMPT);
- String[] result = Gemini.generate(context, model, new String[]{prompt, text});
+ String[] result = Gemini.generate(context, model, new String[]{prompt, text}, temperature);
return TextUtils.join("\n", result);
}
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java b/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java
index 2638be48fc..0bbeb647c6 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java
@@ -90,6 +90,8 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
private EditText etGemini;
private TextInputLayout tilGemini;
private EditText etGeminiModel;
+ private TextView tvGeminiTemperature;
+ private SeekBar sbGeminiTemperature;
private EditText etGeminiSummarize;
private ImageButton ibGemini;
@@ -106,7 +108,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
"vt_enabled", "vt_apikey",
"send_enabled", "send_host", "send_dlimit", "send_tlimit",
"openai_enabled", "openai_uri", "openai_apikey", "openai_model", "openai_temperature", "openai_moderation", "openai_summarize",
- "gemini_enabled", "gemini_uri", "gemini_apikey", "gemini_model", "gemini_summarize"
+ "gemini_enabled", "gemini_uri", "gemini_apikey", "gemini_model", "gemini_temperature", "gemini_summarize"
));
@Override
@@ -162,6 +164,8 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
etGemini = view.findViewById(R.id.etGemini);
tilGemini = view.findViewById(R.id.tilGemini);
etGeminiModel = view.findViewById(R.id.etGeminiModel);
+ tvGeminiTemperature = view.findViewById(R.id.tvGeminiTemperature);
+ sbGeminiTemperature = view.findViewById(R.id.sbGeminiTemperature);
etGeminiSummarize = view.findViewById(R.id.etGeminiSummarize);
ibGemini = view.findViewById(R.id.ibGemini);
@@ -556,6 +560,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("gemini_enabled", checked).apply();
etGeminiModel.setEnabled(checked);
+ sbGeminiTemperature.setEnabled(checked);
etGeminiSummarize.setEnabled(checked);
if (checked)
swOpenAi.setChecked(false);
@@ -634,6 +639,24 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
}
});
+ sbGeminiTemperature.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ float temp = progress / 20f;
+ prefs.edit().putFloat("gemini_temperature", temp).apply();
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+ });
+
etGeminiSummarize.setHint(Gemini.SUMMARY_PROMPT);
etGeminiSummarize.addTextChangedListener(new TextWatcher() {
@Override
@@ -780,6 +803,12 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
tilGemini.getEditText().setText(prefs.getString("gemini_apikey", null));
etGeminiModel.setText(prefs.getString("gemini_model", null));
etGeminiModel.setEnabled(swGemini.isChecked());
+
+ temperature = prefs.getFloat("gemini_temperature", 0.5f);
+ tvGeminiTemperature.setText(getString(R.string.title_advanced_openai_temperature, NF.format(temperature)));
+ sbGeminiTemperature.setProgress(Math.round(temperature * 20));
+ sbGeminiTemperature.setEnabled(swGemini.isChecked());
+
etGeminiSummarize.setText(prefs.getString("gemini_summarize", null));
etGeminiSummarize.setEnabled(swGemini.isChecked());
} catch (Throwable ex) {
diff --git a/app/src/main/java/eu/faircode/email/Gemini.java b/app/src/main/java/eu/faircode/email/Gemini.java
index ea731db039..784bd6cce7 100644
--- a/app/src/main/java/eu/faircode/email/Gemini.java
+++ b/app/src/main/java/eu/faircode/email/Gemini.java
@@ -40,6 +40,8 @@ import java.util.Objects;
public class Gemini {
// https://ai.google.dev/models/gemini
+ static final String MODEL = "model";
+ static final String USER = "user";
static final String SUMMARY_PROMPT = "Summarize the following text:";
private static final int MAX_GEMINI_LEN = 4000; // characters
@@ -57,7 +59,7 @@ public class Gemini {
(!TextUtils.isEmpty(apikey) || !Objects.equals(getUri(context), BuildConfig.GEMINI_ENDPOINT)));
}
- static String[] generate(Context context, String model, String[] texts) throws JSONException, IOException {
+ static String[] generate(Context context, String model, String[] texts, float temperature) throws JSONException, IOException {
JSONArray jpart = new JSONArray();
for (String text : texts) {
JSONObject jtext = new JSONObject();
@@ -67,10 +69,17 @@ public class Gemini {
JSONObject jcontent0 = new JSONObject();
jcontent0.put("parts", jpart);
+ jcontent0.put("role", USER);
JSONArray jcontents = new JSONArray();
jcontents.put(jcontent0);
+
+ // https://ai.google.dev/api/python/google/generativeai/GenerationConfig
+ JSONObject jconfig = new JSONObject();
+ jconfig.put("temperature", temperature);
+
JSONObject jrequest = new JSONObject();
jrequest.put("contents", jcontents);
+ jrequest.put("generationConfig", jconfig);
String path = "models/" + Uri.encode(model) + ":generateContent";
diff --git a/app/src/main/res/layout/fragment_options_integrations.xml b/app/src/main/res/layout/fragment_options_integrations.xml
index 8869a0b4a4..402d8669ed 100644
--- a/app/src/main/res/layout/fragment_options_integrations.xml
+++ b/app/src/main/res/layout/fragment_options_integrations.xml
@@ -750,6 +750,31 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvGeminiModel" />
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/sbGeminiTemperature" />