fix(voice): switch to gemini-3.5-flash, async to_thread, and 20MB file limit handling

This commit is contained in:
Admin 2026-09-04 17:37:16 +04:00
parent ed71b84427
commit 353c7f73b3

View file

@ -240,39 +240,41 @@ async def transcribe_audio(audio_path: str) -> str:
clean_path = tmp_wav clean_path = tmp_wav
models_to_try = [ models_to_try = [
'gemini-2.5-flash', 'gemini-3.5-flash',
'gemini-flash-latest', 'gemini-3-flash-preview',
'gemini-2.5-flash-lite', 'gemini-2.0-flash',
'gemini-3.5-transcribe' '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: try:
logger.info(f"🎙 [Gemini STT] Распознавание {clean_path} через {model_name}...")
audio_file = genai.upload_file(path=clean_path)
prompt = ( prompt = (
"Точно транскрибируй эту аудиозапись на русском языке в текст. " "Точно транскрибируй эту аудиозапись на русском языке в текст. "
"Не добавляй никаких вводных слов, пояснений и комментариев, отдай исключительно чистый текст произнесенных слов." "Не добавляй никаких вводных слов, пояснений и комментариев, отдай исключительно чистый текст произнесенных слов."
) )
model = genai.GenerativeModel(m_name)
model = genai.GenerativeModel(model_name) resp = model.generate_content([audio_file, prompt])
response = model.generate_content([audio_file, prompt]) return resp.text.strip() if resp and resp.text else ""
finally:
try: try:
genai.delete_file(name=audio_file.name) genai.delete_file(name=audio_file.name)
except Exception: except Exception:
pass pass
if response and response.text and response.text.strip(): for model_name in models_to_try:
text = response.text.strip() 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]}...") logger.info(f"🎯 [Gemini STT] Успешно распознано ({model_name}): {text[:70]}...")
if tmp_wav and os.path.exists(tmp_wav): if tmp_wav and os.path.exists(tmp_wav):
os.remove(tmp_wav) os.remove(tmp_wav)
return text return text
except Exception as e: except Exception as e:
logger.warning(f"⚠️ [Gemini STT] Ошибка на модели {model_name}: {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): if tmp_wav and os.path.exists(tmp_wav):
os.remove(tmp_wav) os.remove(tmp_wav)
@ -306,25 +308,34 @@ async def execute_antigravity_agent(user_text: str) -> str:
"Внутри него напиши короткую (1-3 предложения), емкую, теплую голосовую выжимку от Майи без Markdown и эмодзи, которая будет озвучена голосом Шаде." "Внутри него напиши короткую (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 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: for model_name in models_to_try:
try: try:
logger.info(f"🚀 [Maya Agent] Запуск с моделью: {model_name}") logger.info(f"🚀 [Maya Agent] Запуск с моделью: {model_name}")
model = genai.GenerativeModel( response_text = await asyncio.to_thread(_sync_run_agent, model_name, user_text)
model_name=model_name, if response_text:
system_instruction=system_instruction, return response_text
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()
except Exception as e: except Exception as e:
logger.warning(f"⚠️ [Maya Agent] Сбой на модели {model_name}: {e}") logger.warning(f"⚠️ [Maya Agent] Сбой на модели {model_name}: {e}")
last_error = e last_error = e
await asyncio.sleep(1) await asyncio.sleep(0.5)
return f"❌ Ошибка исполнения Maya Agent: {last_error}" return f"❌ Ошибка исполнения Maya Agent: {last_error}"
@ -370,6 +381,18 @@ async def handle_voice_message(message: Message, bot: Bot):
else: else:
return 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"⚠️ <b>Файл слишком большой ({size_mb} МБ).</b>\n\n"
"Telegram Bot API жестко ограничивает скачивание ботами файлов размером до 20 МБ.\n"
"💡 <b>Решение:</b> Сконвертируй запись диктофона в AAC/M4A/MP3 с более низким битрейтом (например, 64 kbps mono) или надиктуй голосовыми сообщениями прямо в чат!",
parse_mode="HTML"
)
return
status_msg = await message.reply("🎙 <i>Слушаю и выполняю команду...</i>", parse_mode="HTML") status_msg = await message.reply("🎙 <i>Слушаю и выполняю команду...</i>", parse_mode="HTML")
await bot.send_chat_action(message.chat.id, "typing") await bot.send_chat_action(message.chat.id, "typing")