diff --git a/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart b/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart new file mode 100644 index 000000000..44d9821c8 --- /dev/null +++ b/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart @@ -0,0 +1,78 @@ +import '../../presentation/model/ai_action.dart'; +import '../../presentation/model/ai_scribe_menu_action.dart'; + +// TODO +// In a near future, prompts will be loaded from a remote source +class AIPrompts { + static String buildPrompt(AIAction action, String? text) { + return switch (action) { + PredefinedAction(action: final menuAction) => buildPredefinedPrompt(menuAction, text ?? ''), + CustomPromptAction(prompt: final customPrompt) => buildCustomPrompt(customPrompt, text), + }; + } + + static String buildPredefinedPrompt(AIScribeMenuAction action, String text) { + switch (action) { + case AIScribeMenuAction.correctGrammar: + return correctGrammar(text); + case AIScribeMenuAction.improveMakeShorter: + return improveMakeShorter(text); + case AIScribeMenuAction.improveExpandContext: + return improveExpandContext(text); + case AIScribeMenuAction.improveEmojify: + return improveEmojify(text); + case AIScribeMenuAction.improveTransformToBullets: + return improveTransformToBullets(text); + case AIScribeMenuAction.changeToneProfessional: + return changeToneTo(text, 'professional'); + case AIScribeMenuAction.changeToneCasual: + return changeToneTo(text, 'casual'); + case AIScribeMenuAction.changeTonePolite: + return changeToneTo(text, 'polite'); + case AIScribeMenuAction.translateFrench: + return translateTo(text, 'French'); + case AIScribeMenuAction.translateEnglish: + return translateTo(text, 'English'); + case AIScribeMenuAction.translateRussian: + return translateTo(text, 'Russian'); + case AIScribeMenuAction.translateVietnamese: + return translateTo(text, 'Vietnamese'); + } + } + + static String improveMakeShorter(String text) { + return 'Make the following text shorter and more concise. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String improveExpandContext(String text) { + return 'Expand the context of the following text to make it more detailed and comprehensive. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String improveEmojify(String text) { + return 'Add appropriate emojis to the following text to make it more expressive. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String improveTransformToBullets(String text) { + return 'Transform the following text into a bulleted list format. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String correctGrammar(String text) { + return 'Correct grammar of the following text. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String changeToneTo(String text, String tone) { + return 'Change the tone of the following text to be more $tone. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String translateTo(String text, String language) { + return 'Translate the following text to $language. Output only the result. Preserve input formatting. Text:\n\n$text'; + } + + static String buildCustomPrompt(String customPrompt, String? text) { + if (text == null) { + return customPrompt; + } + + return '$customPrompt\n\nText:\n\n$text'; + } +} diff --git a/scribe/lib/scribe/ai/presentation/model/ai_action.dart b/scribe/lib/scribe/ai/presentation/model/ai_action.dart new file mode 100644 index 000000000..3a65c5c09 --- /dev/null +++ b/scribe/lib/scribe/ai/presentation/model/ai_action.dart @@ -0,0 +1,25 @@ +import 'ai_scribe_menu_action.dart'; + +sealed class AIAction { + const AIAction(); + + String get label; +} + +class PredefinedAction extends AIAction { + final AIScribeMenuAction action; + + const PredefinedAction(this.action); + + @override + String get label => action.fullLabel; +} + +class CustomPromptAction extends AIAction { + final String prompt; + + const CustomPromptAction(this.prompt); + + @override + String get label => 'Help me write'; +} diff --git a/scribe/lib/scribe/ai/presentation/model/ai_scribe_menu_action.dart b/scribe/lib/scribe/ai/presentation/model/ai_scribe_menu_action.dart new file mode 100644 index 000000000..8a1985544 --- /dev/null +++ b/scribe/lib/scribe/ai/presentation/model/ai_scribe_menu_action.dart @@ -0,0 +1,124 @@ +enum AIScribeMenuAction { + correctGrammar, + improveMakeShorter, + improveExpandContext, + improveEmojify, + improveTransformToBullets, + changeToneProfessional, + changeToneCasual, + changeTonePolite, + translateFrench, + translateEnglish, + translateRussian, + translateVietnamese; + + String get label { + switch (this) { + case AIScribeMenuAction.correctGrammar: + return 'Correct grammar'; + case AIScribeMenuAction.improveMakeShorter: + return 'Make it shorter'; + case AIScribeMenuAction.improveExpandContext: + return 'Expand context'; + case AIScribeMenuAction.improveEmojify: + return 'Emojify'; + case AIScribeMenuAction.improveTransformToBullets: + return 'Transform to bullets'; + case AIScribeMenuAction.changeToneProfessional: + return 'More professional'; + case AIScribeMenuAction.changeToneCasual: + return 'More casual'; + case AIScribeMenuAction.changeTonePolite: + return 'More polite'; + case AIScribeMenuAction.translateFrench: + return 'French'; + case AIScribeMenuAction.translateEnglish: + return 'English'; + case AIScribeMenuAction.translateRussian: + return 'Russian'; + case AIScribeMenuAction.translateVietnamese: + return 'Vietnamese'; + } + } + + AIScribeMenuCategory get category { + switch (this) { + case AIScribeMenuAction.correctGrammar: + return AIScribeMenuCategory.correctGrammar; + case AIScribeMenuAction.improveMakeShorter: + case AIScribeMenuAction.improveExpandContext: + case AIScribeMenuAction.improveEmojify: + case AIScribeMenuAction.improveTransformToBullets: + return AIScribeMenuCategory.improve; + case AIScribeMenuAction.changeToneProfessional: + case AIScribeMenuAction.changeToneCasual: + case AIScribeMenuAction.changeTonePolite: + return AIScribeMenuCategory.changeTone; + case AIScribeMenuAction.translateFrench: + case AIScribeMenuAction.translateEnglish: + case AIScribeMenuAction.translateRussian: + case AIScribeMenuAction.translateVietnamese: + return AIScribeMenuCategory.translate; + } + } + + String get fullLabel { + final categoryLabel = category.label; + if (category.hasSubmenu) { + return '$categoryLabel > $label'; + } else { + return label; + } + } +} + +enum AIScribeMenuCategory { + correctGrammar, + improve, + changeTone, + translate; + + String get label { + switch (this) { + case AIScribeMenuCategory.correctGrammar: + return 'Correct grammar'; + case AIScribeMenuCategory.improve: + return 'Improve'; + case AIScribeMenuCategory.changeTone: + return 'Change tone'; + case AIScribeMenuCategory.translate: + return 'Translate'; + } + } + + List get actions { + switch (this) { + case AIScribeMenuCategory.correctGrammar: + return [AIScribeMenuAction.correctGrammar]; + case AIScribeMenuCategory.improve: + return [ + AIScribeMenuAction.improveMakeShorter, + AIScribeMenuAction.improveExpandContext, + AIScribeMenuAction.improveEmojify, + AIScribeMenuAction.improveTransformToBullets, + ]; + case AIScribeMenuCategory.changeTone: + return [ + AIScribeMenuAction.changeToneProfessional, + AIScribeMenuAction.changeToneCasual, + AIScribeMenuAction.changeTonePolite, + ]; + case AIScribeMenuCategory.translate: + return [ + AIScribeMenuAction.translateFrench, + AIScribeMenuAction.translateEnglish, + AIScribeMenuAction.translateRussian, + AIScribeMenuAction.translateVietnamese, + ]; + } + } + + bool get hasSubmenu { + return actions.length > 1; + } +}