Skip to content
This repository was archived by the owner on Feb 20, 2025. It is now read-only.

Commit a29295c

Browse files
committed
Added File
1 parent 456e0e2 commit a29295c

20 files changed

+4069
-1
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.idea/*
2+
__pycache__/
3+
4+
models/*
5+
whl/*
6+
7+
**/*.mpeg
8+
**/*.mp3
9+
**/*.whl
10+
**/*.google-cookie
11+
**/*.env
12+
**/*.wav

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
1-
# HackAI2023
1+
OC: Windows 10/11
2+
Pycharm 2022.01.01
3+
4+
Инструкция по использованию:
5+
1. Распаковываем архив в любое удобное место на вашем компьютере
6+
2. Открываем папку с файлами в удобной для вас среде (в нашем случае Pycharm)
7+
3. Находим файл main.py и компилируем его
8+
3. После компиляции сказать активационную фразу "привет аня" и дождаться обработку ассистентом вашей речи. Если фраза была сказана правильно, Вы услышите уведомление.
9+
4. Следующим этапом вам нужно назвать неисправность. После обработки ассистент озвучит решение вашей пролемы.
10+
11+
*Если по каким-то причинам не срабатывает фраза активации, зажмите кнопку "ALT" и ждите, пока модель пропустит данный этап. После чего возвращайтесь к пункту 4.
12+
**Важное замечание: ассистент не воспринимает числа больше 9. Поэтому, например, число 43 проговаривать как "четыре три".

data.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

main.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import keyboard
2+
from vosk import Model, KaldiRecognizer # оффлайн-распознавание от Vosk
3+
from termcolor import colored # вывод цветных логов (для выделения распознанной речи)
4+
from dotenv import load_dotenv # загрузка информации из .env-файла
5+
import speech_recognition # распознавание пользовательской речи (Speech-To-Text)
6+
import pyttsx3 # синтез речи (Text-To-Speech)
7+
from pydub import AudioSegment
8+
from pydub.playback import play
9+
import json # работа с json-файлами и json-строками
10+
import wave # создание и чтение аудиофайлов формата wav
11+
import os # работа с файловой системой
12+
from fuzzywuzzy import fuzz # Проверка схожести строк
13+
14+
# Чтение json файла
15+
with open('data.json', 'r', encoding='utf-8') as file:
16+
data = json.load(file)
17+
18+
model = Model(r"vosk-model-small-ru-0.22") # Загрузка модели
19+
20+
21+
def record_and_recognize_audio(is_commands, *args: tuple):
22+
"""
23+
Запись и распознавание аудио
24+
"""
25+
with microphone:
26+
recognized_data = ""
27+
28+
# запоминание шумов окружения для последующей очистки звука от них
29+
recognizer.adjust_for_ambient_noise(microphone, duration=0.5)
30+
try:
31+
# Понятный вывод в консоли
32+
if is_commands:
33+
print("Слушаю команду...")
34+
else:
35+
print('Жду команду активации...')
36+
audio = recognizer.listen(microphone)
37+
38+
with open("microphone-results.wav", "wb") as wav:
39+
wav.write(audio.get_wav_data())
40+
41+
except speech_recognition.WaitTimeoutError:
42+
pass
43+
44+
try:
45+
wave_audio_file = wave.open("microphone-results.wav", "rb")
46+
print("Начинаю обработку...")
47+
offline_recognizer = KaldiRecognizer(model, wave_audio_file.getframerate())
48+
49+
data = wave_audio_file.readframes(wave_audio_file.getnframes())
50+
if len(data) > 0:
51+
if offline_recognizer.AcceptWaveform(data):
52+
recognized_data = offline_recognizer.Result()
53+
54+
# получение данных распознанного текста из JSON-строки (чтобы можно было выдать по ней ответ)
55+
recognized_data = json.loads(recognized_data)
56+
recognized_data = recognized_data["text"]
57+
except:
58+
pass
59+
60+
return recognized_data
61+
62+
63+
def play_voice_assistant_speech(text_to_speech):
64+
"""
65+
Проигрывание речи ответов голосового ассистента (без сохранения аудио)
66+
:param text_to_speech: текст, который нужно преобразовать в речь
67+
"""
68+
ttsEngine.say(str(text_to_speech))
69+
ttsEngine.runAndWait()
70+
71+
72+
def play_greetings(*args: tuple):
73+
"""
74+
Проигрывание звука принятия
75+
"""
76+
song = AudioSegment.from_wav("new_message_notice.wav")
77+
play(song)
78+
79+
80+
def execute_command_with_name(command_name: str, *args: list):
81+
"""
82+
Выполнение заданной пользователем команды и аргументами
83+
:param command_name: название команды
84+
:param args: аргументы, которые будут переданы в метод
85+
:return:
86+
"""
87+
for key in commands.keys():
88+
answers = '' # Ответ бота
89+
accuracy_best = 0 # Лучшая точность
90+
for fragment in data:
91+
accuracy = fuzz.ratio(command_name, fragment['key'])
92+
if accuracy > accuracy_best:
93+
accuracy_best = accuracy
94+
answers = fragment['answers']
95+
print(colored(f'Key: {answers}\n'
96+
f'Accuracy: {accuracy_best}', 'green'))
97+
if accuracy_best >= 65: # Порог срабатывания команды
98+
print(colored(f'Ассистент: {answers}', 'blue'))
99+
play_voice_assistant_speech(answers)
100+
else:
101+
print(colored('Ассистент: я не распознала команду', 'blue'))
102+
play_voice_assistant_speech('я не распознала команду')
103+
104+
105+
# быстрые команды бота
106+
commands = {
107+
("привет аня",): play_greetings, # команда активации
108+
}
109+
110+
if __name__ == "__main__":
111+
112+
# инициализация инструментов распознавания и ввода речи
113+
recognizer = speech_recognition.Recognizer()
114+
microphone = speech_recognition.Microphone()
115+
116+
# инициализация инструмента синтеза речи
117+
ttsEngine = pyttsx3.init()
118+
119+
# загрузка информации из .env-файла (там лежит API-ключ для OpenWeatherMap)
120+
load_dotenv()
121+
122+
while True:
123+
# старт записи речи с последующим выводом распознанной речи и удалением записанного в микрофон аудио
124+
voice_input = ''
125+
keyboard_pc = False
126+
if not (keyboard.is_pressed('alt')):
127+
voice_input = record_and_recognize_audio(False)
128+
os.remove("microphone-results.wav")
129+
else:
130+
keyboard_pc = True
131+
print(colored(f'Услышала: {voice_input}', "blue"))
132+
if voice_input != '' or keyboard_pc:
133+
for key in commands.keys():
134+
answer = '' # Ответ
135+
accurasy_best = 0 # Точность лучшего ответа
136+
for activ_fraza in key:
137+
accurasy = fuzz.ratio(voice_input, activ_fraza)
138+
if accurasy > accurasy_best:
139+
accurasy_best = accurasy
140+
if accurasy_best >= 75 or keyboard_pc:
141+
print(colored('Услышала фразу активации', 'blue'))
142+
keyboard_pc = False
143+
commands[key]()
144+
voice_input = record_and_recognize_audio(True)
145+
# Пред обработка текста
146+
numbers = {'ноль': '0', 'один': '1', 'два': '2', 'три': '3', 'четыре': '4', 'пять': '5',
147+
'шесть': '6', 'семь': '7',
148+
'восемь': '8', 'девять': '9'}
149+
for key in numbers.keys():
150+
voice_input = voice_input.replace(key, numbers[key])
151+
152+
print(colored(f'Обработала: {voice_input}', 'blue'))
153+
execute_command_with_name(voice_input) # Поиск по файлу

parser.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# -*- coding: utf-8 -*-
2+
# Импорт библиотек
3+
import io
4+
import re
5+
import pandas as pd
6+
from transliterate import translit
7+
8+
9+
# Функция обработки строки
10+
def replace_function(line):
11+
line = line.lower()
12+
for symbol in ["'", '"', '(', ')', '/', '.', '!', '\\', ';', ',', '[', ']', ' ']:
13+
line = line.replace(symbol, '')
14+
replase_str = {'+': 'плюс', '%': ' процентов', '°': ' градусов', '°с': ' цельсия'
15+
}
16+
for key in replase_str.keys():
17+
line = line.replace(str(key), str(replase_str[key]))
18+
line = translit(line, 'ru')
19+
return line
20+
21+
22+
path = 'C:\\Users\\k1rsn\Desktop\\Перечень неисправностей.txt' # Путь к файлу
23+
flag_malfunction = True # Флаг на пункт таблицы
24+
flag_skip = False # Пропустить следующую строку, реализовано для пропуска "Вероятная причина"
25+
file_new = io.open('C:\\Users\\k1rsn\Desktop\\info.txt', 'w', encoding='utf-8') # Открытие файла для записи
26+
with io.open(path, encoding='utf-8') as file:
27+
for line in file: # Чтение файла по строчно
28+
line = replace_function(line) # Обработка строки
29+
try: # Проверка на строчку пункта
30+
nums = re.findall(r'\d+', line)
31+
if f'{nums[0]}\n' == line:
32+
flag_malfunction = True
33+
file_new.write('key: ')
34+
flag_skip = False
35+
continue
36+
except:
37+
pass
38+
if flag_malfunction and line != '\n':
39+
if line[0] == '-':
40+
flag_skip = False
41+
if flag_skip:
42+
flag_skip = False
43+
continue
44+
else:
45+
line = line.replace('-', '')
46+
file_new.writelines(line)
47+
flag_skip = True
48+
else:
49+
flag_malfunction = False
50+
flag_skip = False
51+
52+
data = [] # Массив с данными
53+
key = '' # Активационной фраза
54+
answers = '' # Решение неисправности
55+
with io.open('C:\\Users\\k1rsn\Desktop\\info.txt', 'r', encoding='utf-8') as file:
56+
for line in file:
57+
if line[0:5] == 'key: ': # Проверка на активационную фразу
58+
data.append({'key': str(key[5:-1]).lower(), 'answers': str(answers).lower()})
59+
answers = ''
60+
key = line
61+
else:
62+
answers += f'{line[:-1]} '
63+
df = pd.DataFrame(data=data) # Формирование датафрейма
64+
df = df.iloc[1:, :] # Убирание первой строки данных
65+
df = df.groupby(['key'], as_index=False).agg({'answers': ' или '.join})
66+
df.to_csv(r'C:\\Users\\k1rsn\Desktop\\data.csv', index=False) # Запись в csv
67+
df.to_json(r'C:\\Users\\k1rsn\Desktop\\data.json', orient='records')

vosk-model-small-ru-0.22/README

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Small Russian model for Vosk (Android, RPi, other small devices)
2+
3+
%WER 22.71 [ 9092 / 40042, 1124 ins, 1536 del, 6432 sub ] exp/chain_a/tdnn/decode_test_audiobooks_look_fast/wer_10_0.0
4+
%WER 11.79 [ 5940 / 50394, 894 ins, 832 del, 4214 sub ] exp/chain_a/tdnn/decode_test_golos_crowd_look_fast/wer_11_0.0
5+
%WER 21.34 [ 1789 / 8382, 173 ins, 440 del, 1176 sub ] exp/chain_a/tdnn/decode_test_golos_farfield_look_fast/wer_10_0.0
6+
%WER 29.89 [ 5579 / 18666, 476 ins, 1550 del, 3553 sub ] exp/chain_a/tdnn/decode_test_sova_devices_look_fast/wer_10_0.0
7+
%WER 31.97 [ 13588 / 42496, 1013 ins, 3640 del, 8935 sub ] exp/chain_a/tdnn/decode_test_youtube_look_fast/wer_9_0.0
8+

vosk-model-small-ru-0.22/am/final.mdl

15.1 MB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
--sample-frequency=16000
2+
--use-energy=false
3+
--num-mel-bins=40
4+
--num-ceps=40
5+
--low-freq=20
6+
--high-freq=7600
7+
--allow-downsample=true
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--min-active=200
2+
--max-active=3000
3+
--beam=10.0
4+
--lattice-beam=2.0
5+
--acoustic-scale=1.0
6+
--frame-subsampling-factor=3
7+
--endpoint.silence-phones=1:2:3:4:5:6:7:8:9:10
8+
--endpoint.rule2.min-trailing-silence=0.5
9+
--endpoint.rule3.min-trailing-silence=1.0
10+
--endpoint.rule4.min-trailing-silence=2.0

vosk-model-small-ru-0.22/graph/Gr.fst

30.8 MB
Binary file not shown.
31.5 MB
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
9855
2+
9856
3+
9857
4+
9858
5+
9859

0 commit comments

Comments
 (0)