From cd14ca45772643bd36e03225ffea81073051dc8f Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 19 May 2024 17:57:05 +0200 Subject: [PATCH] Refactoring --- app/src/main/java/eu/faircode/email/AI.java | 71 +++++++++++++------ .../java/eu/faircode/email/ActivityBase.java | 4 +- .../email/FragmentDialogSummarize.java | 24 +------ .../main/java/eu/faircode/email/OpenAI.java | 5 +- 4 files changed, 54 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/AI.java b/app/src/main/java/eu/faircode/email/AI.java index 98ba2ce307..65ade676c4 100644 --- a/app/src/main/java/eu/faircode/email/AI.java +++ b/app/src/main/java/eu/faircode/email/AI.java @@ -30,11 +30,14 @@ import androidx.preference.PreferenceManager; import org.json.JSONException; import org.jsoup.nodes.Document; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class AI { + private static final int MAX_SUMMARIZE_TEXT_SIZE = 10 * 1024; + static boolean isAvailable(Context context) { return (OpenAI.isAvailable(context) || Gemini.isAvailable(context)); } @@ -47,10 +50,12 @@ public class AI { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); String model = prefs.getString("openai_model", OpenAI.DEFAULT_MODEL); float temperature = prefs.getFloat("openai_temperature", OpenAI.DEFAULT_TEMPERATURE); + boolean multimodal = prefs.getBoolean("openai_multimodal", true); OpenAI.Message message; if (body instanceof Spannable) - message = new OpenAI.Message(OpenAI.USER, OpenAI.Content.get((Spannable) body, id, context)); + message = new OpenAI.Message(OpenAI.USER, + OpenAI.Content.get((Spannable) body, id, multimodal, context)); else message = new OpenAI.Message(OpenAI.USER, new OpenAI.Content[]{ new OpenAI.Content(OpenAI.CONTENT_TEXT, body.toString())}); @@ -65,9 +70,9 @@ public class AI { if (sb.length() > 0) sb.append('\n'); sb.append(content.getContent() - .replaceAll("^\\n+", "").replaceAll("\\n+$", "")); + .replaceAll("^\\n+", "") + .replaceAll("\\n+$", "")); } - return sb.toString(); } else if (Gemini.isAvailable(context)) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -77,11 +82,17 @@ public class AI { Gemini.Message message = new Gemini.Message(Gemini.USER, new String[]{Gemini.truncateParagraphs(body.toString())}); Gemini.Message[] completions = Gemini.generate(context, model, new Gemini.Message[]{message}, temperature, 1); - if (completions.length == 0) - return null; - return TextUtils.join("\n", completions[0].getContent()) - .replaceAll("^\\n+", "").replaceAll("\\n+$", ""); + StringBuilder sb = new StringBuilder(); + for (Gemini.Message completion : completions) + for (String result : completion.getContent()) { + if (sb.length() > 0) + sb.append('\n'); + sb.append(result + .replaceAll("^\\n+", "") + .replaceAll("\\n+$", "")); + } + return sb.toString(); } else return null; } @@ -96,33 +107,47 @@ public class AI { return context.getString(R.string.title_summarize); } - static String summarize(Context context, long id, String subject, Document d) throws JSONException, IOException { + static String getSummaryText(Context context, EntityMessage message) throws JSONException, IOException { + File file = message.getFile(context); + if (!file.exists()) + return null; + + Document d = JsoupEx.parse(file); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean remove_signatures = prefs.getBoolean("remove_signatures", false); + if (remove_signatures) + HtmlHelper.removeSignatures(d); + + HtmlHelper.removeQuotes(d); + + d = HtmlHelper.sanitizeView(context, d, false); + + HtmlHelper.truncate(d, MAX_SUMMARIZE_TEXT_SIZE); + if (OpenAI.isAvailable(context)) { String model = prefs.getString("openai_model", OpenAI.DEFAULT_MODEL); float temperature = prefs.getFloat("openai_temperature", OpenAI.DEFAULT_TEMPERATURE); String prompt = prefs.getString("openai_summarize", OpenAI.DEFAULT_SUMMARY_PROMPT); + boolean multimodal = prefs.getBoolean("openai_multimodal", true); List input = new ArrayList<>(); input.add(new OpenAI.Message(OpenAI.USER, new OpenAI.Content[]{new OpenAI.Content(OpenAI.CONTENT_TEXT, prompt)})); - if (!TextUtils.isEmpty(subject)) + if (!TextUtils.isEmpty(message.subject)) input.add(new OpenAI.Message(OpenAI.USER, - new OpenAI.Content[]{new OpenAI.Content(OpenAI.CONTENT_TEXT, subject)})); + new OpenAI.Content[]{new OpenAI.Content(OpenAI.CONTENT_TEXT, message.subject)})); SpannableStringBuilder ssb = HtmlHelper.fromDocument(context, d, null, null); input.add(new OpenAI.Message(OpenAI.USER, - OpenAI.Content.get(ssb, id, context))); + OpenAI.Content.get(ssb, message.id, multimodal, context))); - OpenAI.Message[] result = + OpenAI.Message[] completions = OpenAI.completeChat(context, model, input.toArray(new OpenAI.Message[0]), temperature, 1); - if (result.length == 0) - return null; - StringBuilder sb = new StringBuilder(); - for (OpenAI.Message completion : result) + for (OpenAI.Message completion : completions) for (OpenAI.Content content : completion.getContent()) if (OpenAI.CONTENT_TEXT.equals(content.getType())) { if (sb.length() != 0) @@ -140,13 +165,17 @@ public class AI { return null; Gemini.Message content = new Gemini.Message(Gemini.USER, new String[]{prompt, text}); - Gemini.Message[] result = + Gemini.Message[] completions = Gemini.generate(context, model, new Gemini.Message[]{content}, temperature, 1); - if (result.length == 0) - return null; - - return TextUtils.join("\n", result[0].getContent()); + StringBuilder sb = new StringBuilder(); + for (Gemini.Message completion : completions) + for (String result : completion.getContent()) { + if (sb.length() != 0) + sb.append('\n'); + sb.append(result); + } + return sb.toString(); } else return null; } diff --git a/app/src/main/java/eu/faircode/email/ActivityBase.java b/app/src/main/java/eu/faircode/email/ActivityBase.java index 2cb772db2c..786f3c30d7 100644 --- a/app/src/main/java/eu/faircode/email/ActivityBase.java +++ b/app/src/main/java/eu/faircode/email/ActivityBase.java @@ -117,8 +117,8 @@ abstract class ActivityBase extends AppCompatActivity implements SharedPreferenc toolbar.setPopupTheme(getThemeId()); if (hide_toolbar) { AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbar.getLayoutParams(); - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL - | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); toolbar.setLayoutParams(params); getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java b/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java index 96e7fcf1e7..b38baeaa95 100644 --- a/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java +++ b/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java @@ -34,14 +34,9 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentManager; import androidx.preference.PreferenceManager; -import org.jsoup.nodes.Document; - -import java.io.File; import java.util.Date; public class FragmentDialogSummarize extends FragmentDialogBase { - private static final int MAX_SUMMARIZE_TEXT_SIZE = 10 * 1024; - @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { @@ -92,25 +87,8 @@ public class FragmentDialogSummarize extends FragmentDialogBase { if (message == null || !message.content) return null; - File file = EntityMessage.getFile(context, id); - if (!file.exists()) - return null; - - Document d = JsoupEx.parse(file); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean remove_signatures = prefs.getBoolean("remove_signatures", false); - if (remove_signatures) - HtmlHelper.removeSignatures(d); - - HtmlHelper.removeQuotes(d); - - d = HtmlHelper.sanitizeView(context, d, false); - - HtmlHelper.truncate(d, MAX_SUMMARIZE_TEXT_SIZE); - long start = new Date().getTime(); - String summary = AI.summarize(context, id, message.subject, d); + String summary = AI.getSummaryText(context, message); args.putLong("elapsed", new Date().getTime() - start); return summary; diff --git a/app/src/main/java/eu/faircode/email/OpenAI.java b/app/src/main/java/eu/faircode/email/OpenAI.java index eab61bd67c..0e06ddc696 100644 --- a/app/src/main/java/eu/faircode/email/OpenAI.java +++ b/app/src/main/java/eu/faircode/email/OpenAI.java @@ -277,10 +277,7 @@ public class OpenAI { return this.content; } - static Content[] get(Spannable ssb, long id, Context context) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean multimodal = prefs.getBoolean("openai_multimodal", true); - + static Content[] get(Spannable ssb, long id, boolean multimodal, Context context) { DB db = DB.getInstance(context); List contents = new ArrayList<>(); int start = 0;