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.

122 líneas
4.5KB

  1. import 'dart:convert';
  2. import 'package:http/http.dart' as http;
  3. /// Définit un contrat pour tout service capable de générer des idées de posts.
  4. abstract class PostCreationService {
  5. Future<List<String>> generatePostIdeas({
  6. required String base64Image,
  7. required String profession,
  8. required String tone,
  9. });
  10. }
  11. /// L'implémentation Ollama de ce service.
  12. class OllamaPostCreationService implements PostCreationService {
  13. final String _apiUrl = 'http://192.168.20.200:11434/api/generate';
  14. final String _visionModel = 'llava:7b';
  15. // --- DÉBUT DE L'UNIQUE ET CORRECTE MÉTHODE ---
  16. @override
  17. Future<List<String>> generatePostIdeas({
  18. required String base64Image,
  19. required String profession,
  20. required String tone,
  21. }) async {
  22. final requestPrompt = '''
  23. You are a social media expert.
  24. Act as a "$profession".
  25. Analyze the image.
  26. Generate 3 short and engaging social media post ideas in french with a "$tone" tone.
  27. IMPORTANT:
  28. Your output MUST be a valid JSON array of objects, where each object has a "text" key.
  29. - DO NOT add any markdown like ```json or ```.
  30. - DO NOT add any text before or after the JSON array.
  31. - Ensure all strings inside the JSON are properly escaped (especially newlines \n).
  32. Example of a perfect response:
  33. [{"text": "idée 1"}, {"text": "idée 2"}, {"text": "idée 3"}]
  34. ''';
  35. final requestBody = {
  36. 'model': _visionModel,
  37. 'prompt': requestPrompt,
  38. 'images': [base64Image],
  39. 'stream': false,
  40. 'format': 'json',
  41. };
  42. try {
  43. print('[OllamaPostCreationService] 🚀 Appel pour générer des idées...');
  44. final response = await http.post(
  45. Uri.parse(_apiUrl),
  46. headers: {'Content-Type': 'application/json'},
  47. body: jsonEncode(requestBody),
  48. ).timeout(const Duration(minutes: 3));
  49. if (response.statusCode == 200) {
  50. final responseData = jsonDecode(response.body);
  51. final rawResponse = (responseData['response'] as String? ?? '').trim();
  52. if (rawResponse.isEmpty) return ["Le modèle n'a retourné aucune réponse."];
  53. String jsonArrayString;
  54. try {
  55. // --- NOUVELLE LOGIQUE ROBUSTE AVEC REGEX ---
  56. // On cherche un bloc ```json ... ```
  57. final regex = RegExp(r'```json\s*([\s\S]*?)\s*```');
  58. final match = regex.firstMatch(rawResponse);
  59. if (match != null && match.groupCount > 0) {
  60. // On a trouvé un bloc markdown, on extrait le contenu (Groupe 1)
  61. jsonArrayString = match.group(1)!.trim();
  62. } else {
  63. // Pas de bloc markdown. Peut-être que le modèle a bien répondu ?
  64. // On retombe sur l'ancienne logique par sécurité.
  65. final startIndex = rawResponse.indexOf('[');
  66. final endIndex = rawResponse.lastIndexOf(']');
  67. if (startIndex != -1 && endIndex > startIndex) {
  68. jsonArrayString = rawResponse.substring(startIndex, endIndex + 1);
  69. } else {
  70. throw const FormatException("Aucun bloc JSON ```...``` ni tableau '[]' trouvé.");
  71. }
  72. }
  73. // --- FIN DE LA NOUVELLE LOGIQUE ---
  74. // Log de débogage pour voir ce qu'on essaie de parser
  75. print('[OllamaPostCreationService] ℹ️ Tentative de parsing sur : "$jsonArrayString"');
  76. final jsonList = jsonDecode(jsonArrayString) as List;
  77. // Logique de parsing pour une liste d'objets
  78. return jsonList.map((item) {
  79. if (item is Map<String, dynamic> && item.containsKey('text')) {
  80. return item['text'].toString();
  81. }
  82. return 'Format de l\'idée inattendu';
  83. })
  84. .where((text) => text != 'Format de l\'idée inattendu')
  85. .toList();
  86. } catch (e) {
  87. // *** LOGGING AMÉLIORÉ ***
  88. // Ceci nous dira l'erreur EXACTE de parsing (ex: "Unterminated string")
  89. print('[OllamaPostCreationService] ❌ Erreur de parsing JSON.');
  90. print('[OllamaPostCreationService] ❌ Erreur spécifique : ${e.toString()}');
  91. print('[OllamaPostCreationService] ❌ Réponse brute (avant regex) : "$rawResponse"');
  92. return ["Le format de la réponse de l'IA est inattendu."];
  93. }
  94. } else {
  95. throw Exception('Erreur Ollama (generatePostIdeas) ${response.statusCode}: ${response.body}');
  96. }
  97. } catch (e) {
  98. print('[OllamaPostCreationService] ❌ Exception : ${e.toString()}');
  99. rethrow;
  100. }
  101. }
  102. // --- FIN DE LA MÉTHODE MISE À JOUR ---
  103. }