by Aitor Mira
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:
- 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:
- Under the
main
function is thepython-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 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:
- 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 thereceive_webhook
function. - The
receive_webhook
function receives the webhook body, checks if it has amessages
key underentry->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 functionhandle_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 ishttps://graph.facebook.com/v18.0/{os.environ['TEST_PHONE_ID']}/messages
(note thatTEST_PHONE_ID
must be set at your.env
file).
- Header:{"Authorization": "Bearer " + os.environ["WHATSAPP_TOKEN"]}
(note thatWHATSAPP_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
andfastapi
works with asynchronous paradigm so be careful withasync
andawait
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.