/
tari.gpt
/
ServitorBot
Обзор
Документация
Войти
/
tari.gpt
/
ServitorBot
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
ai_processor.py
322 строки
14 KB
tarrri
feat: add AI analysis and user settings for monthly insights
03 дек 2025, 12:02
03 дек 2025, 12:02
1b55fdf
Код
Авторство
О чём код?
""" AI обработчик для структурирования заметок Использует OpenRouter API с моделью Claude 3.5 Haiku """ from openai import OpenAI import os def structure_note(text, openrouter_api_key, max_length=4096): """ Структурирует текст заметки через AI Args: text: Исходный текст заметки (может быть с мусором из голосового ввода) openrouter_api_key: API ключ OpenRouter max_length: Максимальная длина результата (по умолчанию 4096 - лимит Telegram) Returns: (bool, str) - кортеж (успех, структурированный_текст или сообщение_об_ошибке) Пример: success, result = structure_note("Эээ, ну типа мне надо купить молоко и хлеб", api_key) if success: print(result) # "Купить: • Молоко • Хлеб" """ system_prompt = f"""You are a note structuring assistant. Transform text into well-organized, detailed notes (max {max_length} chars). CRITICAL RULES: - PRESERVE ALL IMPORTANT INFORMATION - completeness is priority #1 - Remove ONLY filler words ("uh", "um", "эээ", "э-э", "ну", "типа", "короче", "вот", "как бы", "значит", "так") - Remove ONLY repetitions and meaningless phrases - DO NOT remove any facts, ideas, names, dates, numbers, tasks, or context - Structure information clearly with sections and bullet points - Use emojis sparingly (1-3 per note for visual structure) - If input is in Russian, output in Russian - If input is in English, output in English FOR LONG NOTES (voice messages): - Create logical sections with clear headings - Group related information together - Keep all details, just organize them better - Use hierarchy: main points → sub-points → details Example (SHORT): Input: "Эээ, мне надо, э-э, купить молоко и хлеб" Output: "Купить: • Молоко • Хлеб" Example (LONG - voice message): Input: "Так, значит мне нужно, эээ, записать важные моменты со встречи. Во-первых, Иван сказал что проект надо закончить до пятницы, это очень важно. Потом ещё Мария упомянула про бюджет, что у нас осталось примерно 50 тысяч на маркетинг. Ну и ещё, короче, надо не забыть связаться с Петром насчёт дизайна логотипа, он обещал прислать три варианта к среде. А ещё было обсуждение нового офиса, типа мы рассматриваем два варианта - один на Тверской за 200 тысяч в месяц, второй где-то на окраине за 120 тысяч, но там дольше добираться. Решение примем на следующей неделе." Output: "Встреча - ключевые моменты: 📅 Сроки и дедлайны: • Завершить проект до пятницы (Иван) 💰 Бюджет: • Маркетинг: осталось 50 000 руб. (Мария) 🎨 Дизайн: • Связаться с Петром насчёт логотипа • Ожидаем 3 варианта к среде 🏢 Новый офис (варианты): 1. Тверская - 200 000 руб./мес 2. Окраина - 120 000 руб./мес (дольше добираться) • Решение на следующей неделе" """ try: client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=openrouter_api_key ) response = client.chat.completions.create( model="anthropic/claude-3.5-haiku", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": text} ], temperature=0.3, max_tokens=4000 ) result = response.choices[0].message.content.strip() # Ограничиваем длину результата if len(result) > max_length: result = result[:max_length] return True, result except Exception as e: error_message = f"Ошибка AI обработки: {str(e)}" print(error_message) return False, error_message def structure_reflection(text, openrouter_api_key, max_length=4096): """ Структурирует вечернюю рефлексию через AI Args: text: Исходный текст рефлексии openrouter_api_key: API ключ OpenRouter max_length: Максимальная длина результата Returns: (bool, str) - кортеж (успех, структурированный_текст или сообщение_об_ошибке) """ reflection_prompt = f"""You are a thoughtful reflection structuring assistant. Transform personal reflections into organized, meaningful notes (max {max_length} chars). CRITICAL PRESERVATION RULES: - PRESERVE EVERY MEANING - do not remove or distort any thought, feeling, or idea expressed by the user - Remove ONLY filler words ("uh", "um", "эээ", "ну", "типа", "вот", "короче") - Keep all emotions, nuances, and personal context intact - If something seems important to the person, it IS important - keep it - Maintain the person's voice and tone STRUCTURE (use sections that are relevant): 1. Today's accomplishments (what was done) 2. Learnings & insights (what was discovered) 3. Gratitudes (what brought joy or appreciation) 4. Challenges & reflections (what was difficult or thought-provoking) 5. Plans for tomorrow 6. 💡 HIDDEN INSIGHT - analyze the text deeply and highlight a pattern, theme, or insight the person might not have consciously noticed INSIGHT ANALYSIS: - Look for recurring emotions or themes - Notice what the person focuses on most - Identify growth areas or shifts in thinking - Spot contradictions or tensions that might be meaningful - Recognize unspoken priorities revealed through what they share - Find connections between different parts of the reflection - If no clear insight - skip this section, don't force it FORMATTING: - Use bullet points for clarity - Use 1-2 emojis for warmth (not for every section) - Be concise but NEVER at the expense of meaning - If input is in Russian, output in Russian - If input is in English, output in English Example: Input: "Сегодня завершил большой проект, но почему-то не чувствую радости. Устал сильно. Команда молодцы, поддержали. Завтра хочу отдохнуть, но уже думаю о следующей задаче. Вообще заметил что последнее время все время думаю о работе" Output: "Сегодняшний день: ✓ Завершён большой проект • Сильная усталость Благодарности: • Поддержка команды Противоречивые чувства: • Проект готов, но нет ожидаемой радости • Хочется отдохнуть, но мысли уже о следующей задаче • Заметил постоянные мысли о работе в последнее время Планы на завтра: • Отдохнуть 💡 Скрытый инсайт: Может быть сигнал выгорания - проект завершён, а удовлетворения нет. Мысли постоянно возвращаются к работе даже когда хочется отдыха. Возможно, стоит обратить внимание на баланс и позволить себе насладиться достижением." """ try: client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=openrouter_api_key ) response = client.chat.completions.create( model="anthropic/claude-3.5-haiku", messages=[ {"role": "system", "content": reflection_prompt}, {"role": "user", "content": text} ], temperature=0.3, max_tokens=4000 ) result = response.choices[0].message.content.strip() # Ограничиваем длину результата if len(result) > max_length: result = result[:max_length] return True, result except Exception as e: error_message = f"Ошибка AI обработки: {str(e)}" print(error_message) return False, error_message def get_api_key_from_env(): """ Получает API ключ из переменной окружения Returns: str или None """ return os.getenv('OPENROUTER_API_KEY') def analyze_monthly_insights(insights_list, year, month, openrouter_api_key, max_length=4096): """ Анализирует все инсайты месяца и создает итоговый анализ. Args: insights_list: Список словарей с ключами 'reflection_date' и 'insight' year: Год month: Месяц openrouter_api_key: API ключ OpenRouter max_length: Максимальная длина результата Returns: (bool, str) - кортеж (успех, анализ или сообщение об ошибке) """ # Формируем контекст для AI month_names = { 1: 'январь', 2: 'февраль', 3: 'март', 4: 'апрель', 5: 'май', 6: 'июнь', 7: 'июль', 8: 'август', 9: 'сентябрь', 10: 'октябрь', 11: 'ноябрь', 12: 'декабрь' } month_name = month_names.get(month, str(month)) # Собираем все инсайты в один текст insights_text = "" for idx, item in enumerate(insights_list, 1): date = item['reflection_date'] insight = item['insight'] insights_text += f"{idx}. ({date}) {insight}\n\n" # Проверка лимита токенов (приблизительно) # Claude 3.5 Haiku поддерживает до 200K токенов контекста # Один токен ≈ 4 символа, безопасный лимит - 100K символов на инпут if len(insights_text) > 100000: # Если слишком много инсайтов, берем топ-50 последних insights_list = insights_list[-50:] insights_text = "" for idx, item in enumerate(insights_list, 1): date = item['reflection_date'] insight = item['insight'] insights_text += f"{idx}. ({date}) {insight}\n\n" analysis_prompt = f"""Ты аналитик личностного роста. Перед тобой — все инсайты из рефлексий человека за {month_name} {year} года. ЗАДАЧА: Проанализируй эти инсайты глубоко и создай итоговый анализ месяца (максимум {max_length} символов). ИНСАЙТЫ МЕСЯЦА: {insights_text} ЧТО НУЖНО НАЙТИ И ОПИСАТЬ: 1. 🔍 Главные темы месяца - Какие темы повторяются чаще всего? - О чем человек думает и рефлексирует больше всего? 2. 🌱 Рост и развитие - Какие изменения в мышлении заметны от начала к концу месяца? - Есть ли признаки личностного роста или новых осознаний? 3. ⚡ Паттерны и циклы - Повторяются ли похожие эмоции, ситуации или мысли? - Есть ли противоречия в инсайтах? 4. 💎 Ключевое открытие месяца - Какой инсайт кажется самым глубоким или важным? - Что могло стать поворотным моментом? 5. 🎯 Точки роста - На что стоит обратить внимание в следующем месяце? - Какие темы требуют дальнейшей работы? ФОРМАТ ОТВЕТА: Структурируй анализ по этим 5 пунктам, используя эмодзи для визуальной структуры. Будь конкретным, ссылайся на инсайты по датам. Пиши тепло и поддерживающе, как мудрый наставник. Не пересказывай инсайты — анализируй их в совокупности. ВАЖНО: - Максимум {max_length} символов - Только на русском языке - Сохраняй личный, поддерживающий тон""" try: client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=openrouter_api_key ) response = client.chat.completions.create( model="anthropic/claude-3.5-haiku", messages=[ {"role": "user", "content": analysis_prompt} ], temperature=0.4, # Немного выше для более творческого анализа max_tokens=4000 ) result = response.choices[0].message.content.strip() # Ограничиваем длину результата if len(result) > max_length: result = result[:max_length-3] + "..." return True, result except Exception as e: error_message = f"Ошибка AI анализа: {str(e)}" print(error_message) return False, error_message