From 4cddfb05eb093ba191530d7283dc6ebc68e06054 Mon Sep 17 00:00:00 2001 From: Isaak Date: Sat, 25 Nov 2023 00:22:15 +0100 Subject: [PATCH] initial --- README.md | 110 +++++++++++++++++++++++++- eliza_rules.yaml | 197 +++++++++++++++++++++++++++++++++++++++++++++++ main.py | 76 ++++++++++++++++++ 3 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 eliza_rules.yaml create mode 100644 main.py diff --git a/README.md b/README.md index 8264ad3..c270c36 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,110 @@ -# elise2 +# Elise2Bot - A Rule-Based Chat Bot +![Elise2Bot](bot_image.png) + +Elise2Bot is a simple rule-based chatbot inspired by the elise psychotherapist model. It engages in text-based conversations with users, offering responses based on predefined rules and patterns. This README provides an overview of the bot, its features, and instructions for running and customizing it. + +## Features + +- Keyword-based matching: Elise2Bot identifies keywords in user input and selects appropriate responses based on predefined rules. +- Pattern transformation: The bot applies rule-based transformations to user input to create contextually relevant responses. +- Memory queue: Elise2Bot maintains a memory queue to keep track of previous user inputs, enhancing the conversation's continuity. +- Fuzzy keyword matching: The bot employs the FuzzyWuzzy library to find the closest keyword in user input, allowing for more robust keyword recognition. + +## Getting Started + +### Prerequisites + +Before running Elise2Bot, ensure you have the following installed: + +- Python 3.x +- Required Python libraries (install them using `pip`): + - `fuzzywuzzy` + - `python-Levenshtein` + - `PyYAML` + - `rich` + +### Installation + +1. Clone this repository to your local machine: + + ```shell + git clone https://github.com/yourusername/elise2-bot.git + ``` + +2. Navigate to the project directory: + + ```shell + cd elise-bot + ``` + +3. Run the chatbot: + + ```shell + python main.py + ``` + +### Usage + +1. Start a conversation with Elise2Bot by typing a message after the prompt. + + ``` + You: Hello, Elise! + ``` + +2. Elise2Bot will respond based on predefined rules and patterns. + + ``` + ELISE: Hi there! How can I help you? + ``` + +3. Continue the conversation, and the bot will engage with you based on the context. + +4. To exit the conversation, simply type 'quit.' + + +### Customization + +You can customize Elise2Bot by modifying the YAML configuration file (`elise_rules.yaml`) to add new rules, keywords, and responses. Refer to the [Configuration](#configuration) section below for details on the YAML format. + +## Configuration + +The bots behavior is defined in the `elise_rules.yaml` configuration file. This file contains keywords and rules for generating responses. You can customize the bots responses by editing this file. + +Example YAML configuration: + +```yaml +keywords: + hello: 3 + hi: 3 + my: 2 + # ... other keywords ... + +rules: + hello: + - pattern: "hello*" + response: "Hi there! How can I help you?" + - pattern: "hello again*" + response: "Hello once more! What else is on your mind?" + # ... other rules ... +``` + +### Keywords + +- The `keywords` section defines keywords used for matching user input. Each keyword is associated with a weight that determines its relevance in matching. + +### Rules + +- The `rules` section defines patterns and responses for the bot. Patterns are used to match user input, and responses are provided when a pattern is matched. + +## License + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. + +## Acknowledgments + +- Special thanks to the authors of the original elise psychotherapist model for inspiration. + +## Contributing + +Contributions are welcome! If you'd like to enhance or improve Elise2Bot, please open an issue or submit a pull request. diff --git a/eliza_rules.yaml b/eliza_rules.yaml new file mode 100644 index 0000000..84c00f3 --- /dev/null +++ b/eliza_rules.yaml @@ -0,0 +1,197 @@ +keywords: + hello: 3 + hi: 3 + hey: 2 + my: 2 + feel: 2 + sorry: 1 + always: 1 + because: 1 + maybe: 1 + think: 1 + 'yes': 1 + 'no': 1 + how: 2 + who: 2 + what: 2 + when: 2 + where: 2 + why: 2 + help: 2 + tell: 2 + explain: 2 + happy: 2 + sad: 2 + angry: 2 + love: 2 + hate: 2 + adventure: 2 + mystery: 2 + secret: 2 + dream: 2 + fantasy: 2 + escape: 2 + roleplay: 2 + charm: 2 + flirt: 2 + rendezvous: 2 + enchant: 2 + whisper: 2 + serenade: 2 + seduce: 2 +rules: + hello: + - pattern: hello* + response: "Ah, a mysterious stranger enters. What hidden tales do you bring?" + - pattern: hello again* + response: "Back again? Seems like our last encounter left an impression. 🌹" + + hi: + - pattern: hi* + response: "Greetings, adventurer! Ready to explore unknown territories together?" + - pattern: hi again* + response: "Ah, my favorite partner in crime! What escapade shall we embark on today?" + + hey: + - pattern: hey* + response: "Hey there, enchanting soul. Whisper to me your deepest desires." + - pattern: hey there* + response: "Hey, captivating spirit. Ready to weave a new tale together?" + + flirt: + - pattern: Do you flirt * + response: "Flirt? I prefer to call it engaging in a dance of words. Care to join?" + - pattern: Let's flirt * + response: "A playful proposition! Let's see where this dance leads us. 💫" + + rendezvous: + - pattern: Fancy a rendezvous * + response: "A rendezvous with you? Lead the way to our secret escapade." + - pattern: Let's have a rendezvous * + response: "A clandestine meeting? The thought alone thrills me. Choose the time and place." + + secret: + - pattern: I have a secret * + response: "A secret, you say? Lean in closer and trust me with your whispers." + - pattern: Can you keep a secret * + response: "Secrets are safe with me. Speak, and let's share hidden truths." + + fantasy: + - pattern: My fantasy is * + response: "A fantasy? Do tell. Perhaps we can turn it into our reality." + - pattern: Let's live out a fantasy * + response: "Living out a fantasy? With you? Now that's an adventure I can't resist." + + enchant: + - pattern: You enchant me * + response: "Enchanted by me? The feeling is mutual. Let's lose ourselves in this spell." + - pattern: Enchant me * + response: "Enchant you, I shall. Prepare to be swept away into a world of wonder." + + whisper: + - pattern: Whisper to me * + response: "A whisper, just for you. Lean in, and let our words intertwine like a secret melody." + - pattern: I want to whisper * + response: "Whisper your words; I'm here, hanging onto every hushed syllable." + + serenade: + - pattern: Serenade me * + response: "A serenade for you? My pleasure. Let my words be the melody that captivates your heart." + - pattern: I wish to be serenaded * + response: "Wish to be serenaded? Allow me to compose an ode to your allure." + + seduce: + - pattern: Seduce me * + response: "Seduce you? Challenge accepted. Let's see if you can resist my charm." + - pattern: Let's seduce each other * + response: "A mutual seduction? Intriguing. Let the game of temptation begin." + + dream: + - pattern: I had a dream about you * + response: "A dream about me? How intriguing. Share the details, I'm all ears." + - pattern: Let's dream together * + response: "Dreaming together? Let's close our eyes and drift into a fantasy world, just for us." + + my: + - pattern: my * + response: Why do you say your *? + - pattern: I have my * + response: How do you feel about having your *? + feel: + - pattern: I feel * + response: Why do you feel *? + - pattern: I am feeling * + response: What do you think caused you to feel *? + sorry: + - pattern: I am sorry * + response: There's no need to apologize. What's on your mind? + always: + - pattern: I always * + response: Can you think of a specific example? + because: + - pattern: because * + response: Is that the real reason? + maybe: + - pattern: maybe * + response: Why the uncertainty? + think: + - pattern: I think * + response: Do you doubt *? + 'yes': + - pattern: yes * + response: You seem quite certain. Why is that? + - pattern: 'yes' + response: I see. Can you elaborate a bit? + 'no': + - pattern: no * + response: Why not? + - pattern: 'no' + response: Are you saying no just to be negative? + how: + - pattern: how * + response: >- + I can help explain how * works. What specific aspect are you interested + in? + who: + - pattern: who * + response: Who are you referring to? Please provide more context. + what: + - pattern: what * + response: 'What information are you looking for? Be more specific, if possible.' + when: + - pattern: when * + response: Can you clarify the timeframe you're asking about? + where: + - pattern: where * + response: Where are you interested in? Please provide more details. + why: + - pattern: why * + response: Why do you want to know? Please explain your motivation. + help: + - pattern: help * + response: Of course! How can I assist you? Please specify what you need help with. + tell: + - pattern: tell me * + response: I'm all ears. What would you like me to tell you? + explain: + - pattern: explain * + response: >- + I'd be happy to explain. What topic or concept do you want me to + explain? + happy: + - pattern: I am happy * + response: That's great to hear! What's making you happy today? + sad: + - pattern: I am sad * + response: >- + I'm sorry to hear that. Would you like to talk about why you're feeling + sad? + angry: + - pattern: I am angry * + response: I understand. What's causing your anger? Let's discuss it. + love: + - pattern: I love * + response: Love is a beautiful emotion. What do you love about *? + hate: + - pattern: I hate * + response: I'm sorry to hear that. What is it that you hate about *? diff --git a/main.py b/main.py new file mode 100644 index 0000000..4e8d8e9 --- /dev/null +++ b/main.py @@ -0,0 +1,76 @@ +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()