Answer the question
In order to leave comments, you need to log in
Python. Creating a voice assistant. Could you help with code optimization?
Since I am working with most libraries for the first time, I would like to hear the opinion of a more or less experienced user on optimization. Ideally, help with replacing the if structure
The code can be viewed on GitHub'e: https://github.com/Tysharela/MyAsisstant
Answer the question
In order to leave comments, you need to log in
Well, firstly, your task is changing from writing a voice assistant for a fixed set of commands to writing a framework for creating voice assistants. This should be kept in mind, and the assistant should be designed in such a way that it would be more convenient for the programmer (you) to modify it.
Take Flask as an example, or many bot libs that use decorators to register commands. Then the script turns into a set of functions that implement the command logic itself, and the framework/library does the underlying basic things like communicating with the server.
In your case, these basic things would be:
1. The bot's work cycle
2. Detecting and recognizing the user's speech
3. Determining if the user is accessing the bot.
4. Optionally, the synthesis of a response to the user.
Thus, you can hide the subtleties of speech recognition from individual commands - let them work with text!
Conclusion: in the final bot, in addition to the basic things, there will be separate functions-commands. Each command will be marked with a decorator, which will set the text strings to which it should respond.
More or less like this:
@command('привет') # на какую команду реагировать?
def hello(message: str) -> typing.Optional[str]:
# параметр - полная текстовая строка, которую мы приняли
return "и тебе привет" # возвращаемое значение - None, или строка, которую нужно произнести
@command(r'погода\s+город\s+(.+)') # строка должна начинаться со слов "погода город", а всё что дальше - мы запоминаем.
def hello(match: re.Match) -> typing.Optional[str]:
# параметр - результат сопоставления принятой строки с регуляркой
city = match.group(1)
weather = get_weather_for(city) # узнаём (как-то) погоду, город выбираем по запомненной строке
# возвращаемое значение - None, или строка, которую нужно произнести
return f"Погода в городе {city}: {weather}"
import re
# список зарегистрированных через декоратор команд
registered_commands = []
def command(regexp: str):
def decorator(command_func):
global registered_commands
reg = re.compile(regexp, re.I) # компилируем регулярку, чтобы потом она быстрее работала
item = reg, command_func
registered_commands.append(item) # добавляем регулярку и команду в список команд
return command_func # декоратор должен вернуть функцию, которую обработал
return decorator # возвращаем декоратор для использования
@command('команда')
def some_func(match):
pass
# это то же самое что и ниже
decorator = command('команда') # получили функцию-декоратор
# объявили декорируемую функцию
def some_func(match):
pass
# применили декоратор к функции
some_func = decorator(some_func)
@command
will be automatically collected in the registered_commads list. Then, when processing the next command, we will be able to sort through this list and find the one we need. And then it's simple. You make the work cycle of the bot (the code is abstract, but the idea must be conveyed).while True:
voice = record_user_voice() # детектируем и записываем слова пользователя
text = speech_to_text(voice) # превращаем голос в текст
if text.startswith('имя бота'): # пользователь должен сказать имя бота, чтобы мы напрасно не реагировали
text = text[len('имя бота'):].strip() # убираем имя бота из текста
for regexp, command in registered_commands:
match = regexp.match(text) # пытаемся сопоставить текст с регуляркой
if match is not None: # успешно?
# да
try:
response = command(match) # пытаемся выполнить команду
except Exception as err: # неудачно - сообщаем об ошибке
print(err)
response = "Возникла ошибка"
if response: # если есть что сказать
say(response) # проговариваем ответ
break # так или иначе, мы нашли совпадение с командой. Дальше не ищем.
else: # этот else относится к for ... in registered_commands и сработает если не было break
say("Я не понял команду") # мы не нашли команду
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question