77 lines
2.9 KiB
Python
77 lines
2.9 KiB
Python
import re
|
|
import yaml
|
|
from collections import deque
|
|
from fuzzywuzzy import process
|
|
from nltk.corpus import stopwords
|
|
from nltk.tokenize import word_tokenize
|
|
from nltk import download
|
|
from rich.console import Console
|
|
|
|
download('punkt')
|
|
download('stopwords')
|
|
|
|
|
|
def apply_rule(sentence, pattern, transformation):
|
|
pattern = pattern.replace("*", "(.*)") # Replace * with a capturing group
|
|
match = re.search(pattern, sentence, re.IGNORECASE)
|
|
if match:
|
|
if match.groups(): # Check if there are any capturing groups
|
|
return transformation.replace("*", match.group(1))
|
|
else:
|
|
return transformation
|
|
return sentence
|
|
|
|
|
|
class ElizaBot:
|
|
def __init__(self, config_file):
|
|
try:
|
|
with open(config_file) as file:
|
|
config = yaml.safe_load(file)
|
|
self.keywords = config['keywords']
|
|
self.rules = {key: [(rule['pattern'], rule['response']) for rule in rules]
|
|
for key, rules in config['rules'].items()}
|
|
self.memory_queue = deque(maxlen=5)
|
|
self.console = Console()
|
|
self.stop_words = set(stopwords.words('english'))
|
|
except Exception as e:
|
|
print(f"Error loading YAML file: {e}")
|
|
exit(1)
|
|
|
|
def preprocess_sentence(self, sentence):
|
|
words = word_tokenize(sentence.lower())
|
|
return ' '.join([word for word in words if word not in self.stop_words])
|
|
|
|
def find_closest_keyword(self, sentence, threshold=70):
|
|
processed_sentence = self.preprocess_sentence(sentence)
|
|
matches = process.extractOne(processed_sentence, self.keywords.keys(), score_cutoff=threshold)
|
|
return matches[0] if matches else None
|
|
|
|
def eliza_generator(self, user_sentence):
|
|
selected_word = self.find_closest_keyword(user_sentence)
|
|
|
|
if selected_word:
|
|
for pattern, transformation in self.rules.get(selected_word, []):
|
|
response = apply_rule(user_sentence, pattern, transformation)
|
|
if response != user_sentence:
|
|
if selected_word == 'my':
|
|
future_response = apply_rule(user_sentence, "my *", "Earlier, you mentioned your *.")
|
|
self.memory_queue.append(future_response)
|
|
return response
|
|
|
|
return self.memory_queue.popleft() if self.memory_queue else "Tell me more."
|
|
|
|
def chat(self):
|
|
self.console.print("ELISE: Hi! I'm here to chat. What's on your mind?", style="bold green")
|
|
while True:
|
|
user_input = self.console.input("[bold blue]You: [/]")
|
|
if user_input.lower() == 'quit':
|
|
self.console.print("ELISE: Goodbye! Take care.", style="bold green")
|
|
break
|
|
response = self.eliza_generator(user_input)
|
|
self.console.print(f"ELISE: {response}", style="bold green")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
eliza = ElizaBot("eliza_rules.yaml")
|
|
eliza.chat()
|