attheoaks.com

Creating an Automated Summarizer Bot with Azure and GitHub

Written on

Chapter 1: Introduction

A friend of mine recently requested that I set up a Telegram channel to share my articles (which I did! You can find it here). While the idea was appealing, the thought of writing a brief summary for each article felt tedious. Given my forgetfulness, I was bound to miss posting on the channel altogether.

The solution? I decided to automate the entire process using GitHub Actions, Azure Functions, and Azure OpenAI, all while having some fun and learning along the way. Let's delve into the design phase!

Architecture Overview

The architecture for this solution is straightforward. Here are the key components involved:

  1. A GitHub Action that triggers whenever I publish a new article on my personal blog.
  2. An LLM model, specifically GPT-4, hosted via Azure OpenAI, to summarize the content.
  3. An Azure Function that acts as a bridge, connecting the LLM to the Telegram API and GitHub Actions.

Here's a visual representation of the REST calls involved:

  1. The GitHub Action activates the Azure Function (1).
  2. The function retrieves the raw markdown of the article from my GitHub repository (2).
  3. The text is sent to the LLM for summarization (3).
  4. Finally, the summary is posted to the Telegram API (4).

I will start by refining the existing YAML workflow that builds my blog before coding the integration function.

Section 1.1: GitHub Action Configuration

I prefer to keep things simple, so I designed the function app to trigger only when I commit with a message starting with "article:"—a style reminiscent of Conventional Commits. I also specify the folder containing the article to pass it to the Azure Function later.

💡 Note: I adopted a bottom-up approach, beginning with the GitHub Action because I already had a plan in mind. The integration requires minimal data (just the article folder name), making it easier to conceptualize.

I quickly consulted GPT-4 to generate a GitHub Action, which I then modified to create the following job:

Copy trigger-summarizer:

runs-on: ubuntu-latest

if: startsWith(github.event.head_commit.message, 'article:')

needs: deploy

steps:

  • name: Call Summarizer

    env:

    FUNCTION_URL: ${{ secrets.LOGIC_APP_URL }}

    run: |

    COMMIT_MESSAGE="${{ github.event.head_commit.message }}"

    ARTICLE_NAME=$(echo $COMMIT_MESSAGE | awk '{print $2}')

    curl -X POST $FUNCTION_URL

    -H "Content-Type: application/json"

    —data "{"articleName": "$ARTICLE_NAME"}"

This snippet checks if the commit message begins with "article:", extracts the second word (the article name), and sends a POST request to the Azure Function.

I integrated this job into my existing workflow for building my Hugo-based blog. You can check the code for the integration with the preexisting workflow logic.

Section 1.2: Developing the Azure Function

Now, let's move on to the Azure Function. I won't delve into the Azure OpenAI setup here, as I have a separate article on that topic.

💡 Ensure that your GPT-4 deployment is properly configured to avoid throttling issues!

For our Azure Functions, we will use the V2 Python programming model, which is more efficient than V1, allowing inline trigger and binding definitions via Python decorators.

To get started, follow these commands:

mkdir summarizer_bot_function

cd ./summarizer_bot_function/

func init --model V2 --python

func new --name SummarizerFunction --template "HTTP trigger" --authlevel "function"

At this stage, you should have a new folder created. We also need to install a couple of libraries (requests and openai) and update the requirements.txt file:

pip install requests openai

pip freeze > requirements.txt

To avoid potential library conflicts in future projects, consider using a Python virtual environment.

Next, we can launch Visual Studio Code with code . (if you're in the same terminal directory) and begin developing our function. Replace the content in function_app.py with the following code:

import azure.functions as func

import logging

import os

from openai import AzureOpenAI

import requests

azure_endpoint = os.getenv('AZURE_OPENAI_ENDPOINT')

azure_key = os.getenv('AZURE_OPENAI_KEY')

telegram_bot_token = os.getenv('TELEGRAM_BOT_TOKEN')

telegram_channel_id = os.getenv('TELEGRAM_CHANNEL_ID')

client = AzureOpenAI(

azure_endpoint=azure_endpoint,

api_key=azure_key,

api_version="2023-05-15"

)

app = func.FunctionApp()

@app.route(route="SummarizerFunction", auth_level=func.AuthLevel.FUNCTION, methods=["POST"])

def summarizer(req: func.HttpRequest) -> func.HttpResponse:

logging.info('Python HTTP trigger function processed a request.')

# Deserialize article name from request body

req_body = req.get_json()

article_name = req_body.get('articleName')

# Retrieve article raw markdown content from GitHub

raw_md_content = requests.get(

response = client.chat.completions.create(

model="gpt4_turbo",

messages=[

{"role": "system", "content": "You are a skilled copywriter. Summarize the following article in 50 words."},

{"role": "user", "content": raw_md_content}

]

)

# Prepare the Telegram message text

# Post message to Telegram channel

"chat_id": telegram_channel_id, "text": telegram_message_text, "parse_mode": "Markdown"})

return func.HttpResponse(f"Telegram responded with: {telegram_response}", status_code=telegram_response.status_code)

To ensure everything functions correctly, set the following environmental variables:

  • AZURE_OPENAI_ENDPOINT: Your Azure OpenAI service endpoint
  • AZURE_OPENAI_KEY: Your Azure OpenAI service key
  • TELEGRAM_BOT_TOKEN: The token for your Telegram bot
  • TELEGRAM_CHANNEL_ID: The ID of your Telegram channel

💡 Remember to grant your bot sufficient permissions to post in your channel. After creating the channel, refer to the walkthrough to obtain a token and add your bot to the channel.

Assuming all parameters are correctly set, you can test your Azure Function by running func start. The function will be ready for input. You can use curl or a graphical tool like Insomnia to send a request:

curl -X POST http://localhost:7071/api/SummarizerFunction -H 'Content-Type: application/json' -d '{"articleName" : "diy-copilot-phi"}'

If successful, you should see a new post in your Telegram channel!

Chapter 2: Deployment and Testing

Now that the function works as expected, it's time to deploy it to Azure. Begin by creating a new serverless Function App in your Azure subscription. You can follow the instructions for using either the Azure CLI or the Azure Portal.

Take note of your Function App's name (e.g., summarizer-bot-fap). Next, deploy it using the Azure Functions Core Tools:

func azure functionapp publish

💡 Don’t forget to set the App Settings for the Function App in the portal or via command line. For enhanced security, consider using Key Vault references.

Once the publish step is successful, you should see the function listed in the Functions tab of your Function App. Click on your Azure Function name and then select the "Get Function Url" button. This URL will contain the default Host key required for authenticating with your Function App, so handle it securely.

Next, navigate to GitHub and add the FUNCTION_URL to your repository settings. Check the guide if you need assistance. You should see this in your repository's Secrets and Variables/Action Secrets section.

Now, let's test the deployment by committing to the repository with the message: "article: diy-copilot-phi test function app." After a moment, the trigger summarizer job should show as successful! Check your Telegram channel, and you should see the summary along with the article link.

In conclusion, we have successfully created an automated summarization solution using Azure OpenAI, Azure Functions, and GitHub Actions. Future enhancements could include a review step for summaries before publication, possibly through a secondary private channel for approving or modifying them. I might explore this in a future article, but for now, this implementation meets my needs perfectly.

Thank you for following along—here's to the power of technology!

References

  • Conventional Commits
  • AWK command in Unix/Linux with examples — GeeksforGeeks
  • Deploying Azure OpenAI Service using OpenTofu | by Tommaso Colella | Feb, 2024 | Medium
  • Create a Python function from the command line — Azure Functions | Microsoft Learn
  • requests · PyPI
  • openai · PyPI
  • venv — Creation of virtual environments — Python 3.11.8 documentation
  • From BotFather to 'Hello World' (telegram.org)
  • Create a serverless function app using the Azure CLI | Microsoft Learn
  • Use Key Vault references — Azure App Service | Microsoft Learn
  • Using secrets in GitHub Actions — GitHub Docs

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

# Embracing the Memory Curse: A Journey of Connection

Discover how embracing the gift of memory can enhance connections with others, turning a perceived curse into a meaningful experience.

# Understanding the Enigma of Regular Ron: A Tale of Relationships

Explore the perplexing charm of an average man who attracts stunning women, unraveling the mystery behind his unexpected success.

Cultivating Everyday Gratitude: Embracing Life's Blessings

Explore the significance of gratitude in daily life and practical ways to cultivate appreciation for what we have.

Coping with Climate Knowledge: Insights from Experts

Explore how climate scientists manage the weight of their knowledge and the impact of climate anxiety on mental health.

Understanding the Cause Behind the SpaceX Explosion Incident

A detailed analysis of the SpaceX explosion, its causes, and the implications for future missions.

Swift Closures: Understanding Their Power and Purpose

Discover the fundamentals of closures in Swift, how they enhance coding, and practical examples to simplify your programming tasks.

Tesla and Apple: A Study in Corporate Stubbornness and Innovation

An exploration of Tesla and Apple's contrasting approaches to competition and innovation in the tech industry.

Transforming Energy: The Path to Total Electrification

Exploring the future of energy through radical electrification, focusing on efficiency, reduced carbon footprint, and economic benefits.