diff --git a/docs/examples/whatsapp_bot.mdx b/docs/examples/whatsapp_bot.mdx index c4773361..cdeb8128 100644 --- a/docs/examples/whatsapp_bot.mdx +++ b/docs/examples/whatsapp_bot.mdx @@ -2,26 +2,45 @@ title: '💬 WhatsApp Bot' --- -### 🖼️ Template Setup +### 🚀 Getting started -- Fork [this](https://replit.com/@taranjeetio/EC-WhatsApp-Bot-Template?v=1#README.md) replit template. -- Set your `OPENAI_API_KEY` in Secrets. -- Register for a free account on [Twilio](https://www.twilio.com/try-twilio) and create a new Whatsapp Sandbox. -- You can find it in the left Sidebar under `Develop` by navigating to `Messaging>Try it out>Send a WhatsApp Message`. -- To connect a phone number and allow it to chat with the bot, follow the on screen instructions. -- Click on `Run` in the replit container and a URL will get generated for your bot. -- Copy the URL, append `/chat` at the end and paste it under `When a message comes in` under the `Sandbox settings` for Whatsapp in Twilio. Save your settings. +1. Install embedchain python package: -### 🚀 Usage Instructions - -- To allow a new number or reconnect an old number with the Sandbox, follow the instructions in your Twilio account. -- To add data sources to the bot, use the command: -```text -add -``` -- To ask queries from the bot, use the command: -```text - +```bash +pip install embedchain ``` -🎉 Happy Chatting! 🎉 +2. Launch your WhatsApp bot: + + +```bash +python -m embedchain.bots.whatsapp --port 5000 +``` + +If your bot needs to be accessible online, use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible. + +3. Create a free account on [Twilio](https://www.twilio.com/try-twilio) + - Set up a WhatsApp Sandbox in your Twilio dashboard. Access it via the left sidebar: `Messaging > Try it out > Send a WhatsApp Message`. + - Follow on-screen instructions to link a phone number for chatting with your bot + - Copy your bot's public URL, add /chat at the end, and paste it in Twilio's WhatsApp Sandbox settings under "When a message comes in". Save the settings. + +- Copy your bot's public url, append `/chat` at the end and paste it under `When a message comes in` under the `Sandbox settings` for Whatsapp in Twilio. Save your settings. + +### 💬 How to use + +- To connect a new number or reconnect an old one in the Sandbox, follow Twilio's instructions. +- To include data sources, use this command: +```text +add +``` + +- To ask the bot questions, just type your query: +```text + +``` + +### Example + +Here is an example of Elon Musk WhatsApp Bot that we created: + + diff --git a/docs/images/whatsapp.jpg b/docs/images/whatsapp.jpg new file mode 100644 index 00000000..6f28ba20 Binary files /dev/null and b/docs/images/whatsapp.jpg differ diff --git a/embedchain/bots/__init__.py b/embedchain/bots/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/embedchain/bots/base.py b/embedchain/bots/base.py new file mode 100644 index 00000000..bc94b769 --- /dev/null +++ b/embedchain/bots/base.py @@ -0,0 +1,25 @@ +from embedchain import CustomApp +from embedchain.config import AddConfig, CustomAppConfig, QueryConfig +from embedchain.models import EmbeddingFunctions, Providers + + +class BaseBot: + def __init__(self, app_config=None): + if app_config is None: + app_config = CustomAppConfig(embedding_fn=EmbeddingFunctions.OPENAI, provider=Providers.OPENAI) + self.app_config = app_config + self.app = CustomApp(config=self.app_config) + + def add(self, data, config: AddConfig = None): + """Add data to the bot""" + config = config if config else AddConfig() + self.app.add(data, config=config) + + def query(self, query, config: QueryConfig = None): + """Query bot""" + config = config if config else QueryConfig() + return self.app.query(query, config=config) + + def start(self): + """Start the bot's functionality.""" + raise NotImplementedError("Subclasses must implement the start method.") diff --git a/embedchain/bots/whatsapp.py b/embedchain/bots/whatsapp.py new file mode 100644 index 00000000..6ea64155 --- /dev/null +++ b/embedchain/bots/whatsapp.py @@ -0,0 +1,72 @@ +import argparse +import logging +import signal +import sys + +from flask import Flask, request +from twilio.twiml.messaging_response import MessagingResponse + +from .base import BaseBot + + +class WhatsAppBot(BaseBot): + def __init__(self): + super().__init__() + + def handle_message(self, message): + if message.startswith("add "): + response = self.add_data(message) + else: + response = self.ask_bot(message) + return response + + def add_data(self, message): + data = message.split(" ")[-1] + try: + self.add(data) + response = f"Added data from: {data}" + except Exception: + logging.exception(f"Failed to add data {data}.") + response = "Some error occurred while adding data." + return response + + def ask_bot(self, message): + try: + response = self.query(message) + except Exception: + logging.exception(f"Failed to query {message}.") + response = "An error occurred. Please try again!" + return response + + def start(self, host="0.0.0.0", port=5000, debug=True): + app = Flask(__name__) + + def signal_handler(sig, frame): + logging.info("\nGracefully shutting down the WhatsAppBot...") + sys.exit(0) + + signal.signal(signal.SIGINT, signal_handler) + + @app.route("/chat", methods=["POST"]) + def chat(): + incoming_message = request.values.get("Body", "").lower() + response = self.handle_message(incoming_message) + twilio_response = MessagingResponse() + twilio_response.message(response) + return str(twilio_response) + + app.run(host=host, port=port, debug=debug) + + +def start_command(): + parser = argparse.ArgumentParser(description="EmbedChain WhatsAppBot command line interface") + parser.add_argument("--host", default="0.0.0.0", help="Host IP to bind") + parser.add_argument("--port", default=5000, type=int, help="Port to bind") + args = parser.parse_args() + + whatsapp_bot = WhatsAppBot() + whatsapp_bot.start(host=args.host, port=args.port) + + +if __name__ == "__main__": + start_command() diff --git a/examples/whatsapp_bot/run.py b/examples/whatsapp_bot/run.py new file mode 100644 index 00000000..92e26be1 --- /dev/null +++ b/examples/whatsapp_bot/run.py @@ -0,0 +1,10 @@ +from embedchain.bots.whatsapp import WhatsAppBot + + +def main(): + whatsapp_bot = WhatsAppBot() + whatsapp_bot.start() + + +if __name__ == "__main__": + main() diff --git a/setup.py b/setup.py index 9da86f18..2c5970c8 100644 --- a/setup.py +++ b/setup.py @@ -41,5 +41,6 @@ setuptools.setup( "dev": ["black", "ruff", "isort", "pytest"], "community": ["llama-index==0.7.21"], "elasticsearch": ["elasticsearch>=8.9.0"], + "whatsapp": ["twilio==8.5.0", "flask==1.1.2"], }, )