// lib/services/ollama_service.dart import 'dart:convert'; import 'package:http/http.dart' as http; // ========================================================================= // SERVICE 1: ANALYSE D'IMAGE (POUR LE PROMPT INITIAL) // ========================================================================= /// Définit un contrat pour tout service capable d'analyser une image /// et de la décrire sous forme de texte. abstract class ImageAnalysisService { /// Prend une image en base64 et retourne une description textuelle (prompt). Future analyzeImage(String base64Image); } /// L'implémentation Ollama de ce service. class OllamaImageAnalysisService implements ImageAnalysisService { final String _apiUrl = 'http://192.168.20.200:11434/api/generate'; final String _visionModel = 'llava:7b'; @override Future analyzeImage(String base64Image) async { print("[OllamaImageAnalysisService] 🚀 Lancement de l'analyse de l'image..."); final requestPrompt = ''' Décris cette image en une phrase courte et factuelle, comme un prompt pour une IA. Concentre-toi sur le sujet principal, son action et l'environnement. Sois direct, concis et ne mentionne pas le mot 'image' ou 'photo'. '''; final requestBody = { 'model': _visionModel, 'prompt': requestPrompt, 'images': [base64Image], 'stream': false, }; try { final response = await http.post( Uri.parse(_apiUrl), headers: {'Content-Type': 'application/json'}, body: jsonEncode(requestBody), ).timeout(const Duration(minutes: 2)); if (response.statusCode == 200) { final body = jsonDecode(response.body); final generatedPrompt = (body['response'] as String? ?? '').trim().replaceAll('\n', ' '); print("[OllamaImageAnalysisService] ✅ Analyse terminée : $generatedPrompt"); return generatedPrompt; } else { throw Exception('Erreur Ollama (analyzeImage) ${response.statusCode}: ${response.body}'); } } catch (e) { print("[OllamaImageAnalysisService] ❌ Exception : ${e.toString()}"); rethrow; } } } // ========================================================================= // SERVICE 2: CRÉATION DE POSTS SOCIAUX // ========================================================================= /// Définit un contrat pour tout service capable de générer des idées de posts. abstract class PostCreationService { Future> 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'; @override Future> 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. Your output MUST be a valid JSON array of strings. Example: ["Idée de post 1...", "Idée de post 2...", "Idée de post 3..."] """; final requestBody = { 'model': _visionModel, 'prompt': requestPrompt, 'images': [base64Image], 'stream': false, }; 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 jsonString = (responseData['response'] as String? ?? '').trim(); if (jsonString.isEmpty) return []; try { final ideasList = jsonDecode(jsonString) as List; return ideasList.map((idea) => idea.toString()).toList(); } catch (e) { print("[OllamaPostCreationService] ❌ Erreur de parsing JSON. Réponse : $jsonString"); return [jsonString]; // Retourne la réponse brute comme une seule idée } } else { throw Exception('Erreur Ollama (generatePostIdeas) ${response.statusCode}: ${response.body}'); } } catch (e) { print("[OllamaPostCreationService] ❌ Exception : ${e.toString()}"); rethrow; } } } // ========================================================================= // SERVICE 3: AMÉLIORATION DE TEXTE // ========================================================================= /// Définit un contrat pour tout service capable d'améliorer un texte. abstract class TextImprovementService { Future improveText({ required String originalText, required String userInstruction, }); } /// L'implémentation Ollama de ce service. class OllamaTextImprovementService implements TextImprovementService { final String _apiUrl = 'http://192.168.20.200:11434/api/generate'; final String _textModel = 'gpt-oss:20b'; @override Future improveText({ required String originalText, required String userInstruction, }) async { print("[OllamaTextImprovementService] 🚀 Appel pour améliorer le texte..."); final requestPrompt = """ You are a social media writing assistant. A user wants to improve the following text: --- TEXT TO IMPROVE --- $originalText ----------------------- The user's instruction is: "$userInstruction". Rewrite the text based on the instruction. Your output MUST be ONLY the improved text, without any extra commentary or explanations. """; final requestBody = { 'model': _textModel, 'prompt': requestPrompt, 'stream': false, }; try { final response = await http.post( Uri.parse(_apiUrl), headers: {'Content-Type': 'application/json'}, body: jsonEncode(requestBody), ).timeout(const Duration(minutes: 2)); if (response.statusCode == 200) { final responseData = jsonDecode(response.body); return (responseData['response'] as String? ?? '').trim(); } else { throw Exception('Erreur Ollama (improveText) ${response.statusCode}: ${response.body}'); } } catch (e) { print("[OllamaTextImprovementService] ❌ Exception : ${e.toString()}"); rethrow; } } }