Голосовой бот + телефония на полном OpenSource. Часть 2 — учим бота слушать и говорить


    В первой части статьи я описал как создать простого чат бота, в этой статье мы научим нашего бота говорить и слушать русскую речь и переводить ее в текст.

    Чтобы наш чат-бот заговорил и начал слушать, нужно пройти несколько подготовительных этапов:

    1. Озвучить все ответные фразы
    2. Установить систему телефонии
    3. Установить систему распознавания голоса
    4. Написать простые скрипты для связи телефонии и нашей нейронной сети с чат-ботом

    Шаг 1: Озвучка ответных фраз


    Так как наш бот довольно примитивный и может произносить только заранее подготовленные фразы, то первым делом озвучим все наши ответные фразы с использованием к примеру yandex speechkit. Положим их в корневую директорию с аудиозаписями freeswitch /usr/share/freeswitch/sounds/en/us/callie/ivr предварительно обрежем длину имени до 50 символов.

    Шаг 2: Установка системы телефонии


    Для того, чтобы наш робот приносил пользу, его надо научить работать с системой телефонии. Была выбрана перспективная система телефонии Freeswitch.

    Чтобы научить freeswitch понимать русскую речь, ему необходимо настроить интеграцию с системой распознавания речи, в нашем случае это будет бесплатный сервер vosk.

    Для сборки freeswitch с поддержкой mod_vosk рекомендуется использовать репозиторий, предлагаемый разработчиком vosk. Скомпилировать его можно по инструкциина сайте freeswitch. Важный момент, для корректной работы mod_vosk необходимо перекомпилировать libks из репозитория.

    PS. для удобства конфигурирования Freeswitch можно установить вэб-интерфейс FusionPBX

    Шаг 3: Установка системы распознавания голоса


    Для распознавания голоса был выбран бесплатный сервер vosk. Базовая установка очень проста, достаточно просто скачать докер образ и запустить на вашей машине.

    docker run -d -p 2700:2700 alphacep/kaldi-ru:latest

    Далее необходимо сконфигурировать mod_vosk для freeswitch, для этого в директории /etc/freeswitch/autoload_configs необходимо создать файл vosk.conf.xml, если его нет. В данном файле необходимо указать только адрес вашего vosk сервера:

    <configuration name="vosk.conf" description="Vosk ASR Configuration">
      <settings>
        <param name="server-url" value="ws://localhost:2700"/>
        <param name="return-json" value="0"/>
      </settings>
    </configuration>

    После настройки можно запустить сам freeswitch

    systemctl start freeswitch

    И запустить модуль

    fs_cli -x "load mod_vosk

    Шаг 4: Скрипты для запуска распознавания голоса


    Для связки телефонии с нейронной сетью чат бота можно использовать rest api интерфейс, который необходимо реализовать и lua скрипт для передачи распознанного текста в rest api и озвучки ответов.

    Шаг 4.1: REST API интерфейс для нейронной сети


    Самым быстрым и удобным способом научить нейросеть отвечать на http запросы является библиотека Fastapi для python. Для начала объявим класс Prediction, который содержит формат входных данных для запроса.

    class Prediction(BaseModel):
    	text: str

    Загрузим нашу модель

    model = Sequential()
    model.add(LSTM(64,return_sequences=True,input_shape=(description_length, num_encoder_tokens)))
    model.add(LSTM(32))
    model.add(Dropout(0.25))
    model.add(Dense(1024, activation='relu'))
    model.add(Dropout(0.25))
    model.add(Dense(158, activation='softmax'))
    opt=keras.optimizers.adam(lr=0.01,amsgrad=True)
    model.compile(loss='categorical_crossentropy',
    				  optimizer=opt,
    				  metrics=['accuracy'])
    #model.summary()
    
    model.load_weights("h_10072020.h5")

    напишем небольшую функцию по предсказанию ответа

    def get_answer(text):
    	t = preprocess_ru_text(text) # функция по препроцессингу текста, такая же как и при обучении модели
    	input_data = np.zeros(
    			(1,description_length,num_encoder_tokens),
    			dtype='float32')
    	j=0
    	for word in t:
    		wordidxs = np.zeros((num_encoder_tokens),dtype='float32')
    		if word in input_token_index:
    			wordidxs[input_token_index[word]]=1
    			input_data[0,j]=wordidxs
    			j+=1
    			print(word)
    	results = model.predict(input_data)
    	print (results[0][np.argmax(results)],
              list(y_dict)[np.argmax(results)])
    	if results[0][np.argmax(results)]>0.5:
    		return random.choice(result_config['intents'][list(y_dict)[np.argmax(results)]]['responses'])
    	else: #если уверенность нейронной сети меньше 50%, возвращаем фразу, что не расслышали вопрос.
    		return random.choice(result_config['failure_phrases'])

    и в конце сделаем интерфейс для получения ответа по запросу:

    @app.post('/prediction/',response_model=Prediction)
    async def prediction_route(text: Prediction):
    	question = text.text
    	answer = get_answer(question)
    	return HTMLResponse(content=clear_text(answer)[:50], status_code=200) # обрезаем длину ответа до 50, чтобы совпадало с именем озвученных файлов

    Можно запускать наш сервис:

    uvicorn main:app --reload --host 0.0.0.0

    Теперь при запросе на localhost:8000/prediction:

    {
    	"text":"привет"
    }

    мы получаем ответ:

    Хай

    Шаг 4.2: LUA скрипт для запуска приложения на freeswitch


    Задачами lua скрипта будут во первых получение распознанного текста из звонка, во вторых получение ответа от нейронной сети и воспроизведение подготовленного файла с озвученной фразой.

    Для возможности осуществления http запросов из lua необходимо установить библиотеку luasocket.

    Чтобы без проблем импортировать эту библиотеку, добавьте в свой скрипт строчку:

    package.path = package.path .. ";" .. [[/usr/share/lua/5.2/?.lua]];

    Далее напишем небольшую функцию получения ответа от нашей нейронной сети:

    function sendRequest(speech_res)
      local path = "http://localhost:8000/prediction/";
      local payload = string.format("{\"text\":\"%s\"}",speech_res);
      log.notice(payload);
      local response_body = { };
      log.notice(path);
      local res, code, response_headers, status = http.request
      {
        url = path,
        method = "POST",
        headers =
        {
          ["Authorization"] = "",
          ["Content-Type"] = "application/json",
          ["Content-Length"] = payload:len()
        },
        source = ltn12.source.string(payload),
        sink = ltn12.sink.table(response_body)
      }
      return trim1(table.concat(response_body))
    end

    И запускаем в бесконечном цикле распознавание и воспроизведение ответных фраз:

    session:execute("play_and_detect_speech", "ivr/привет я могу посоветовать тебе фильм или сериал.wav detect:vosk default");
    while session:ready() do
        local res = session:getVariable('detect_speech_result');
    	if res ~= nil then
    		local speech_res = session:getVariable("detect_speech_result");
    		local response_body = sendRequest(speech_res);
    		log.notice(response_body);
    		session:execute("play_and_detect_speech", "ivr/"..response_body..".wav detect:vosk default");
    	end
    end

    Чтобы повесить этот скрипт на определенный номер, достаточно создать конфигурацию такого вида:

    <extension name="7000" continue="false">
    	<condition field="destination_number" expression="7000">
    		<action application="lua" data="test_vosk.lua"/>
    	</condition>
    </extension>

    И перечитать конфиги:

    fs_cli -x "reloadxml"

    Заключение


    После запуска нейронной сети и freeswitch можно позвонить на номер с привязанным lua скриптом и поговорить с роботом.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 5

      0
      Шаг 3: Установка системы распознавания голоса
      Для распознавания голоса был выбран бесплатный сервер vosk. Базовая установка очень проста, достаточно просто скачать докер образ и запустить на вашей машине.


      А почему оффлайновая распознавалка не использовалась?
        +1
        Ну как бы… работает в офлайне
        prnt.sc/uxhvdj
          0
          это и есть оффлайновая распознавалка, она ставится в докере локально на вашей машине
            0

            Причем неплохо так работает. Тестил для сценариев умного дома, точность распознавания даже через обычный микрофон ноутбука вполне приличная. Скорость бы быстрее чуток, но для УД достаточнач

              0
              на самом деле как заявляет разработчик vosk — процент ошибок достаточно велик, около 40%

        Only users with full accounts can post comments. Log in, please.