|
|
|
|
|
|
|
|
import json |
|
|
import random |
|
|
import re |
|
|
import sys |
|
|
from difflib import get_close_matches |
|
|
|
|
|
def robust_input(prompt): |
|
|
try: |
|
|
return input(prompt).strip() |
|
|
except UnicodeDecodeError: |
|
|
pass |
|
|
|
|
|
sys.stdout.flush() |
|
|
print(prompt, end='', flush=True) |
|
|
try: |
|
|
raw = sys.stdin.buffer.readline() |
|
|
if not raw: |
|
|
return "" |
|
|
raw = raw.rstrip(b'\r\n') |
|
|
for encoding in ['utf-8', 'cp1251', 'koi8-r', 'iso8859-5']: |
|
|
try: |
|
|
return raw.decode(encoding).strip() |
|
|
except UnicodeDecodeError: |
|
|
continue |
|
|
return raw.decode('utf-8', errors='replace').strip() |
|
|
except Exception: |
|
|
return "" |
|
|
|
|
|
try: |
|
|
with open("patterns.json", "r", encoding="utf-8") as f: |
|
|
PATTERNS = json.load(f) |
|
|
except FileNotFoundError: |
|
|
print("❌ Ошибка: файл patterns.json не найден!") |
|
|
print("Создайте его или скачайте с Hugging Face.") |
|
|
sys.exit(1) |
|
|
except json.JSONDecodeError: |
|
|
print("❌ Ошибка: повреждён файл patterns.json") |
|
|
sys.exit(1) |
|
|
|
|
|
KEYWORDS = { |
|
|
"привет": ["привет", "здравствуй", "хай", "прив", "здарова"], |
|
|
"как дела": ["дела", "как ты", "ты как", "настроение"], |
|
|
"имя": ["имя", "кто ты", "зовут", "тебя зовут"], |
|
|
"школа": ["школа", "урок", "задача", "домашка", "математика", "геометрия"], |
|
|
"пока": ["пока", "выход", "quit", "до свидания", "закончить", "стоп"], |
|
|
"knowledge": ["что такое", "как приготовить", "что значит", "расскажи про", "как сделать"] |
|
|
} |
|
|
|
|
|
def preprocess(text): |
|
|
return re.sub(r'[^а-яё\s]', ' ', text.lower()).strip() |
|
|
|
|
|
def find_response(user_input): |
|
|
clean = preprocess(user_input) |
|
|
if not clean: |
|
|
return random.choice(PATTERNS["default"]) |
|
|
|
|
|
if any(word in clean for word in ["пока", "выход", "quit", "стоп", "закончить", "exit"]): |
|
|
return random.choice(PATTERNS["пока"]) |
|
|
|
|
|
knowledge = PATTERNS.get("knowledge", {}) |
|
|
if clean in knowledge: |
|
|
return knowledge[clean] |
|
|
|
|
|
if knowledge: |
|
|
matches = get_close_matches(clean, knowledge.keys(), n=1, cutoff=0.6) |
|
|
if matches: |
|
|
return knowledge[matches[0]] |
|
|
|
|
|
all_keywords = [] |
|
|
keyword_to_intent = {} |
|
|
for intent, words in KEYWORDS.items(): |
|
|
if intent == "knowledge": |
|
|
continue |
|
|
for word in words: |
|
|
all_keywords.append(word) |
|
|
keyword_to_intent[word] = intent |
|
|
|
|
|
for token in clean.split(): |
|
|
matches = get_close_matches(token, all_keywords, n=1, cutoff=0.6) |
|
|
if matches: |
|
|
intent = keyword_to_intent[matches[0]] |
|
|
return random.choice(PATTERNS[intent]) |
|
|
|
|
|
return random.choice(PATTERNS["default"]) |
|
|
|
|
|
def main(): |
|
|
print("Newton Micro — сверхлёгкий ИИ") |
|
|
print("Поддерживает: опечатки, рецепты, определения, выход по 'пока'") |
|
|
|
|
|
while True: |
|
|
try: |
|
|
user_input = robust_input("Ты: ") |
|
|
if not user_input: |
|
|
continue |
|
|
|
|
|
response = find_response(user_input) |
|
|
print(f"Newton Micro: {response}\n") |
|
|
|
|
|
if any(w in user_input.lower() for w in ["пока", "выход", "quit", "стоп"]): |
|
|
break |
|
|
|
|
|
except KeyboardInterrupt: |
|
|
print("\nNewton Micro: Пока! Береги себя! ✨") |
|
|
break |
|
|
except EOFError: |
|
|
print("\nNewton Micro: До свидания!") |
|
|
break |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |
|
|
|