1
0
mirror of https://github.com/MarkParker5/STARK.git synced 2024-11-24 08:12:13 +02:00

Add online/offline mode, change Command.find() and @Command.background() returns, fix bugs

This commit is contained in:
dQz6tMwk8rJqvDR 2020-07-28 17:25:41 +03:00
parent 5e94014dcd
commit d75f1cb626
5 changed files with 68 additions and 37 deletions

View File

@ -39,10 +39,10 @@ class Command(ABC):
}
_regex = {
# stars *
f'([A-Za-zА-ЯЁа-яё0-9]+)\*([A-Za-zА-ЯЁа-яё0-9]+)': r'\\b\1.*\2\\b', # 'te*xt'
f'\*([A-Za-zА-ЯЁа-яё0-9]+)': r'\\b.*\1', # '*text'
f'([A-Za-zА-ЯЁа-яё0-9]+)\*': r'\1.*\\b', # 'text*'
f'(^|\s)\*($|\s)': r'.*', # '*' ' * '
'([A-Za-zА-ЯЁа-яё0-9\(\)\[\]\{\}]+)\*([A-Za-zА-ЯЁа-яё0-9\(\)\[\]\{\}]+)': r'\\b\1.*\2\\b', # 'te*xt'
'\*([A-Za-zА-ЯЁа-яё0-9\(\)\[\]\{\}]+)': r'\\b.*\1', # '*text'
'([A-Za-zА-ЯЁа-яё0-9\(\)\[\]\{\}]+)\*': r'\1.*\\b', # 'text*'
'(^|\s)\*($|\s)': r'.*', # '*' ' * '
# one of the list (a|b|c)
'\(((?:.*\|)*.*)\)': r'(?:\1)',
# 0 or 1 the of list [a|b|c]
@ -131,19 +131,24 @@ class Command(ABC):
list = Command.getList()
for i, obj in enumerate( list ):
chances[i] = 0
x = 1 / ( sum([int(i) for i in obj.getKeywords().keys()]) or 1 )
k = 1 / ( sum( [int(w)*len(kw) for w, kw in obj.getKeywords().items()] ) or 1 )
for weight, kws in obj.getKeywords().items():
k = x * weight / len(kws)
for kw in kws:
chances[i] += Command.ratio(string, kw) * k
chances[i] += Command.ratio(string, kw) * weight * k
if( sum( chances.values() ) ):
top = max( chances.values() ) / sum( chances.values() ) * 100
else:
return list[0]
return {
'cmd': list[0],
'params': None,
}
#if( max( chances.values() ) < 800 or top < 80): return list[0]
for i, chance in chances.items():
if chance == max( chances.values() ):
return list[i]
return {
'cmd': list[i],
'params': None,
}
@staticmethod
def reg_find(string):
@ -155,15 +160,21 @@ class Command(ABC):
for ptrn, regex in Command._regex.items():
pattern = re.sub(re.compile(ptrn), regex, pattern)
# links $Pattern
link = re.search(re.compile(f'\$[A-Za-zА-ЯЁа-яё0-9]+'), pattern)
link = re.search(re.compile('\$[A-Za-zА-ЯЁа-яё0-9\(\)\[\]\{\}]+'), pattern)
if link: pattern = re.sub('\\'+link[0], f'(?P<{link[0][1:]}>{Command._patterns[link[0][1:]]})', pattern)
# find
match = re.search(re.compile(pattern), string)
if(match): return obj # match.groupdict()
return None
if(match): return {
'cmd': obj,
'params': match.groupdict(),
}
return {
'cmd': list[0],
'params': None,
}
@staticmethod
def background(answer = ''):
def background(answer = '', voice = ''):
def decorator(cmd):
def wrapper(text):
finish_event = Event()
@ -172,6 +183,7 @@ class Command(ABC):
return {
'type': 'background',
'text': answer,
'voice': voice,
'thread': {
'thread': thread,
'finish_event': finish_event,

View File

@ -21,12 +21,12 @@ from .SmallTalk import *
import datetime, time
import math
from Command import Command
import time
################################################################################
def method(text):
return {
'type': 'simple',
'text': 'Я не понимаю',
'voice': 'Я не понимаю',
}
keywords = {}
@ -96,11 +96,16 @@ def method(text):
str_num += 'десят'
result.append(str_num)
return ' '.join(result)
answer = f'Сейчас {get_str_num(hours, 0)} {str_hour}'
if(minutes): answer += f', {get_str_num(minutes, 1)} {str_minute}'
voice = f'Сейчас {get_str_num(hours, 0)} {str_hour}'
if(minutes): voice += f', {get_str_num(minutes, 1)} {str_minute}'
hours = now.hour if now.hour > 9 else '0'+str(now.hour)
minutes = minutes if minutes > 9 else '0'+str(minutes) if minutes else '00'
text = f'Текущее время: {hours}:{minutes}'
return {
'type': 'simple',
'text': answer
'text': text,
'voice': voice,
}
keywords = {
@ -108,24 +113,25 @@ keywords = {
5: ['текущее', 'сейчас', 'время'],
1: ['сколько']
}
patterns = ['* который * час *', '* скольк* * врем* *', 'время']
patterns = ['* который * час *', '* скольк* * (врем|час)* *', '* врем* *']
ctime = SmallTalk('Current Time', keywords, patterns)
ctime.setStart(method)
################################################################################
# Only for tests
@Command.background('Запускаю фоновый процесс')
@Command.background(answer = 'Запуск фонового процесса', voice = 'Запускаю фоновый процесс')
def method(text, finish_event):
time.sleep(10)
finish_event.set()
return {
'text': 'Фоновый процесс завершен',
'voice': 'Фоновый процесс завершен',
}
keywords = {
10: ['тестирование', 'проверка', 'потоков', 'фоновых', 'процессов'],
}
patterns = ['* (тестир*|провер*) * [фоновых] * (процесс*|поток*) *']
patterns = ['* [тест|провер]* * [фонов*] * (процесс|поток)* *']
test = SmallTalk('Test threads', keywords, patterns)
test.setStart(method)
################################################################################

View File

@ -16,7 +16,6 @@ class Speech:
def speak(this):
if( os.path.exists(this._path) ):
print(f'Говорю: {this._text}')
with open(this._path) as f:
with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as audio:
mixer.init()

View File

@ -1,2 +1,3 @@
goole_tts_json_key = "tts-gc-key.json"
language_code = "ru-RU"
names = ['арчи', 'archie']

45
main.py
View File

@ -2,11 +2,14 @@ import SpeechRecognition
import Text2Speech
import SmallTalk
from Command import Command
import config
listener = SpeechRecognition.SpeechToText()
voice = Text2Speech.Engine()
threads = []
memory = []
online = False
voids = 0
listener.listen_noise()
def check_threads():
@ -14,27 +17,37 @@ def check_threads():
if thread['finish_event'].is_set():
responce = thread['thread'].join()
if responce['text']:
voice.generate(responce['text']).speak()
print(''+responce['text'])
if responce['voice']:
voice.generate(responce['voice']).speak()
thread['finish_event'].clear()
del thread
while True: # main loop
check_threads()
print('Listening...')
print('\nYou: ', end='')
speech = listener.listen()
text = speech['text']
print('You: ')
if text:
cmd = Command.find(text)
responce = cmd.start(text)
memory.insert(0, {
'text': text,
'cmd': cmd,
'responce': responce
})
if responce['type'] == 'background': # add background thread to list
threads.append(responce['thread'])
if responce['text']:
voice.generate(responce['text']).speak()
speech['status'] = 'ok' if text else 'void'
if speech['status'] == 'ok':
print(text)
if set(config.names) & set(text.split(' ')): online = True
if online:
voids = 0
cmd, params = Command.reg_find(text).values()
responce = cmd.start(text)
memory.insert(0, {
'text': text,
'cmd': cmd,
'responce': responce
})
if responce['type'] == 'background': # add background thread to list
threads.append(responce['thread'])
if responce['text']:
print('Archie: '+responce['text'])
if responce['voice']:
voice.generate(responce['voice']).speak()
else:
print(speech['status'])
if speech['status'] == 'error': print('Отсутсвует подключение к интернету');
elif speech['status'] == 'void': voids += 1
if voids >= 3: online = False; voids = 0