|
- import 'dart:convert';
- import 'package:http/http.dart' as http;
-
- /// Définit un contrat pour tout service capable de générer des idées de posts.
- abstract class PostCreationService {
- Future<List<String>> generatePostIdeas({
- required String base64Image,
- required String profession,
- required String tone,
- });
- }
-
- /// L'implémentation Ollama de ce service.
- class OllamaPostCreationService implements PostCreationService {
- final String _apiUrl = 'http://192.168.20.200:11434/api/generate';
- final String _visionModel = 'llava:7b';
-
- // --- DÉBUT DE L'UNIQUE ET CORRECTE MÉTHODE ---
- @override
- Future<List<String>> generatePostIdeas({
- required String base64Image,
- required String profession,
- required String tone,
- }) async {
- final requestPrompt = '''
- You are a social media expert.
- Act as a "$profession".
- Analyze the image.
- Generate 3 short and engaging social media post ideas in french with a "$tone" tone.
-
- IMPORTANT:
- Your output MUST be a valid JSON array of objects, where each object has a "text" key.
- - DO NOT add any markdown like ```json or ```.
- - DO NOT add any text before or after the JSON array.
- - Ensure all strings inside the JSON are properly escaped (especially newlines \n).
-
- Example of a perfect response:
- [{"text": "idée 1"}, {"text": "idée 2"}, {"text": "idée 3"}]
- ''';
-
- final requestBody = {
- 'model': _visionModel,
- 'prompt': requestPrompt,
- 'images': [base64Image],
- 'stream': false,
- 'format': 'json',
- };
-
- try {
- print('[OllamaPostCreationService] 🚀 Appel pour générer des idées...');
- final response = await http.post(
- Uri.parse(_apiUrl),
- headers: {'Content-Type': 'application/json'},
- body: jsonEncode(requestBody),
- ).timeout(const Duration(minutes: 3));
-
- if (response.statusCode == 200) {
- final responseData = jsonDecode(response.body);
- final rawResponse = (responseData['response'] as String? ?? '').trim();
-
- if (rawResponse.isEmpty) return ["Le modèle n'a retourné aucune réponse."];
-
- String jsonArrayString;
-
- try {
- // --- NOUVELLE LOGIQUE ROBUSTE AVEC REGEX ---
- // On cherche un bloc ```json ... ```
- final regex = RegExp(r'```json\s*([\s\S]*?)\s*```');
- final match = regex.firstMatch(rawResponse);
-
- if (match != null && match.groupCount > 0) {
- // On a trouvé un bloc markdown, on extrait le contenu (Groupe 1)
- jsonArrayString = match.group(1)!.trim();
- } else {
- // Pas de bloc markdown. Peut-être que le modèle a bien répondu ?
- // On retombe sur l'ancienne logique par sécurité.
- final startIndex = rawResponse.indexOf('[');
- final endIndex = rawResponse.lastIndexOf(']');
-
- if (startIndex != -1 && endIndex > startIndex) {
- jsonArrayString = rawResponse.substring(startIndex, endIndex + 1);
- } else {
- throw const FormatException("Aucun bloc JSON ```...``` ni tableau '[]' trouvé.");
- }
- }
- // --- FIN DE LA NOUVELLE LOGIQUE ---
-
- // Log de débogage pour voir ce qu'on essaie de parser
- print('[OllamaPostCreationService] ℹ️ Tentative de parsing sur : "$jsonArrayString"');
-
- final jsonList = jsonDecode(jsonArrayString) as List;
-
- // Logique de parsing pour une liste d'objets
- return jsonList.map((item) {
- if (item is Map<String, dynamic> && item.containsKey('text')) {
- return item['text'].toString();
- }
- return 'Format de l\'idée inattendu';
- })
- .where((text) => text != 'Format de l\'idée inattendu')
- .toList();
-
- } catch (e) {
- // *** LOGGING AMÉLIORÉ ***
- // Ceci nous dira l'erreur EXACTE de parsing (ex: "Unterminated string")
- print('[OllamaPostCreationService] ❌ Erreur de parsing JSON.');
- print('[OllamaPostCreationService] ❌ Erreur spécifique : ${e.toString()}');
- print('[OllamaPostCreationService] ❌ Réponse brute (avant regex) : "$rawResponse"');
- return ["Le format de la réponse de l'IA est inattendu."];
- }
-
- } else {
- throw Exception('Erreur Ollama (generatePostIdeas) ${response.statusCode}: ${response.body}');
- }
- } catch (e) {
- print('[OllamaPostCreationService] ❌ Exception : ${e.toString()}');
- rethrow;
- }
- }
- // --- FIN DE LA MÉTHODE MISE À JOUR ---
- }
|