import 'dart:convert'; import 'package:http/http.dart' as http; import '../models/history_entry_model.dart'; import '../models/word_model.dart'; class AiOracleService { static final AiOracleService _instance = AiOracleService._internal(); factory AiOracleService() => _instance; AiOracleService._internal(); /// Interprets a full multi-word session narrative (1 to 9 words) Future interpretSession({ required List words, required String question, }) async { if (words.isEmpty) return 'Нет знаков для трактовки.'; // 1. Try Live Online Endpoints (Fast timeout) try { final prompt = _buildMultiWordPrompt( question: question, words: words, ); final onlineResult = await _tryFetchOnlineAi(prompt); if (onlineResult != null && onlineResult.trim().length > 30) { return onlineResult.trim(); } } catch (_) {} // 2. High-Dimensional Deep Semantic Synthesizer (Instant & Deep) return _synthesizeDeepSacredNarrative(words, question); } /// Multi-turn chat with the Oracle inside a session Future chatWithOracle({ required OracleSession session, required String userMessage, SessionWord? newlyAddedWord, }) async { final wordsNarrative = StringBuffer(); for (int i = 0; i < session.words.length; i++) { final w = session.words[i]; wordsNarrative.writeln('${i + 1}. #${w.formattedSessionNumber} «${w.word.toUpperCase()}» (${w.category}): ${w.symbolicMeaning}'); } final prompt = '''Ты — Сакральный Оракул 999. Ответь на вопрос вопрошающего: «$userMessage» Контекст: Вопрос: «${session.question ?? 'Поиск пути'}» Выпавшие знаки: $wordsNarrative ${newlyAddedWord != null ? "Дополнительный знак: #${newlyAddedWord.formattedSessionNumber} «${newlyAddedWord.word.toUpperCase()}» (${newlyAddedWord.symbolicMeaning})" : ""} Дай мудрый, глубокий и прямой ответ (2-4 предложения).'''; try { final onlineResult = await _tryFetchOnlineAi(prompt); if (onlineResult != null && onlineResult.trim().length > 20) { return onlineResult.trim(); } } catch (_) {} return _synthesizeChatReply(session, userMessage, newlyAddedWord); } Future _tryFetchOnlineAi(String prompt) async { const workingModels = [ 'gpt-4o-mini', 'gpt-4o', 'command-r', 'command-r7b', 'Yqcloud', 'HuggingSpace', 'WeWordle', ]; final endpoints = [ 'http://localhost:8080/v1/chat/completions', 'http://127.0.0.1:8080/v1/chat/completions', ]; for (final ep in endpoints) { for (final modelName in workingModels) { try { final res = await http.post( Uri.parse(ep), headers: {'Content-Type': 'application/json'}, body: jsonEncode({ 'model': modelName, 'messages': [{'role': 'user', 'content': prompt}], 'temperature': 0.7, }), ).timeout(const Duration(seconds: 10)); if (res.statusCode == 200) { final data = jsonDecode(utf8.decode(res.bodyBytes)); final content = data['choices']?[0]?['message']?['content'] as String?; if (content != null && content.trim().length > 15) { return content.trim(); } } } catch (_) {} } } return null; } String _buildMultiWordPrompt({ required String question, required List words, }) { final qStr = question.trim().isNotEmpty ? 'Вопрос: «$question»' : 'Общий расклад судьбы'; final wordsStr = words .asMap() .entries .map((e) => '${e.key + 1}. #${e.value.formattedSessionNumber} «${e.value.word.toUpperCase()}» (${e.value.category}) — ${e.value.symbolicMeaning}') .join('\n'); return '''Ты — Священный Оракул 999. Составь цельное, глубокое, психологически точное толкование выпавших знаков жребия. $qStr Выпавшие знаки: $wordsStr Требования: - Свяжи выпавшие знаки в единую осмысленную историю-трансформацию. - Укажи скрытую причину, ключевой вызов и вектор исхода. - Ответ на русском языке (3-5 предложений), образный, сильный, без шаблонных фраз.'''; } /// High-dimensional Deep Semantic Synthesizer String _synthesizeDeepSacredNarrative(List words, String question) { final sb = StringBuffer(); final first = words.first; final last = words.last; final hasQuestion = question.trim().isNotEmpty; // Introduction / Framing if (hasQuestion) { sb.write('Относительно вашего вопроса «${question.trim()}» '); } else { sb.write('В потоке открывшегося жребия '); } if (words.length == 1) { sb.write('выпал единственный доминирующий знак — #${first.formattedSessionNumber} «${first.word.toUpperCase()}» (${first.category}). '); sb.write('${first.symbolicMeaning} '); sb.write('Этот символ требует предельной концентрации: обратите внимание на скрытые мотивы и не рассеивайте внимание на второстепенное.'); return sb.toString(); } if (words.length == 2) { final second = words[1]; sb.write('проявляется взаимодействие двух сил: начального импульса #${first.formattedSessionNumber} «${first.word.toUpperCase()}» и вектора #${second.formattedSessionNumber} «${second.word.toUpperCase()}». '); sb.write('С одной стороны, ${first.symbolicMeaning.toLowerCase()} С другой — ${second.symbolicMeaning.toLowerCase()} '); sb.write('Разрешение ситуации лежит в точке баланса между ними: не отвергайте первое, но направляйте его энергию в созидательное русло второго.'); return sb.toString(); } // 3 or more words sb.write('разворачивается цепь из ${words.length} взаимосвязанных знаков. '); sb.write('Исток ситуации заложен в знаке #${first.formattedSessionNumber} «${first.word.toUpperCase()}» — ${first.symbolicMeaning.toLowerCase()} '); // Middle transitions if (words.length > 2) { final middleWords = words.sublist(1, words.length - 1); final midNames = middleWords.map((w) => '«${w.word.toUpperCase()}» (#${w.formattedSessionNumber})').join(' и '); final midMeanings = middleWords.map((w) => w.symbolicMeaning).join(' '); sb.write('Процесс трансформации проходит через испытание $midNames, где $midMeanings '); } // Resolution / Outcome sb.write('Кульминация и ключ к исходу запечатаны в знаке #${last.formattedSessionNumber} «${last.word.toUpperCase()}» — ${last.symbolicMeaning.toLowerCase()} '); sb.write('Оракул указывает: путь открыт через осознание скрытых уроков и решительный шаг вперед.'); return sb.toString(); } String _synthesizeChatReply(OracleSession session, String userMessage, SessionWord? newlyAddedWord) { if (newlyAddedWord != null) { return 'Дополнительный знак #${newlyAddedWord.formattedSessionNumber} «${newlyAddedWord.word.toUpperCase()}» (${newlyAddedWord.category}) раскрывает скрытую грань ситуации: ${newlyAddedWord.symbolicMeaning} В контексте ваших предыдущих знаков это означает, что нужно сместить фокус внимания на внутреннюю суть происходящего.'; } final wordsStr = session.words.map((w) => '«${w.word.toUpperCase()}»').join(', '); return 'Вглядываясь в знаки ($wordsStr), Оракул отвечает на ваш вопрос: суть ответа лежит в осознании скрытых взаимосвязей. Отпустите страх неопределенности и доверьтесь логике происходящих изменений.'; } /// Legacy single word helper Future interpret({ required WordItem word, required String question, String? positionTitle, }) async { final sessionWord = SessionWord.fromWordItem(word, positionTitle: positionTitle); return interpretSession(words: [sessionWord], question: question); } }