From 353c7f73b3032c8fce380b9a3e20ce65543b4afe Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 4 Sep 2026 17:37:16 +0400 Subject: [PATCH] fix(voice): switch to gemini-3.5-flash, async to_thread, and 20MB file limit handling --- handlers/voice.py | 75 +++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/handlers/voice.py b/handlers/voice.py index 8895f07..f99216f 100644 --- a/handlers/voice.py +++ b/handlers/voice.py @@ -240,39 +240,41 @@ async def transcribe_audio(audio_path: str) -> str: clean_path = tmp_wav models_to_try = [ - 'gemini-2.5-flash', - 'gemini-flash-latest', - 'gemini-2.5-flash-lite', - 'gemini-3.5-transcribe' + 'gemini-3.5-flash', + 'gemini-3-flash-preview', + 'gemini-2.0-flash', + 'gemini-1.5-flash' ] - for model_name in models_to_try: + def _sync_transcribe(clean_file_path: str, m_name: str) -> str: + audio_file = genai.upload_file(path=clean_file_path) try: - logger.info(f"πŸŽ™ [Gemini STT] РаспознаваниС {clean_path} Ρ‡Π΅Ρ€Π΅Π· {model_name}...") - audio_file = genai.upload_file(path=clean_path) - prompt = ( "Π’ΠΎΡ‡Π½ΠΎ транскрибируй эту Π°ΡƒΠ΄ΠΈΠΎΠ·Π°ΠΏΠΈΡΡŒ Π½Π° русском языкС Π² тСкст. " "НС добавляй Π½ΠΈΠΊΠ°ΠΊΠΈΡ… Π²Π²ΠΎΠ΄Π½Ρ‹Ρ… слов, пояснСний ΠΈ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π², ΠΎΡ‚Π΄Π°ΠΉ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ чистый тСкст произнСсСнных слов." ) - - model = genai.GenerativeModel(model_name) - response = model.generate_content([audio_file, prompt]) - + model = genai.GenerativeModel(m_name) + resp = model.generate_content([audio_file, prompt]) + return resp.text.strip() if resp and resp.text else "" + finally: try: genai.delete_file(name=audio_file.name) except Exception: pass - if response and response.text and response.text.strip(): - text = response.text.strip() + for model_name in models_to_try: + try: + logger.info(f"πŸŽ™ [Gemini STT] РаспознаваниС {clean_path} Ρ‡Π΅Ρ€Π΅Π· {model_name}...") + text = await asyncio.to_thread(_sync_transcribe, clean_path, model_name) + + if text: logger.info(f"🎯 [Gemini STT] УспСшно распознано ({model_name}): {text[:70]}...") if tmp_wav and os.path.exists(tmp_wav): os.remove(tmp_wav) return text except Exception as e: logger.warning(f"⚠️ [Gemini STT] Ошибка Π½Π° ΠΌΠΎΠ΄Π΅Π»ΠΈ {model_name}: {e}") - await asyncio.sleep(1) + await asyncio.sleep(0.5) if tmp_wav and os.path.exists(tmp_wav): os.remove(tmp_wav) @@ -306,25 +308,34 @@ async def execute_antigravity_agent(user_text: str) -> str: "Π’Π½ΡƒΡ‚Ρ€ΠΈ Π½Π΅Π³ΠΎ напиши ΠΊΠΎΡ€ΠΎΡ‚ΠΊΡƒΡŽ (1-3 прСдлоТСния), Π΅ΠΌΠΊΡƒΡŽ, Ρ‚Π΅ΠΏΠ»ΡƒΡŽ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡƒΡŽ Π²Ρ‹ΠΆΠΈΠΌΠΊΡƒ ΠΎΡ‚ Майи Π±Π΅Π· Markdown ΠΈ эмодзи, которая Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ·Π²ΡƒΡ‡Π΅Π½Π° голосом Π¨Π°Π΄Π΅." ) - models_to_try = ['gemini-2.5-flash', 'gemini-flash-latest', 'gemini-2.5-flash-lite', 'gemini-3.7-flash', 'gemini-2.5-pro'] + models_to_try = [ + 'gemini-3.5-flash', + 'gemini-3-flash-preview', + 'gemini-2.0-flash', + 'gemini-1.5-flash' + ] last_error = None + def _sync_run_agent(m_name: str, u_text: str) -> str: + model = genai.GenerativeModel( + model_name=m_name, + system_instruction=system_instruction, + tools=[query_bitrix24, execute_bash_command, save_to_obsidian] + ) + chat = model.start_chat(enable_automatic_function_calling=True) + resp = chat.send_message(u_text) + return resp.text.strip() if resp and resp.text else "" + for model_name in models_to_try: try: logger.info(f"πŸš€ [Maya Agent] Запуск с модСлью: {model_name}") - model = genai.GenerativeModel( - model_name=model_name, - system_instruction=system_instruction, - tools=[query_bitrix24, execute_bash_command, save_to_obsidian] - ) - chat = model.start_chat(enable_automatic_function_calling=True) - response = chat.send_message(user_text) - if response and response.text: - return response.text.strip() + response_text = await asyncio.to_thread(_sync_run_agent, model_name, user_text) + if response_text: + return response_text except Exception as e: logger.warning(f"⚠️ [Maya Agent] Π‘Π±ΠΎΠΉ Π½Π° ΠΌΠΎΠ΄Π΅Π»ΠΈ {model_name}: {e}") last_error = e - await asyncio.sleep(1) + await asyncio.sleep(0.5) return f"❌ Ошибка исполнСния Maya Agent: {last_error}" @@ -370,6 +381,18 @@ async def handle_voice_message(message: Message, bot: Bot): else: return + target_obj = message.voice or message.video_note or message.audio or message.document + file_size = getattr(target_obj, "file_size", 0) or 0 + if file_size > 20 * 1024 * 1024: + size_mb = round(file_size / (1024 * 1024), 1) + await message.reply( + f"⚠️ Π€Π°ΠΉΠ» слишком большой ({size_mb} ΠœΠ‘).\n\n" + "Telegram Bot API ТСстко ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ скачиваниС Π±ΠΎΡ‚Π°ΠΌΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ Π΄ΠΎ 20 ΠœΠ‘.\n" + "πŸ’‘ РСшСниС: Π‘ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΡƒΠΉ запись Π΄ΠΈΠΊΡ‚ΠΎΡ„ΠΎΠ½Π° Π² AAC/M4A/MP3 с Π±ΠΎΠ»Π΅Π΅ Π½ΠΈΠ·ΠΊΠΈΠΌ Π±ΠΈΡ‚Ρ€Π΅ΠΉΡ‚ΠΎΠΌ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 64 kbps mono) ΠΈΠ»ΠΈ Π½Π°Π΄ΠΈΠΊΡ‚ΡƒΠΉ голосовыми сообщСниями прямо Π² Ρ‡Π°Ρ‚!", + parse_mode="HTML" + ) + return + status_msg = await message.reply("πŸŽ™ Π‘Π»ΡƒΡˆΠ°ΡŽ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ...", parse_mode="HTML") await bot.send_chat_action(message.chat.id, "typing")