Whatsapp / Telegram LLM based bot

Diverger
6 min readJan 30, 2024

--

by Aitor Mira

Dall-E generated image of a robot interacting with a user

The goal we set in this article is to get your own LLM to interact through a Whatsapp or Telegram chat with any user.

The demo development repo to follow the explanation is found at:

In order to run the scripts you just need to install the requirements under your python environment (python 3.11 preferred):

pip install -r requirements.txt

Let’s go step by step through the set up for each platform.

Telegram

At Telegram, interactions with automated systems are managed with bots (hi, captain obvious). The bot creation is quite straightforward:

  1. With your telegram user account open a chat with

and write /start

2. Here you’ll see lots of options for bot management. By now we’ll select /newbot

3. Give the bot a name and you’ll receive back an access token. Save the token for later.

With that we’re ready to clone the demo repository (find the link above) and create a .env file with your token like this:

TELEGRAM_TOKEN = 123546815:AERNO23ferlbqWDFni329VREgn

Under the llm_ma_bots folder you’ll find the script called telegram_bot.py. It is a minimal implementation of a telegram chatbot, based on python-telegram-bot package, which receives user messages, passes it to LLM and responds with the LLM completion. Let’s explore how it does:

  1. Under the main function is the python-telegram-bot boilerplates, let’s deep dive on it:

a. The ApplicationBuilder connects to your bot by giving it the token.

b. The CommandHandler creates commands which the user will be able to use at telegram with the slash format (e.g. /start). The first arg is the command name, and the second argument is the function called when the command is run by the user.

c. The MessageHandler receives every normal message sent by the user within the chat. The first arg is a filter to just handle specific type of messages (e.g. only replies, messages from a certain user…).

d. Finally, run_polling just configures API calls technical parameters.

2. The message or command handlers passes to the functions and Update object with chat/user metadata and the content (i.e. message) itself. An important metadata is the chat_id, (i.e. update.effective_chat.id) which makes us able to send back responses to a specific chat.

3. In order to send a message to a specific user or group just:

a. context.bot.send_message(chat_id=update.effective_chat.id, text= “message for the user”)

4. Given the above, read a message, pass it to the LLM of your choice and send back the response is trivial. It is what the ai_chat function does. There’re some caveats here:

a. The script implements a custom chat history. Telegram does not allows to read previous messages from a chat so this is the only way to keep a conversation memory.

b. The LLM used for this demo has been served locally with LM Studio. Thus it is accessed through the OpenAI python package. See caveats at page bottom.

Whatsapp

Whatsapp is a bit more complicated than Telegram and the only way to interact programmatically with users is via Whatsapp business account app. Here’s how to set it up:

  1. Create a Meta developer account

2. Create a Whatsapp Business app

3. Get into API configuration, get your temporal token (Identificador de acceso temporal), the test phone id and save them into an .env file in the repo root under two vars called:

a. WHATSAPP_TOKEN

b. TEST_PHONE_ID

4. Add your phone number as “destination phone” and test send messages with API (step 2)

5. Now you should configure the webhook but first there's something you should do first by your side. Under the llm_ma_bots folder you'll find the script called whatsapp_bot.py, we’ll dive on it later. For now, you must know that the script creates an API that will receive the webhook updates. However, in order to make the communication possible, our API must be public online, so you should deploy it by your own means. This is out of this post scope, but for testing purposes I suggest you to use:

Once we have our API exposed and the public URL, run the whatsapp_bot.py script to wake up the service. Now we can continue with the set up steps.

6. Click on “configure webhooks” and you’ll be asked for your API URL (URL de devolución de llamada) and a verification id (identificador de verificación). This verification id is designed as secure password to validate each call, but now just write a random word, it doesn’t matter. Then, click verify and save (verificar y guardar). It will call your API get endpoint, and just need your API to respond with an 200 ok code.

7. Now go to “webhooks” of the left menu and suscribe to “messages“.

Congratulations, you’ve already set up a test Whastsapp business app. Now we’re ready to dive into whatsapp_bot.py. Let’s see how it works:

  • The script is basically a FastAPI service run with uvicorn. Remember, this FastAPI-Uvicorn API must be exposed to public (see ngrok).
  • The API has only one endpoint called /webhook/ with two methods (i.e. GET and POST):
    - The GET method does nothing but return a 200 ok response for the verification step.
    - The POST method is the one that will be called by whatsapp webhook with the events subscribed (i.e. messages). The webhook body will be processed as the argument for the receive_webhook function.
  • The receive_webhook function receives the webhook body, checks if it has a messages key under entry->changes->value. Then we can assure it is a message coming from the user and not our own future response (yes, whatsapp webhook gives you back your own sent messages and may end into an infinite loop). Given that, the function handle_whatsapp_message is called.
  • Given the above, read a message and pass it to the LLM of your choice is trivial. It is what the handle_whatsapp_message function does. There’re some caveats here:
    a. The script implements a custom chat history. Telegram does not allows to read previous messages from a chat so this is the only way to keep a conversation memory.
    b. The LLM used for this demo has been served locally with LM Studio. Thus it is accesed via de OpenAI python package.
  • Finally, to send back to the whatsapp user the LLM response we must send a POST request to an specific endpoint with the following configuration:
    - URL: by the time of writing this post, the message endpoint is https://graph.facebook.com/v18.0/{os.environ['TEST_PHONE_ID']}/messages (note that TEST_PHONE_ID must be set at your .env file).
    - Header: {"Authorization": "Bearer " + os.environ["WHATSAPP_TOKEN"]} (note that WHATSAPP_TOKEN must be set at your .env file)
    - Json:
{
"messaging_product": "whatsapp",
"to": body["entry"][0]["changes"][0]["value"]["messages"][0]["from"],
"type": "text",
"text": {"preview_url": False, "body": bot_response},
}

Voilà! Everything is set and running.

General caveats

  • Both packages python-telegram-bot and fastapi works with asynchronous paradigm so be careful with async and await declarations.
  • For this tutorial I’ve used a locally deployed LLM, served with LM Studio API. The repo code requests the API using the OpenAI package which allows to his interface with generic API services. You need to serve your own API or use a public API (like OpenAI).
  • The configured Whatsapp bot is a test/development one. If you want to actually deploy it you must configure and pay for an official Whatsapp Business Account.

--

--

Diverger
Diverger

Written by Diverger

Inteligencia Artificial Generativa aplicada para los profesionales de la información y para el desarrollo de software.

No responses yet