From fabf3ec54f86b693fc11cec791f912eb167e9c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Poizat?= Date: Thu, 29 Jan 2026 15:48:21 +0100 Subject: [PATCH] Manage prompts as a "messages" object during prompt lifecycle Before, our prompts were just a string like "Translate this text: user text" and just before being sent to the backend, it was converted to an "messages" object compatible with OpenAI API like [{ "role": "user", "content": "Translate this text: user text"}]. Now, we use "messages" object directly when building the prompt because in the near future we will create more complex prompts with system content and user content so we will need "messages" object dirrectly. --- scribe/lib/scribe/ai/data/datasource/ai_datasource.dart | 3 ++- .../ai/data/datasource_impl/ai_datasource_impl.dart | 5 +++-- scribe/lib/scribe/ai/data/model/ai_message.dart | 6 ++++++ scribe/lib/scribe/ai/data/network/ai_api.dart | 8 ++------ .../scribe/ai/data/repository/ai_repository_impl.dart | 5 +++-- scribe/lib/scribe/ai/domain/constants/ai_prompts.dart | 9 +++++++-- .../ai/domain/repository/ai_scribe_repository.dart | 3 ++- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/scribe/lib/scribe/ai/data/datasource/ai_datasource.dart b/scribe/lib/scribe/ai/data/datasource/ai_datasource.dart index 73af09b4d..ef60dc6ab 100644 --- a/scribe/lib/scribe/ai/data/datasource/ai_datasource.dart +++ b/scribe/lib/scribe/ai/data/datasource/ai_datasource.dart @@ -1,5 +1,6 @@ +import 'package:scribe/scribe/ai/data/model/ai_message.dart'; import 'package:scribe/scribe/ai/domain/model/ai_response.dart'; abstract class AIDataSource { - Future generateMessage(String prompt); + Future generateMessage(List messages); } diff --git a/scribe/lib/scribe/ai/data/datasource_impl/ai_datasource_impl.dart b/scribe/lib/scribe/ai/data/datasource_impl/ai_datasource_impl.dart index 7ff7b02e7..d8fbfa9c6 100644 --- a/scribe/lib/scribe/ai/data/datasource_impl/ai_datasource_impl.dart +++ b/scribe/lib/scribe/ai/data/datasource_impl/ai_datasource_impl.dart @@ -1,5 +1,6 @@ import 'package:dio/dio.dart'; import 'package:scribe/scribe/ai/data/datasource/ai_datasource.dart'; +import 'package:scribe/scribe/ai/data/model/ai_message.dart'; import 'package:scribe/scribe/ai/data/network/ai_api.dart'; import 'package:scribe/scribe/ai/domain/model/ai_response.dart'; @@ -9,9 +10,9 @@ class AIDataSourceImpl implements AIDataSource { AIDataSourceImpl(this._aiApi); @override - Future generateMessage(String prompt) async { + Future generateMessage(List messages) async { try { - final apiResponse = await _aiApi.generateMessage(prompt); + final apiResponse = await _aiApi.generateMessage(messages); return AIResponse(result: apiResponse.content); } on DioException catch (e) { throw Exception('Failed to generate AI text: ${e.message}'); diff --git a/scribe/lib/scribe/ai/data/model/ai_message.dart b/scribe/lib/scribe/ai/data/model/ai_message.dart index eb8e6d571..e4cedee4e 100644 --- a/scribe/lib/scribe/ai/data/model/ai_message.dart +++ b/scribe/lib/scribe/ai/data/model/ai_message.dart @@ -5,6 +5,7 @@ part 'ai_message.g.dart'; @JsonSerializable() class AIMessage { static const String aiUserRole = 'user'; + static const String aiSystemRole = 'system'; final String role; final String content; @@ -23,4 +24,9 @@ class AIMessage { role: aiUserRole, content: content, ); + + factory AIMessage.ofSystem(String content) => AIMessage( + role: aiSystemRole, + content: content, + ); } diff --git a/scribe/lib/scribe/ai/data/network/ai_api.dart b/scribe/lib/scribe/ai/data/network/ai_api.dart index 374effbae..d972e5dfe 100644 --- a/scribe/lib/scribe/ai/data/network/ai_api.dart +++ b/scribe/lib/scribe/ai/data/network/ai_api.dart @@ -9,8 +9,8 @@ class AIApi { AIApi(this._dioClient, this.aiEndpoint); - Future generateMessage(String prompt) async { - final aiRequest = _generateRequest(prompt); + Future generateMessage(List messages) async { + final aiRequest = AIAPIRequest(messages: messages); final response = await _dioClient.post( aiEndpoint, @@ -20,8 +20,4 @@ class AIApi { return AIApiResponse.fromJson(response); } - - AIAPIRequest _generateRequest(String prompt) { - return AIAPIRequest(messages: [AIMessage.ofUser(prompt)]); - } } diff --git a/scribe/lib/scribe/ai/data/repository/ai_repository_impl.dart b/scribe/lib/scribe/ai/data/repository/ai_repository_impl.dart index f3d6115f1..68200d42f 100644 --- a/scribe/lib/scribe/ai/data/repository/ai_repository_impl.dart +++ b/scribe/lib/scribe/ai/data/repository/ai_repository_impl.dart @@ -1,4 +1,5 @@ import 'package:scribe/scribe/ai/data/datasource/ai_datasource.dart'; +import 'package:scribe/scribe/ai/data/model/ai_message.dart'; import 'package:scribe/scribe/ai/domain/model/ai_response.dart'; import 'package:scribe/scribe/ai/domain/repository/ai_scribe_repository.dart'; @@ -8,7 +9,7 @@ class AIScribeRepositoryImpl implements AIScribeRepository { AIScribeRepositoryImpl(this._aiDataSource); @override - Future generateMessage(String prompt) { - return _aiDataSource.generateMessage(prompt); + Future generateMessage(List messages) { + return _aiDataSource.generateMessage(messages); } } diff --git a/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart b/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart index a0eafc2ed..73b934695 100644 --- a/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart +++ b/scribe/lib/scribe/ai/domain/constants/ai_prompts.dart @@ -1,3 +1,4 @@ +import 'package:scribe/scribe/ai/data/model/ai_message.dart'; import 'package:scribe/scribe/ai/presentation/model/ai_action.dart'; import 'package:scribe/scribe/ai/presentation/model/ai_scribe_menu_action.dart'; @@ -8,8 +9,8 @@ class AIPrompts { static const _doNotAddInfoPrompt = "Do not add any extra information or interpret anything beyond the explicit task."; - static String buildPrompt(AIAction action, String? text) { - return switch (action) { + static List buildPrompt(AIAction action, String? text) { + final prompt = switch (action) { PredefinedAction(action: final menuAction) => text?.trim().isNotEmpty == true ? buildPredefinedPrompt(menuAction, text!) @@ -17,6 +18,10 @@ class AIPrompts { CustomPromptAction(prompt: final customPrompt) => buildCustomPrompt(customPrompt, text), }; + + final message = [AIMessage.ofUser(prompt)]; + + return message; } static String buildPredefinedPrompt(AIScribeMenuAction action, String text) { diff --git a/scribe/lib/scribe/ai/domain/repository/ai_scribe_repository.dart b/scribe/lib/scribe/ai/domain/repository/ai_scribe_repository.dart index 2412bf758..3f603a932 100644 --- a/scribe/lib/scribe/ai/domain/repository/ai_scribe_repository.dart +++ b/scribe/lib/scribe/ai/domain/repository/ai_scribe_repository.dart @@ -1,5 +1,6 @@ +import 'package:scribe/scribe/ai/data/model/ai_message.dart'; import 'package:scribe/scribe/ai/domain/model/ai_response.dart'; abstract class AIScribeRepository { - Future generateMessage(String prompt); + Future generateMessage(List messages); }