No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

197 líneas
6.4KB

  1. // lib/services/ollama_service.dart
  2. import 'dart:convert';
  3. import 'package:http/http.dart' as http;
  4. // =========================================================================
  5. // SERVICE 1: ANALYSE D'IMAGE (POUR LE PROMPT INITIAL)
  6. // =========================================================================
  7. /// Définit un contrat pour tout service capable d'analyser une image
  8. /// et de la décrire sous forme de texte.
  9. abstract class ImageAnalysisService {
  10. /// Prend une image en base64 et retourne une description textuelle (prompt).
  11. Future<String> analyzeImage(String base64Image);
  12. }
  13. /// L'implémentation Ollama de ce service.
  14. class OllamaImageAnalysisService implements ImageAnalysisService {
  15. final String _apiUrl = 'http://192.168.20.200:11434/api/generate';
  16. final String _visionModel = 'llava:7b';
  17. @override
  18. Future<String> analyzeImage(String base64Image) async {
  19. print("[OllamaImageAnalysisService] 🚀 Lancement de l'analyse de l'image...");
  20. final requestPrompt = '''
  21. Décris cette image en une phrase courte et factuelle, comme un prompt pour une IA.
  22. Concentre-toi sur le sujet principal, son action et l'environnement.
  23. Sois direct, concis et ne mentionne pas le mot 'image' ou 'photo'.
  24. ''';
  25. final requestBody = {
  26. 'model': _visionModel,
  27. 'prompt': requestPrompt,
  28. 'images': [base64Image],
  29. 'stream': false,
  30. };
  31. try {
  32. final response = await http.post(
  33. Uri.parse(_apiUrl),
  34. headers: {'Content-Type': 'application/json'},
  35. body: jsonEncode(requestBody),
  36. ).timeout(const Duration(minutes: 2));
  37. if (response.statusCode == 200) {
  38. final body = jsonDecode(response.body);
  39. final generatedPrompt = (body['response'] as String? ?? '').trim().replaceAll('\n', ' ');
  40. print("[OllamaImageAnalysisService] ✅ Analyse terminée : $generatedPrompt");
  41. return generatedPrompt;
  42. } else {
  43. throw Exception('Erreur Ollama (analyzeImage) ${response.statusCode}: ${response.body}');
  44. }
  45. } catch (e) {
  46. print("[OllamaImageAnalysisService] ❌ Exception : ${e.toString()}");
  47. rethrow;
  48. }
  49. }
  50. }
  51. // =========================================================================
  52. // SERVICE 2: CRÉATION DE POSTS SOCIAUX
  53. // =========================================================================
  54. /// Définit un contrat pour tout service capable de générer des idées de posts.
  55. abstract class PostCreationService {
  56. Future<List<String>> generatePostIdeas({
  57. required String base64Image,
  58. required String profession,
  59. required String tone,
  60. });
  61. }
  62. /// L'implémentation Ollama de ce service.
  63. class OllamaPostCreationService implements PostCreationService {
  64. final String _apiUrl = 'http://192.168.20.200:11434/api/generate';
  65. final String _visionModel = 'llava:7b';
  66. @override
  67. Future<List<String>> generatePostIdeas({
  68. required String base64Image,
  69. required String profession,
  70. required String tone,
  71. }) async {
  72. final requestPrompt = """
  73. You are a social media expert.
  74. Act as a "$profession".
  75. Analyze the image.
  76. Generate 3 short and engaging social media post ideas in french with a "$tone" tone.
  77. Your output MUST be a valid JSON array of strings.
  78. Example:
  79. ["Idée de post 1...", "Idée de post 2...", "Idée de post 3..."]
  80. """;
  81. final requestBody = {
  82. 'model': _visionModel,
  83. 'prompt': requestPrompt,
  84. 'images': [base64Image],
  85. 'stream': false,
  86. };
  87. try {
  88. print("[OllamaPostCreationService] 🚀 Appel pour générer des idées...");
  89. final response = await http.post(
  90. Uri.parse(_apiUrl),
  91. headers: {'Content-Type': 'application/json'},
  92. body: jsonEncode(requestBody),
  93. ).timeout(const Duration(minutes: 3));
  94. if (response.statusCode == 200) {
  95. final responseData = jsonDecode(response.body);
  96. final jsonString = (responseData['response'] as String? ?? '').trim();
  97. if (jsonString.isEmpty) return [];
  98. try {
  99. final ideasList = jsonDecode(jsonString) as List;
  100. return ideasList.map((idea) => idea.toString()).toList();
  101. } catch (e) {
  102. print("[OllamaPostCreationService] ❌ Erreur de parsing JSON. Réponse : $jsonString");
  103. return [jsonString]; // Retourne la réponse brute comme une seule idée
  104. }
  105. } else {
  106. throw Exception('Erreur Ollama (generatePostIdeas) ${response.statusCode}: ${response.body}');
  107. }
  108. } catch (e) {
  109. print("[OllamaPostCreationService] ❌ Exception : ${e.toString()}");
  110. rethrow;
  111. }
  112. }
  113. }
  114. // =========================================================================
  115. // SERVICE 3: AMÉLIORATION DE TEXTE
  116. // =========================================================================
  117. /// Définit un contrat pour tout service capable d'améliorer un texte.
  118. abstract class TextImprovementService {
  119. Future<String> improveText({
  120. required String originalText,
  121. required String userInstruction,
  122. });
  123. }
  124. /// L'implémentation Ollama de ce service.
  125. class OllamaTextImprovementService implements TextImprovementService {
  126. final String _apiUrl = 'http://192.168.20.200:11434/api/generate';
  127. final String _textModel = 'gpt-oss:20b';
  128. @override
  129. Future<String> improveText({
  130. required String originalText,
  131. required String userInstruction,
  132. }) async {
  133. print("[OllamaTextImprovementService] 🚀 Appel pour améliorer le texte...");
  134. final requestPrompt = """
  135. You are a social media writing assistant.
  136. A user wants to improve the following text:
  137. --- TEXT TO IMPROVE ---
  138. $originalText
  139. -----------------------
  140. The user's instruction is: "$userInstruction".
  141. Rewrite the text based on the instruction.
  142. Your output MUST be ONLY the improved text, without any extra commentary or explanations.
  143. """;
  144. final requestBody = {
  145. 'model': _textModel,
  146. 'prompt': requestPrompt,
  147. 'stream': false,
  148. };
  149. try {
  150. final response = await http.post(
  151. Uri.parse(_apiUrl),
  152. headers: {'Content-Type': 'application/json'},
  153. body: jsonEncode(requestBody),
  154. ).timeout(const Duration(minutes: 2));
  155. if (response.statusCode == 200) {
  156. final responseData = jsonDecode(response.body);
  157. return (responseData['response'] as String? ?? '').trim();
  158. } else {
  159. throw Exception('Erreur Ollama (improveText) ${response.statusCode}: ${response.body}');
  160. }
  161. } catch (e) {
  162. print("[OllamaTextImprovementService] ❌ Exception : ${e.toString()}");
  163. rethrow;
  164. }
  165. }
  166. }