Optimize hot paths and reuse HTTP sessions

This commit is contained in:
2026-02-02 23:45:51 +03:00
parent 38b95e0de6
commit 3caa099232
3 changed files with 134 additions and 85 deletions

View File

@@ -58,6 +58,120 @@ from .features.weather import get_weather_report
from .features.music import get_music_controller
from .features.cities_game import get_cities_game
_TRANSLATION_COMMANDS = [
("переведи на английский с русского", "ru", "en"),
("переведи на русский с английского", "en", "ru"),
("переведи на английский язык с русского", "ru", "en"),
("переведи на русский язык с английского", "en", "ru"),
("переведи с русского на английский", "ru", "en"),
("переведи с русского в английский", "ru", "en"),
("переведи с английского на русский", "en", "ru"),
("переведи с английского в русский", "en", "ru"),
("переведи с русского языка", "ru", "en"),
("переведи с английского языка", "en", "ru"),
("переведи на английский язык", "ru", "en"),
("переведи на русский язык", "en", "ru"),
("переведи на английский", "ru", "en"),
("переведи на русский", "en", "ru"),
("переведи с английского", "en", "ru"),
("переведи с русского", "ru", "en"),
("как по-английски", "ru", "en"),
("как по английски", "ru", "en"),
("как по-русски", "en", "ru"),
("как по русски", "en", "ru"),
("translate to english from russian", "ru", "en"),
("translate to russian from english", "en", "ru"),
("translate from russian to english", "ru", "en"),
("translate from english to russian", "en", "ru"),
("translate into english", "ru", "en"),
("translate into russian", "en", "ru"),
("translate to english", "ru", "en"),
("translate to russian", "en", "ru"),
("translate from english", "en", "ru"),
("translate from russian", "ru", "en"),
]
_TRANSLATION_COMMANDS_SORTED = sorted(
_TRANSLATION_COMMANDS, key=lambda item: len(item[0]), reverse=True
)
_REPEAT_PHRASES = {
"еще раз",
"повтори",
"скажи еще раз",
"что ты сказал",
"повтори пожалуйста",
"александр еще раз",
"еще раз александр",
"александр повтори",
"повтори александр",
}
_WEATHER_TRIGGERS = (
"погода",
"погоду",
"что на улице",
"какая температура",
"сколько градусов",
"холодно ли",
"жарко ли",
"нужен ли зонт",
"брать ли зонт",
"прогноз погоды",
"че там на улице",
"что там на улице",
"как на улице",
"как на улице-то",
)
_CITY_INVALID_WORDS = {
"этом",
"том",
"той",
"тут",
"здесь",
"там",
"всё",
"все",
"всей",
"всего",
"всем",
"всеми",
"городе",
"город",
"село",
"деревня",
"посёлок",
"аул",
"станция",
"область",
"район",
"край",
"республика",
}
_CITY_PATTERNS = [
re.compile(
r"в\s+городе\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)",
re.IGNORECASE,
),
re.compile(
r"в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)",
re.IGNORECASE,
),
re.compile(
r"погода\s+в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)",
re.IGNORECASE,
),
re.compile(
r"погода\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)\s+(?:какая|сейчас|там)",
re.IGNORECASE,
),
re.compile(
r"(?:какая|как)\s+погода\s+в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)",
re.IGNORECASE,
),
]
def signal_handler(sig, frame):
"""
Обработчик сигнала Ctrl+C.
@@ -87,42 +201,7 @@ def parse_translation_request(text: str):
# Список префиксов команд перевода и соответствующих направлений языков.
# Важно: более длинные префиксы должны проверяться первыми (например,
# "переведи с русского на английский" не должен схватиться как "переведи с русского").
commands = [
("переведи на английский с русского", "ru", "en"),
("переведи на русский с английского", "en", "ru"),
("переведи на английский язык с русского", "ru", "en"),
("переведи на русский язык с английского", "en", "ru"),
("переведи с русского на английский", "ru", "en"),
("переведи с русского в английский", "ru", "en"),
("переведи с английского на русский", "en", "ru"),
("переведи с английского в русский", "en", "ru"),
("переведи с русского языка", "ru", "en"),
("переведи с английского языка", "en", "ru"),
("переведи на английский язык", "ru", "en"),
("переведи на русский язык", "en", "ru"),
("переведи на английский", "ru", "en"),
("переведи на русский", "en", "ru"),
("переведи с английского", "en", "ru"),
("переведи с русского", "ru", "en"),
("как по-английски", "ru", "en"),
("как по английски", "ru", "en"),
("как по-русски", "en", "ru"),
("как по русски", "en", "ru"),
("translate to english from russian", "ru", "en"),
("translate to russian from english", "en", "ru"),
("translate from russian to english", "ru", "en"),
("translate from english to russian", "en", "ru"),
("translate into english", "ru", "en"),
("translate into russian", "en", "ru"),
("translate to english", "ru", "en"),
("translate to russian", "en", "ru"),
("translate from english", "en", "ru"),
("translate from russian", "ru", "en"),
]
for prefix, source_lang, target_lang in sorted(
commands, key=lambda item: len(item[0]), reverse=True
):
for prefix, source_lang, target_lang in _TRANSLATION_COMMANDS_SORTED:
if text_lower.startswith(prefix):
# Отрезаем команду (префикс), оставляем только текст для перевода
rest = text[len(prefix) :].strip()
@@ -284,19 +363,8 @@ def main():
# Проверка на команду "Повтори" / "Еще раз"
user_text_lower = user_text.lower().strip()
repeat_phrases = [
"еще раз",
"повтори",
"скажи еще раз",
"что ты сказал",
"повтори пожалуйста",
"александр еще раз",
"еще раз александр",
"александр повтори",
"повтори александр",
]
# Проверяем точное совпадение или если фраза начинается с "повтори" (но не "повтори за мной")
if user_text_lower in repeat_phrases or (
if user_text_lower in _REPEAT_PHRASES or (
user_text_lower.startswith("повтори")
and "за мной" not in user_text_lower
):
@@ -358,49 +426,28 @@ def main():
continue
# Проверка команды "Погода"
weather_triggers = [
"погода",
"погоду",
"что на улице",
"какая температура",
"сколько градусов",
"холодно ли",
"жарко ли",
"нужен ли зонт",
"брать ли зонт",
"прогноз погоды",
"че там на улице",
"что там на улице",
"как на улице",
"как на улице-то",
]
# Проверяем, содержит ли запрос информацию о конкретном городе
requested_city = None
user_text_lower = user_text.lower()
# Проверяем наличие упоминания города в запросе (например, "погода в Нью-Йорке", "какая погода в Москве")
import re
city_patterns = [
r"в\s+городе\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "в городе Волгоград"
r"в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "в Нью-Йорке" - улучшенный паттерн для составных названий
r"погода\s+в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "погода в Москве" - улучшенный паттерн
r"погода\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)\s+(?:какая|сейчас|там)", # "погода Москва какая"
r"(?:какая|как)\s+погода\s+в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "какая погода в Москве"
]
for pattern in city_patterns:
match = re.search(pattern, user_text_lower, re.IGNORECASE)
for pattern in _CITY_PATTERNS:
match = pattern.search(user_text_lower)
if match:
potential_city = match.group(1).strip()
# Проверяем, что это не местоимение или другое слово, а реально название города
invalid_words = ["этом", "том", "той", "тут", "здесь", "там", "всё", "все", "всей", "всего", "всем", "всеми", "городе", "город", "село", "деревня", "посёлок", "аул", "станция", "область", "район", "край", "республика"]
if potential_city and len(potential_city) > 1 and not any(word in potential_city for word in invalid_words):
if (
potential_city
and len(potential_city) > 1
and not any(word in potential_city for word in _CITY_INVALID_WORDS)
):
requested_city = potential_city.title() # Приводим к формату "Нью-Йорк", "Москва"
break
# Проверяем, содержит ли запрос одну из погодных команд
has_weather_trigger = any(trigger in user_text_lower for trigger in weather_triggers)
has_weather_trigger = any(
trigger in user_text_lower for trigger in _WEATHER_TRIGGERS
)
if has_weather_trigger:
from .features.weather import get_weather_report