Reading view

There are new articles available, click to refresh the page.

Golden Feedbacks for Python Sessions 1.0 from last year (2024)

Many Thanks to Shrini for documenting it last year. This serves as a good reference to improve my skills. Hope it will help many.

📢 What Participants wanted to improve

🚶‍♂️ Go a bit slower so that everyone can understand clearly without feeling rushed.


📚 Provide more basics and examples to make learning easier for beginners.


🖥 Spend the first week explaining programming basics so that newcomers don’t feel lost.


📊 Teach flowcharting methods to help participants understand the logic behind coding.


🕹 Try teaching Scratch as an interactive way to introduce programming concepts.


🗓 Offer weekend batches for those who prefer learning on weekends.


🗣 Encourage more conversations so that participants can actively engage in discussions.


👥 Create sub-groups to allow participants to collaborate and support each other.


🎉 Get “cheerleaders” within the team to make the classes more fun and interactive.


📢 Increase promotion efforts to reach a wider audience and get more participants.


🔍 Provide better examples to make concepts easier to grasp.


❓ Conduct more Q&A sessions so participants can ask and clarify their doubts.


🎙 Ensure that each participant gets a chance to speak and express their thoughts.


📹 Showing your face in videos can help in building a more personal connection with the learners.


🏆 Organize mini-hackathons to provide hands-on experience and encourage practical learning.


🔗 Foster more interactions and connections between participants to build a strong learning community.


✍ Encourage participants to write blogs daily to document their learning and share insights.


🎤 Motivate participants to give talks in class and other communities to build confidence.

📝 Other Learnings & Suggestions

📵 Avoid creating WhatsApp groups for communication, as the 1024 member limit makes it difficult to manage multiple groups.


✉ Telegram works fine for now, but explore using mailing lists as an alternative for structured discussions.


🔕 Mute groups when necessary to prevent unnecessary messages like “Hi, Hello, Good Morning.”


📢 Teach participants how to join mailing lists like ChennaiPy and KanchiLUG and guide them on asking questions in forums like Tamil Linux Community.


📝 Show participants how to create a free blog on platforms like dev.to or WordPress to share their learning journey.


🛠 Avoid spending too much time explaining everything in-depth, as participants should start coding a small project by the 5th or 6th class.


📌 Present topics as solutions to project ideas or real-world problem statements instead of just theory.


👤 Encourage using names when addressing people, rather than calling them “Sir” or “Madam,” to maintain an equal and friendly learning environment.


💸 Zoom is costly, and since only around 50 people complete the training, consider alternatives like Jitsi or Google Meet for better cost-effectiveness.

Will try to incorporate these learnings in our upcoming sessions.

🚀 Let’s make this learning experience engaging, interactive, and impactful! 🎯

A Step-by-Step Guide to LLM Function Calling in Python

Function calling allows Claude to interact with external functions and tools in a structured way. This guide will walk you through implementing function calling with Claude using Python, complete with examples and best practices.

Prerequisites

To get started, you'll need:

  • Python 3.7+
  • anthropic Python package
  • A valid API key from Anthropic

Basic Setup

from anthropic import Anthropic
import json
# Initialize the client
anthropic = Anthropic(api_key='your-api-key')

Defining Functions

function_schema = {
    "name": "get_weather",
    "description": "Get the current weather for a specific location",
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "City name or coordinates"
            },
            "unit": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"],
                "description": "Temperature unit"
            }
        },
        "required": ["location"]
    }
}

Making Function Calls

A Step-by-Step Guide to LLM Function Calling in Python
Function calling allows Claude to interact with external functions and tools in a structured way. This guide will walk you through implementing function calling with Claude using Python, complete with examples and best practices.
Prerequisites
To get started, you'll need:
Python 3.7+
anthropic Python package
A valid API key from Anthropic

Basic Setup
from anthropic import Anthropic
import json
# Initialize the client
anthropic = Anthropic(api_key='your-api-key')
Defining Functions
function_schema = {
    "name": "get_weather",
    "description": "Get the current weather for a specific location",
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "City name or coordinates"
            },
            "unit": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"],
                "description": "Temperature unit"
            }
        },
        "required": ["location"]
    }
}
Making Function Calls
def get_weather(location, unit="celsius"):
    # This is a mock implementation but you can all call your API
    return {
        "location": location,
        "temperature": 22 if unit == "celsius" else 72,
        "conditions": "sunny"
    }
def process_function_call(message):
    try:
        # Parse the function call parameters
        params = json.loads(message.content)
        # Call the appropriate function
        if message.name == "get_weather":
            result = get_weather(**params)
            return json.dumps(result)
        else:
            raise ValueError(f"Unknown function: {message.name}")
    except Exception as e:
        return json.dumps({"error": str(e)})
# Example conversation with function calling
messages = [
    {
        "role": "user",
        "content": "What's the weather like in Paris?"
    }
]
while True:
    response = anthropic.messages.create(
        model="claude-3-5-haiku-latest",
        messages=messages,
        tools=[function_schema]
    )
    # Check if Claude wants to call a function
    if response.tool_calls:
        for tool_call in response.tool_calls:
            # Execute the function
            result = process_function_call(tool_call)
            # Add the function result to the conversation
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "name": tool_call.name,
                "content": result
            })
    else:
        # Normal response - print and break
        print(response.content)
        break

Best Practices

  1. Clear Function Descriptions
  • Write detailed descriptions for your functions
  • Specify parameter types and constraints clearly
  • Include examples in the descriptions when helpful
  1. Input Validation
  • Validate all function inputs before processing
  • Return meaningful error messages
  • Handle edge cases gracefully
  1. Response Formatting
  • Return consistent JSON structures
  • Include status indicators in responses
  • Format error messages uniformly

4 . Security Considerations

  • Validate and sanitize all inputs
  • Implement rate limiting if needed
  • Use appropriate authentication
  • Don't expose sensitive information in function descriptions

Conclusion

Function calling with Claude enables powerful integrations between the language model and external tools. By following these best practices and implementing proper error handling, you can create robust and reliable function-calling implementations.

Learning Notes #71 – pyproject.toml

In the evolving Python ecosystem, pyproject.toml has emerged as a pivotal configuration file, streamlining project management and enhancing interoperability across tools.

In this blog i delve deep into the significance, structure, and usage of pyproject.toml.

What is pyproject.toml?

Introduced in PEP 518, pyproject.toml is a standardized file format designed to specify build system requirements and manage project configurations. Its primary goal is to provide a unified, tool-agnostic approach to project setup, reducing the clutter of multiple configuration files.

Why Use pyproject.toml?

  • Standardization: Offers a consistent way to define project metadata, dependencies, and build tools.
  • Interoperability: Supported by various tools like Poetry, Flit, Black, isort, and even pip.
  • Simplification: Consolidates multiple configuration files (like setup.cfg, requirements.txt) into one.
  • Future-Proofing: As Python evolves, pyproject.toml is becoming the de facto standard for project configurations, ensuring compatibility with future tools and practices.

Structure of pyproject.toml

The pyproject.toml file uses the TOML format, which stands for “Tom’s Obvious, Minimal Language.” TOML is designed to be easy to read and write while being simple enough for parsing by tools.

1. [build-system]

Defines the build system requirements. Essential for tools like pip to know how to build the project.

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

requires: Lists the build dependencies required to build the project. These packages are installed in an isolated environment before the build process starts.

build-backend: Specifies the backend responsible for building the project. Common backends include:

  • setuptools.build_meta (for traditional Python projects)
  • flit_core.buildapi (for projects managed with Flit)
  • poetry.core.masonry.api (for Poetry projects)

2. [tool]

This section is used by third-party tools to store their configuration. Each tool manages its own sub-table under [tool].

Example with Black (Python code formatter):

[tool.black]
line-length = 88
target-version = ["py38"]
include = '\.pyi?$'
exclude = '''
/(
  \.git
  | \.mypy_cache
  | \.venv
  | build
  | dist
)/
'''

  • line-length: Sets the maximum line length for code formatting.
  • target-version: Specifies the Python versions the code should be compatible with.
  • include / exclude: Regular expressions to define which files Black should format.

Example with isort (import sorter)

[tool.isort]
profile = "black"
line_length = 88
multi_line_output = 3
include_trailing_comma = true

  • profile: Allows easy integration with formatting tools like Black.
  • multi_line_output: Controls how imports are wrapped.
  • include_trailing_comma: Ensures trailing commas in multi-line imports.

3. [project]

Introduced in PEP 621, this section standardizes project metadata, reducing reliance on setup.py.

[project]
name = "my-awesome-project"
version = "0.1.0"
description = "An awesome Python project"
readme = "README.md"
requires-python = ">=3.8"
authors = [
    { name="Syed Jafer K", email="syed@example.com" }
]
dependencies = [
    "requests>=2.25.1",
    "fastapi"
]
license = { file = "LICENSE" }
keywords = ["python", "awesome", "project"]
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent"
]

  • name, version, description: Basic project metadata.
  • readme: Path to the README file.
  • requires-python: Specifies compatible Python versions.
  • authors: List of project authors.
  • dependencies: Project dependencies.
  • license: Specifies the project’s license.
  • keywords: Helps with project discovery in package repositories.
  • classifiers: Provides metadata for tools like PyPI to categorize the project.

4. Optional scripts and entry-points

Define CLI commands:

[project.scripts]
mycli = "my_module:main"

  • scripts: Maps command-line scripts to Python functions, allowing users to run mycli directly after installing the package.

Tools That Support pyproject.toml

  • Build tools: Poetry, Flit, setuptools
  • Linters/Formatters: Black, isort, Ruff
  • Test frameworks: Pytest (via addopts)
  • Package managers: Pip (PEP 517/518 compliant)
  • Documentation tools: Sphinx

Migration Tips

  • Gradual Migration: Move one configuration at a time to avoid breaking changes.
  • Backwards Compatibility: Keep older config files during transition if needed.
  • Testing: Use CI pipelines to ensure the new configuration doesn’t break the build.

Troubleshooting Common Issues

  1. Build Failures with Pip: Ensure build-system.requires includes all necessary build tools.
  2. Incompatible Tools: Check for the latest versions of tools to ensure pyproject.toml support.
  3. Configuration Errors: Validate your TOML file with online validators like TOML Lint.

Further Reading:

📢 Python Learning 2.0 in Tamil – Call for Participants! 🚀

After an incredible year of Python learning Watch our journey here, we’re back with an all new approach for 2025!

If you haven’t subscribed to our channel, don’t miss to do it ? Support Us by subscribing

This time, we’re shifting gears from theory to practice with mini projects that will help you build real-world solutions. Study materials will be shared beforehand, and you’ll work hands-on to solve practical problems building actual projects that showcase your skills.

🔑 What’s New?

✅ Real-world mini projects
✅ Task-based shortlisting process
✅ Limited seats for focused learning
✅ Dedicated WhatsApp group for discussions & mentorship
✅ Live streaming of sessions for wider participation
✅ Study materials, quizzes, surprise gifts, and more!

📋 How to Join?

  1. Fill the below RSVP – Open for 20 days (till – March 2) only!
  2. After RSVP closes, shortlisted participants will receive tasks via email.
  3. Complete the tasks to get shortlisted.
  4. Selected students will be added to an exclusive WhatsApp group for intensive training.
  5. It’s a COST-FREE learning. We require your time, effort and support.
  6. Course start date will be announced after RSVP.

📜 RSVP Form

☎ How to Contact for Queries ?

If you have any queries, feel free to message in whatsapp, telegram, signal on this number 9176409201.

You can also mail me at learnwithjafer@gmail.com

Follow us for more oppurtunities/updates and more…

Don’t miss this chance to level up your Python skills Cost Free with hands-on projects and exciting rewards! RSVP now and be part of Python Learning 2.0! 🚀

Our Previous Monthly meets – https://www.youtube.com/watch?v=cPtyuSzeaa8&list=PLiutOxBS1MizPGGcdfXF61WP5pNUYvxUl&pp=gAQB

Our Previous Sessions,

Postgres – https://www.youtube.com/watch?v=04pE5bK2-VA&list=PLiutOxBS1Miy3PPwxuvlGRpmNo724mAlt&pp=gAQB

Python – https://www.youtube.com/watch?v=lQquVptFreE&list=PLiutOxBS1Mizte0ehfMrRKHSIQcCImwHL&pp=gAQB

Docker – https://www.youtube.com/watch?v=nXgUBanjZP8&list=PLiutOxBS1Mizi9IRQM-N3BFWXJkb-hQ4U&pp=gAQB

Note: If you wish to support me for this initiative please share this with your friends, students and those who are in need.

Learning Notes #70 – RUFF An extremely fast Python linter and code formatter, written in Rust.

In the field of Python development, maintaining clean, readable, and efficient code is needed.

The Ruff Python package is a faster linter and code formatter designed to boost code quality and developer productivity. Written in Rust, Ruff stands out for its blazing speed and comprehensive feature set.

This blog will delve into Ruff’s features, usage, and how it compares to other popular Python linters and formatters like flake8, pylint, and black.

What is Ruff?

Ruff is an extremely fast Python linter and code formatter that provides linting, code formatting, and static code analysis in a single package. It supports a wide range of rules out of the box, covering various Python standards and style guides.

Key Features of Ruff

  1. Lightning-fast Performance: Written in Rust, Ruff is significantly faster than traditional Python linters.
  2. All-in-One Tool: Combines linting, formatting, and static analysis.
  3. Extensive Rule Support: Covers rules from flake8, isort, pyflakes, pylint, and more.
  4. Customizable: Allows configuration of rules to fit specific project needs.
  5. Seamless Integration: Works well with CI/CD pipelines and popular code editors.

Installing Ruff


# Using pip
pip install ruff

# Using Homebrew (macOS/Linux)
brew install ruff

# Using UV
uv add ruff

Basic Usage

1. Linting a python file

# Lint a single file
ruff check app.py

# Lint an entire directory
ruff check src/

2. Auto Fixing Issues

ruff check src/ --fix

3. Formatting Code

While Ruff primarily focuses on linting, it also handles some formatting tasks

ruff format src/

Configuration

Ruff can be configured using a pyproject.toml file

[tool.ruff]
line-length = 88
exclude = ["migrations"]
select = ["E", "F", "W"]  # Enable specific rule categories
ignore = ["E501"]          # Ignore specific rules

Examples

import sys
import os

print("Hello World !")


def add(a, b):
    result = a + b
    return a

x= 1
y =2
print(x+y)

def append_to_list(value, my_list=[]):
    my_list.append(value)
    return my_list

def append_to_list(value, my_list=[]):
    my_list.append(value)
    return my_list

  1. Identifying Unused Imports
  2. Auto-fixing Imports
  3. Sorting Imports
  4. Detecting Unused Variables
  5. Enforcing Code Style (PEP 8 Violations)
  6. Detecting Mutable Default Arguments
  7. Fixing Line Length Issues

Integrating Ruff with Pre-commit

To ensure code quality before every commit, integrate Ruff with pre-commit

Step 1: Install Pre-Commit

pip install pre-commit

Step 2: Create a .pre-commit-config.yaml file

repos:
  - repo: https://github.com/charliermarsh/ruff-pre-commit
    rev: v0.1.0  # Use the latest version
    hooks:
      - id: ruff

Step 3: Install the Pre-commit Hook

pre-commit install

Step 4: Test the Hook

pre-commit run --all-files

This setup ensures that Ruff automatically checks your code for linting issues before every commit, maintaining consistent code quality.

When to Use Ruff

  • Large Codebases: Ideal for projects with thousands of files due to its speed.
  • CI/CD Pipelines: Reduces linting time, accelerating build processes.
  • Code Reviews: Ensures consistent coding standards across teams.
  • Open Source Projects: Simplifies code quality management.
  • Pre-commit Hooks: Ensures code quality before committing changes.

Integrating Ruff with CI/CD

name: Lint Code

on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.10'
    - name: Install Ruff
      run: pip install ruff
    - name: Lint Code
      run: ruff check .

Ruff is a game-changer in the Python development ecosystem. Its unmatched speed, comprehensive rule set, and ease of use make it a powerful tool for developers aiming to maintain high code quality.

Whether you’re working on small scripts or large-scale applications, Ruff can streamline your linting and formatting processes, ensuring clean, efficient, and consistent code.

Python variable

This blog explores Python variable usage and functionalities.

Store All Data Types

First, let’s list the data types supported in Python.

Python Supported Data Types

  • Primitive Data Types:
    • Integer
    • Float
    • String
    • Boolean
    • None
  • Non-Primitive Data Types:
    • List
    • Tuple
    • Set
    • Bytes and ByteArray
    • Complex
    • Class Object

Store and Experiment with All Data Types

phone = 1234567890
pi    = 3.14
name  = "python programming"
using_python   = True
example_none   = None
simple_list    = [1,2,3]
simple_dict    = {"name":"python"}
simple_set     = {1,1,1,1,1.0}
simple_tuple   = (1,2,3)
complex_number = 3+5j

print("number     = ",phone)
print("float      = ",pi)
print("boolean    = ",using_python)
print("None       = ",example_none)
print("list       = ",simple_list)
print("dictionary = ",simple_dict)
print("set        = ",simple_set)
print("tuple      = ",simple_tuple)
print("complex    = ",complex_number)

Output

number     =  1234567890
float      =  3.14
boolean    =  True
None       =  None
list       =  [1, 2, 3]
dictionary =  {'name': 'python'}
set        =  {1}
tuple      =  (1, 2, 3)
complex    =  (3+5j)

Type Function

This function is used to print the data type of a variable.

print(type(phone))
print(type(pi))
print(type(using_python))
print(type(simple_list))
print(type(simple_dict))
print(type(simple_set))
print(type(simple_tuple))
print(type(complex_number))
print(type(example_none))

Output

<class 'int'>
<class 'float'>
<class 'bool'>
<class 'list'>
<class 'dict'>
<class 'set'>
<class 'tuple'>
<class 'complex'>
<class 'NoneType'>

Bytes and ByteArray

These data types help modify large binary datasets like audio and image processing.

The memoryview() function allows modifying this data without zero-copy access to memory.

bytes is immutable, where as bytearray is mutable.

bytes

b1 = bytes([1,2,3,4])
bo = memoryview(b1)
print("byte example :",bo[0])

Output

byte example : 1

bytearray

b2 = bytearray(b"aaaa")
bo = memoryview(b2)
print("byte array :",b2)
bo[1] = 98
bo[2] = 99
bo[3] = 100
print("byte array :",b2)

Output

byte array : bytearray(b'aaaa')
byte array : bytearray(b'abcd')

Other Data Types

Frozenset

A frozenset is similar to a normal set, but it is immutable.

test_frozenset = frozenset([1,2,1])
for i in test_frozenset:
    print("frozen set item :",i)

Output

frozen set item : 1
frozen set item : 2

Range

The range data type specifies a number range (e.g., 1-10).

It is mostly used in loops and mathematical operations.

a = range(3)
print("a = ",a)
print("type = ",type(a))

Output

a =  range(0, 3)
type =  <class 'range'>

Type Casting

Type casting is converting a data type into another. Try explicit type casting to change data types.

value = 1
numbers = [1,2,3]
print("type casting int     : ",type(int(value)))
print("type casting float   : ",type(float(value)))
print("type casting string  : ",type(str(value)))
print("type casting boolean : ",type(bool("True")))
print("type casting list    : ",type(list(numbers)))
print("type casting set     : ",type(set(numbers)))
print("type casting tuple   : ",type(tuple(numbers)))

Output

type casting int     :  <class 'int'>
type casting float   :  <class 'float'>
type casting string  :  <class 'str'>
type casting boolean :  <class 'bool'>
type casting list    :  <class 'list'>
type casting set     :  <class 'set'>
type casting tuple   :  <class 'tuple'>

Delete Variable

Delete an existing variable using Python’s del keyword.

temp = 1
print("temp variable is : ",temp)
del temp
# print(temp)  => throw NameError : temp not defined

Output

temp variable is :  1

Find Variable Memory Address

Use the id() function to find the memory address of a variable.

temp = "hi"
print("address of temp variable : ",id(temp))

Output

address of temp variable :  140710894284672

Constants

Python does not have a direct keyword for constants, but namedtuple can be used to create constants.

from collections import namedtuple
const = namedtuple("const",["PI"])
math = const(3.14)

print("namedtuple PI = ",math.PI)
print("namedtuple type =",type(math))

Output

namedtuple PI =  3.14
namedtuple type = <class '__main__.const'>

Global Keyword

Before understanding global keyword, understand function-scoped variables.

  • Function inside variable are stored in stack memory.
  • A function cannot modify an outside (global) variable directly, but it can access it.
  • To create a reference to a global variable inside a function, use the global keyword.
message = "Hi"
def dummy():
    global message 
    message = message+" all"

dummy()
print(message)

Output

Hi all

Explicit Type Hint

Type hints are mostly used in function parameters and arguments.

They improve code readability and help developers understand variable types.

-> float : It indicates the return data type.

def area_of_circle(radius :float) -> float:
    PI :float = 3.14
    return PI * (radius * radius)

print("calculate area of circle = ",area_of_circle(2))

Output

calculate area of circle =  12.56

Learning Notes #68 – Buildpacks and Dockerfile

  1. What is an OCI ?
  2. Does Docker Create OCI Images?
  3. What is a Buildpack ?
  4. Overview of Buildpack Process
  5. Builder: The Image That Executes the Build
    1. Components of a Builder Image
    2. Stack: The Combination of Build and Run Images
  6. Installation and Initial Setups
  7. Basic Build of an Image (Python Project)
    1. Building an image using buildpack
    2. Building an Image using Dockerfile
  8. Unique Benefits of Buildpacks
    1. No Need for a Dockerfile (Auto-Detection)
    2. Automatic Security Updates
    3. Standardized & Reproducible Builds
    4. Extensibility: Custom Buildpacks
  9. Generating SBOM in Buildpacks
    1. a) Using pack CLI to Generate SBOM
    2. b) Generate SBOM in Docker

Last few days, i was exploring on Buildpacks. I am amused at this tool features on reducing the developer’s pain. In this blog i jot down my experience on Buildpacks.

Before going to try Buildpacks, we need to understand what is an OCI ?

What is an OCI ?

An OCI Image (Open Container Initiative Image) is a standard format for container images, defined by the Open Container Initiative (OCI) to ensure interoperability across different container runtimes (Docker, Podman, containerd, etc.).

It consists of,

  1. Manifest – Metadata describing the image (layers, config, etc.).
  2. Config JSON – Information about how the container should run (CMD, ENV, etc.).
  3. Filesystem Layers – The actual file system of the container.

OCI Image Specification ensures that container images built once can run on any OCI-compliant runtime.

Does Docker Create OCI Images?

Yes, Docker creates OCI-compliant images. Since Docker v1.10+, Docker has been aligned with the OCI Image Specification, and all Docker images are OCI-compliant by default.

  • When you build an image with docker build, it follows the OCI Image format.
  • When you push/pull images to registries like Docker Hub, they follow the OCI Image Specification.

However, Docker also supports its legacy Docker Image format, which existed before OCI was introduced. Most modern registries and runtimes (Kubernetes, Podman, containerd) support OCI images natively.

What is a Buildpack ?

A buildpack is a framework for transforming application source code into a runnable image by handling dependencies, compilation, and configuration. Buildpacks are widely used in cloud environments like Heroku, Cloud Foundry, and Kubernetes (via Cloud Native Buildpacks).

Overview of Buildpack Process

The buildpack process consists of two primary phases

  • Detection Phase: Determines if the buildpack should be applied based on the app’s dependencies.
  • Build Phase: Executes the necessary steps to prepare the application for running in a container.

Buildpacks work with a lifecycle manager (e.g., Cloud Native Buildpacks’ lifecycle) that orchestrates the execution of multiple buildpacks in an ordered sequence.

Builder: The Image That Executes the Build

A builder is an image that contains all necessary components to run a buildpack.

Components of a Builder Image

  1. Build Image – Used during the build phase (includes compilers, dependencies, etc.).
  2. Run Image – A minimal environment for running the final built application.
  3. Lifecycle – The core mechanism that executes buildpacks, orchestrates the process, and ensures reproducibility.

Stack: The Combination of Build and Run Images

  • Build Image + Run Image = Stack
  • Build Image: Base OS with tools required for building (e.g., Ubuntu, Alpine).
  • Run Image: Lightweight OS with only the runtime dependencies for execution.

Installation and Initial Setups

Basic Build of an Image (Python Project)

Project Source: https://github.com/syedjaferk/gh_action_docker_build_push_fastapi_app

Building an image using buildpack

Before running these commands, ensure you have Pack CLI (pack) installed.

a) Detect builder suggest

pack builder suggest

b) Build the image

pack build my-app --builder paketobuildpacks/builder:base

c) Run the image locally


docker run -p 8080:8080 my-python-app

Building an Image using Dockerfile

a) Dockerfile


FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .

RUN pip install -r requirements.txt

COPY ./random_id_generator ./random_id_generator
COPY app.py app.py

EXPOSE 8080

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]

b) Build and Run


docker build -t my-python-app .
docker run -p 8080:8080 my-python-app

Unique Benefits of Buildpacks

No Need for a Dockerfile (Auto-Detection)

Buildpacks automatically detect the language and dependencies, removing the need for Dockerfile.


pack build my-python-app --builder paketobuildpacks/builder:base

It detects Python, installs dependencies, and builds the app into a container. 🚀 Docker requires a Dockerfile, which developers must manually configure and maintain.

Automatic Security Updates

Buildpacks automatically patch base images for security vulnerabilities.

If there’s a CVE in the OS layer, Buildpacks update the base image without rebuilding the app.


pack rebase my-python-app

No need to rebuild! It replaces only the OS layers while keeping the app the same.

Standardized & Reproducible Builds

Ensures consistent images across environments (dev, CI/CD, production). Example: Running the same build locally and on Heroku/Cloud Run,


pack build my-app

Extensibility: Custom Buildpacks

Developers can create custom Buildpacks to add special dependencies.

Example: Adding ffmpeg to a Python buildpack,


pack buildpack package my-custom-python-buildpack --path .

Generating SBOM in Buildpacks

a) Using pack CLI to Generate SBOM

After building an image with pack, run,


pack sbom download my-python-app --output-dir ./sbom
  • This fetches the SBOM for your built image.
  • The SBOM is saved in the ./sbom/ directory.

✅ Supported formats:

  • SPDX (sbom.spdx.json)
  • CycloneDX (sbom.cdx.json)

b) Generate SBOM in Docker


trivy image --format cyclonedx -o sbom.json my-python-app

Both are helpful in creating images. Its all about the tradeoffs.

Understanding RAGAS: A Comprehensive Framework for RAG System Evaluation

In the rapidly evolving landscape of artificial intelligence, Retrieval Augmented Generation (RAG) systems have emerged as a crucial technology for enhancing Large Language Models with external knowledge. However, ensuring the quality and reliability of these systems requires robust evaluation methods. Enter RAGAS (Retrieval Augmented Generation Assessment System), a groundbreaking framework that provides comprehensive metrics for evaluating RAG systems.

The Importance of RAG Evaluation

RAG systems combine the power of retrieval mechanisms with generative AI to produce more accurate and contextually relevant responses. However, their complexity introduces multiple potential points of failure, from retrieval accuracy to answer generation quality. This is where RAGAS steps in, offering a structured approach to assessment that helps developers and organizations maintain high standards in their RAG implementations.

Core RAGAS Metrics

Context Precision

Context precision measures how relevant the retrieved information is to the given query. This metric evaluates whether the system is pulling in the right pieces of information from its knowledge base. A high context precision score indicates that the retrieval component is effectively identifying and selecting relevant content, while a low score might suggest that the system is retrieving tangentially related or irrelevant information.

Faithfulness

Faithfulness assesses the alignment between the generated answer and the provided context. This crucial metric ensures that the system's responses are grounded in the retrieved information rather than hallucinated or drawn from the model's pre-trained knowledge. A faithful response should be directly supported by the context, without introducing external or contradictory information.

Answer Relevancy

The answer relevancy metric evaluates how well the generated response addresses the original question. This goes beyond mere factual accuracy to assess whether the answer provides the information the user was seeking. A highly relevant answer should directly address the query's intent and provide appropriate detail level.

Context Recall

Context recall compares the retrieved contexts against ground truth information, measuring how much of the necessary information was successfully retrieved. This metric helps identify cases where critical information might be missing from the system's responses, even if what was retrieved was accurate.

Practical Implementation

RAGAS's implementation is designed to be straightforward while providing deep insights. The framework accepts evaluation datasets containing:

Questions posed to the system
Retrieved contexts for each question
Generated answers
Ground truth answers for comparison

This structured approach allows for automated evaluation across multiple dimensions of RAG system performance, providing a comprehensive view of system quality.

Benefits and Applications

Quality Assurance

RAGAS enables continuous monitoring of RAG system performance, helping teams identify degradation or improvements over time. This is particularly valuable when making changes to the retrieval mechanism or underlying models.

Development Guidance

The granular metrics provided by RAGAS help developers pinpoint specific areas needing improvement. For instance, low context precision scores might indicate the need to refine the retrieval strategy, while poor faithfulness scores might suggest issues with the generation parameters.

Comparative Analysis

Organizations can use RAGAS to compare different RAG implementations or configurations, making it easier to make data-driven decisions about system architecture and deployment.

Best Practices for RAGAS Implementation

  1. Regular Evaluation Implement RAGAS as part of your regular testing pipeline to catch potential issues early and maintain consistent quality.
  2. Diverse Test Sets Create evaluation datasets that cover various query types, complexities, and subject matters to ensure robust assessment.
  3. Metric Thresholds Establish minimum acceptable scores for each metric based on your application's requirements and use these as quality gates in your deployment process.
  4. Iterative Refinement Use RAGAS metrics to guide iterative improvements to your RAG system, focusing on the areas showing the lowest performance scores.

Practical Code Examples

Basic RAGAS Evaluation

Here's a simple example of how to implement RAGAS evaluation in your Python code:

from ragas import evaluate
from datasets import Dataset
from ragas.metrics import (
    faithfulness,
    answer_relevancy,
    context_precision
)

def evaluate_rag_system(questions, contexts, answers, references):
    """
    Simple function to evaluate a RAG system using RAGAS

    Args:
        questions (list): List of questions
        contexts (list): List of contexts for each question
        answers (list): List of generated answers
        references (list): List of reference answers (ground truth)

    Returns:
        EvaluationResult: RAGAS evaluation results
    """
    # First, let's make sure you have the required packages
    try:
        import ragas
        import datasets
    except ImportError:
        print("Please install required packages:")
        print("pip install ragas datasets")
        return None

    # Prepare evaluation dataset
    eval_data = {
        "question": questions,
        "contexts": [[ctx] for ctx in contexts],  # RAGAS expects list of lists
        "answer": answers,
        "reference": references
    }

    # Convert to Dataset format
    eval_dataset = Dataset.from_dict(eval_data)

    # Run evaluation with key metrics
    results = evaluate(
        eval_dataset,
        metrics=[
            faithfulness,      # Measures if answer is supported by context
            answer_relevancy,  # Measures if answer is relevant to question
            context_precision  # Measures if retrieved context is relevant
        ]
    )

    return results

# Example usage
if __name__ == "__main__":
    # Sample data
    questions = [
        "What are the key features of Python?",
        "How does Python handle memory management?"
    ]

    contexts = [
        "Python is a high-level programming language known for its simple syntax and readability. It supports multiple programming paradigms including object-oriented, imperative, and functional programming.",
        "Python uses automatic memory management through garbage collection. It employs reference counting as the primary mechanism and has a cycle-detecting garbage collector for handling circular references."
    ]

    answers = [
        "Python is known for its simple syntax and readability, and it supports multiple programming paradigms including OOP.",
        "Python handles memory management automatically through garbage collection, using reference counting and cycle detection."
    ]

    references = [
        "Python's key features include readable syntax and support for multiple programming paradigms like OOP, imperative, and functional programming.",
        "Python uses automatic garbage collection with reference counting and cycle detection for memory management."
    ]

    # Run evaluation
    results = evaluate_rag_system(
        questions=questions,
        contexts=contexts,
        answers=answers,
        references=references
    )

    if results:
        # Print results
        print("\nRAG System Evaluation Results:")
        print(results)  

Welcoming Winter with Python – PyKids and PyLadies

Winter Break for kids

In Canada, we have around 15 days of winter break for all school kids, covering Christmas and New year.

These celebrations are helping much to come out of the winter worries.

Winter is scary word, but people have to go through it, as life has to go on. As we can not travel much and there are no outdoor events/games, we have to be at home, all the days, weeks and months. Organizing indoor events are costly.

To spend the winter actively, many celebrations days are occurring. Halloween, Christmas, Boxing day, New year, Valentine day and more are there, to make the winter active.

Keeping the kids at home for 17 days winter break is tough. We have to engage them whole day. In our apartment, we are conducting many kids events like weekly chess hour, dance hours, board games day, movie time, sleep over nights etc.

Computer Literacy is good here. Kids are learning to use computer at school, from Grade 3 itself. They play many educational games at school. Homework are done with google slides and google docs, from grade 5. Scratch programming also trained here at grade 5. So, they know very well to use computer, read text online, search the internet and gather some info etc.

PyKids

This time, thought of having some tech events for kids. Called for 10 days training as “PyKids”, for grade 5 and above. The announcement was welcomed well by many parents. We had around 17 kids participated.

As our house is empty mostly, ( thanks to Nithya, for the minimalistic life style ), our hall helped for gathering and teaching.

By keeping the hall empty, we are using the place as Daily Zumba dance hall, mini party hall, DJ hall, kids play area and now as a learning place.

Teaching Python for kids is not easy. The kids are not ready to listen to any long talks. They can not even listen to my regular “python introduction” slides. So, jumped into hands-on on the day one itself.

My mentor, Asokan Pichai explained how we have to goto hands-on on any python training, few months ago. Experienced the benefits of it this time.

Even-though, I am using Python for 10+ years, teaching it to kids was really tough. I had to read few books and read on more basics, so that I can explain the building blocks of python with more relevant examples for kids.

The kids are good at asking questions. They share feedback with their eyes itself. It is a huge different on teaching to adults. Most of the adults don’t ask questions. They hesitate to say they don’t understand something. But, kids are brave enough to ask questions and express the feedback immediately.

With a training on 4-6 pm everyday, for around 10 days, we can cover so little of python only.

We practiced the code here – https://github.com/tshrinivasan/python-for-kids We used https://www.online-python.com/ as IDE, as the kids have laptops and tablets with different OS. Will install Python on their laptops on next events so that they can explore more python libraries.

On the final day, my friend Jay Varadharajan, gave a Pizza party for all kids, along with a participation certificate.

Thanks for all the questions kids. Along with you, I learnt a lot. Thanks for all the parents for the great support.

PyLadies

Nithya wanted to try out full day training for her friends. Getting a time of 9-5 to learn something is so luxury for many people. Still, around 10 friends participated.

Nithya took the day with all hands-on. She covered the variables, getting input, if/else, for/while loop, string/list operations. The participants were happy to dive into programming so quickly.

“A byte of Python” is a super easy book to learn python. Read it here for free. https://python.swaroopch.com/

Gave this link as asked to read/practice regularly. Hope they are following the book.

Hall for PyLadies meetup

Home as Learning Space

Thus, we are converting our home as a learning space for kids and friends. Thinking of conducting some technical meetups too. ( I am missing all the Linux Users groups meetings and hackathons). Hope we can get more tech events in the winter and make it so interesting and productive.

Welcoming Winter with Python – PyKids and PyLadies

Winter Break for kids

In Canada, we have around 15 days of winter break for all school kids, covering Christmas and New year.

These celebrations are helping much to come out of the winter worries.

Winter is scary word, but people have to go through it, as life has to go on. As we can not travel much and there are no outdoor events/games, we have to be at home, all the days, weeks and months. Organizing indoor events are costly.

To spend the winter actively, many celebrations days are occurring. Halloween, Christmas, Boxing day, New year, Valentine day and more are there, to make the winter active.

Keeping the kids at home for 17 days winter break is tough. We have to engage them whole day. In our apartment, we are conducting many kids events like weekly chess hour, dance hours, board games day, movie time, sleep over nights etc.

Computer Literacy is good here. Kids are learning to use computer at school, from Grade 3 itself. They play many educational games at school. Homework are done with google slides and google docs, from grade 5. Scratch programming also trained here at grade 5. So, they know very well to use computer, read text online, search the internet and gather some info etc.

PyKids

This time, thought of having some tech events for kids. Called for 10 days training as “PyKids”, for grade 5 and above. The announcement was welcomed well by many parents. We had around 17 kids participated.

As our house is empty mostly, ( thanks to Nithya, for the minimalistic life style ), our hall helped for gathering and teaching.

By keeping the hall empty, we are using the place as Daily Zumba dance hall, mini party hall, DJ hall, kids play area and now as a learning place.

Teaching Python for kids is not easy. The kids are not ready to listen to any long talks. They can not even listen to my regular “python introduction” slides. So, jumped into hands-on on the day one itself.

My mentor, Asokan Pichai explained how we have to goto hands-on on any python training, few months ago. Experienced the benefits of it this time.

Even-though, I am using Python for 10+ years, teaching it to kids was really tough. I had to read few books and read on more basics, so that I can explain the building blocks of python with more relevant examples for kids.

The kids are good at asking questions. They share feedback with their eyes itself. It is a huge different on teaching to adults. Most of the adults don’t ask questions. They hesitate to say they don’t understand something. But, kids are brave enough to ask questions and express the feedback immediately.

With a training on 4-6 pm everyday, for around 10 days, we can cover so little of python only.

We practiced the code here – https://github.com/tshrinivasan/python-for-kids We used https://www.online-python.com/ as IDE, as the kids have laptops and tablets with different OS. Will install Python on their laptops on next events so that they can explore more python libraries.

On the final day, my friend Jay Varadharajan, gave a Pizza party for all kids, along with a participation certificate.

Thanks for all the questions kids. Along with you, I learnt a lot. Thanks for all the parents for the great support.

PyLadies

Nithya wanted to try out full day training for her friends. Getting a time of 9-5 to learn something is so luxury for many people. Still, around 10 friends participated.

Nithya took the day with all hands-on. She covered the variables, getting input, if/else, for/while loop, string/list operations. The participants were happy to dive into programming so quickly.

“A byte of Python” is a super easy book to learn python. Read it here for free. https://python.swaroopch.com/

Gave this link as asked to read/practice regularly. Hope they are following the book.

Hall for PyLadies meetup

Home as Learning Space

Thus, we are converting our home as a learning space for kids and friends. Thinking of conducting some technical meetups too. ( I am missing all the Linux Users groups meetings and hackathons). Hope we can get more tech events in the winter and make it so interesting and productive.

Minimal Typing Practice Application in Python

Introduction

This is a Python-based single-file application designed for typing practice. It provides a simple interface to improve typing accuracy and speed. Over time, this minimal program has gradually increased my typing skill.

What I Learned from This Project

  • 2D Array Validation
    I first simply used a 1D array to store user input, but I noticed some issues. After implementing a 2D array, I understood why the 2D array was more appropriate for handling user inputs.
  • Tkinter
    I wanted to visually see and update correct, wrong, and incomplete typing inputs, but I didn’t know how to implement it in the terminal. So, I used a simple Tkinter gui window

Run This Program

It depends on the following applications:

  • Python 3
  • python3-tk

Installation Command on Debian-Based Systems

sudo apt install python3 python3-tk

Clone repository and run program

git clone https://github.com/github-CS-krishna/TerminalTyping
cd TerminalTyping
python3 terminalType.py

Links

For more details, refer to the README documentation on GitHub.

This will help you understand how to use it.

source code(github)

Learning Notes #67 – Build and Push to a Registry (Docker Hub) with GH-Actions

GitHub Actions is a powerful tool for automating workflows directly in your repository.In this blog, we’ll explore how to efficiently set up GitHub Actions to handle Docker workflows with environments, secrets, and protection rules.

Why Use GitHub Actions for Docker?

My Code base is in Github and i want to tryout gh-actions to build and push images to docker hub seamlessly.

Setting Up GitHub Environments

GitHub Environments let you define settings specific to deployment stages. Here’s how to configure them:

1. Create an Environment

Go to your GitHub repository and navigate to Settings > Environments. Click New environment, name it (e.g., production), and save.

2. Add Secrets and Variables

Inside the environment settings, click Add secret to store sensitive information like DOCKER_USERNAME and DOCKER_TOKEN.

Use Variables for non-sensitive configuration, such as the Docker image name.

3. Optional: Set Protection Rules

Enforce rules like requiring manual approval before deployments. Restrict deployments to specific branches (e.g., main).

Sample Workflow for Building and Pushing Docker Images

Below is a GitHub Actions workflow for automating the build and push of a Docker image based on a minimal Flask app.

Workflow: .github/workflows/docker-build-push.yml


name: Build and Push Docker Image

on:
  push:
    branches:
      - main  # Trigger workflow on pushes to the `main` branch

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    environment: production  # Specify the environment to use

    steps:
      # Checkout the repository
      - name: Checkout code
        uses: actions/checkout@v3

      # Log in to Docker Hub using environment secrets
      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}

      # Build the Docker image using an environment variable
      - name: Build Docker image
        env:
          DOCKER_IMAGE_NAME: ${{ vars.DOCKER_IMAGE_NAME }}
        run: |
          docker build -t ${{ secrets.DOCKER_USERNAME }}/$DOCKER_IMAGE_NAME:${{ github.run_id }} .

      # Push the Docker image to Docker Hub
      - name: Push Docker image
        env:
          DOCKER_IMAGE_NAME: ${{ vars.DOCKER_IMAGE_NAME }}
        run: |
          docker push ${{ secrets.DOCKER_USERNAME }}/$DOCKER_IMAGE_NAME:${{ github.run_id }}

To Actions on live: https://github.com/syedjaferk/gh_action_docker_build_push_fastapi_app/actions

SelfHost #2 | BugSink – An Error Tracking Tool

I am regular follower of https://selfh.st/ , last week they showcased about BugSink. Bugsink is a tool to track errors in your applications that you can self-host. It’s easy to install and use, is compatible with the Sentry SDK, and is scalable and reliable.

When an application breaks, finding and fixing the root cause quickly is critical. Hosted error tracking tools often make you trade privacy for convenience, and they can be expensive. On the other hand, self-hosted solutions are an alternative, but they are often a pain to set up and maintain.

What Is Error Tracking?

When code is deployed in production, errors are inevitable. They can arise from a variety of reasons like bugs in the code, network failures, integration mismatches, or even unforeseen user behavior. To ensure smooth operation and user satisfaction, error tracking is essential.

Error tracking involves monitoring and recording errors in your application code, particularly in production environments. A good error tracker doesn’t just log errors; it contextualizes them, offering insights that make troubleshooting straightforward.

Here are the key benefits of error tracking

  • Early Detection: Spot issues before they snowball into critical outages.
  • Context-Rich Reporting: Understand the “what, when, and why” of an error.
  • Faster Debugging: Detailed stack traces make it easier to pinpoint root causes.

Effective error tracking tools allow developers to respond to errors proactively, minimizing user impact.

Why Bugsink?

Bugsink takes error tracking to a new level by prioritizing privacy, simplicity, and compatibility.

1. Built for Self-Hosting

Unlike many hosted error tracking tools that require sensitive data to be shared with third-party servers, Bugsink is self-hosted. This ensures you retain full control over your data, a critical aspect for privacy-conscious teams.

2. Easy to Set Up and Manage

Whether you’re deploying it on your local server or in the cloud, the experience is smooth.

3. Resource Efficiency

Bugsink is designed to be lightweight and efficient. It doesn’t demand hefty server resources, making it an ideal choice for startups, small teams, or resource-constrained environments.

4. Compatible with Sentry

If you’ve used Sentry before, you’ll feel right at home with Bugsink. It offers Sentry compatibility, allowing you to migrate effortlessly or use it alongside existing tools. This compatibility also means you can leverage existing SDKs and integrations.

5. Proactive Notifications

Bugsink ensures you’re in the loop as soon as something goes wrong. Email notifications alert you the moment an error occurs, enabling swift action. This proactive approach reduces the mean time to resolution (MTTR) and keeps users happy.

Docs: https://www.bugsink.com/docs/

In this blog, i jot down my experience on using BugSink with Python.

1. Run using Docker

There are many ways proposed for BugSink installation, https://www.bugsink.com/docs/installation/. In this blog, i am trying using docker.


docker pull bugsink/bugsink:latest

docker run \
  -e SECRET_KEY=ab4xjs5wfnP2XrUwRJPtmk1sEnMcx9d2mta8vtbdZ4oOtvy5BJ \
  -e CREATE_SUPERUSER=admin:admin \
  -e PORT=8000 \
  -p 8000:8000 \
  bugsink/bugsink

2. Log In, Create a Team, Project

The Application will run at port 8000.

Login using admin/admin. Create a new team, by clicking the top right button.

Give a name to the team,

then create a project, under this team,

After creating a project, you will be able to see like below,

You will get an individual DSN , like http://9d0186dd7b854205bed8d60674f349ea@localhost:8000/1.

3. Attaching DSN to python app



import sentry_sdk

sentry_sdk.init(
    "http://d76bc0ccf4da4423b71d1fa80d6004a3@localhost:8000/1",

    send_default_pii=True,
    max_request_body_size="always",
    traces_sample_rate=0,
)

def divide(num1, num2):
    return num1/num2

divide(1, 0)


The above program, will throw an Zero Division Error, which will be reflected in BugSink application.

The best part is you will get the value of variables at that instance. In this example, you can see values of num1 and num2.

There are lot more awesome features out there https://www.bugsink.com/docs/.

RAG vs GraphRAG

Introduction to RAG and GraphRAG

What is RAG?

RAG, or Retrieval-Augmented Generation, is a technique that combines information retrieval with text generation to produce more accurate and contextually relevant responses. It works by retrieving relevant information from a knowledge base and then using that information to augment the input to a large language model (LLM).

What is GraphRAG?

GraphRAG is an extension of the RAG framework that incorporates graph-structured knowledge. Instead of using a flat document-based retrieval system, GraphRAG utilizes graph databases to represent and query complex relationships between entities and concepts.

Applications of RAG and GraphRAG

RAG Applications

  1. Question-answering systems
  2. Chatbots and virtual assistants
  3. Content summarization
  4. Fact-checking and information verification
  5. Personalized content generation

GraphRAG Applications

  1. Knowledge graph-based question answering
  2. Complex reasoning tasks
  3. Recommendation systems
  4. Fraud detection and financial analysis
  5. Scientific research and literature review

Pros and Cons of RAG

Pros of RAG

  1. Improved accuracy: By retrieving relevant information, RAG can provide more accurate and up-to-date responses.
  2. Reduced hallucinations: The retrieval step helps ground the model's responses in factual information.
  3. Scalability: Easy to update the knowledge base without retraining the entire model.
  4. Transparency: The retrieved documents can be used to explain the model's reasoning.
  5. Customizability: Can be tailored to specific domains or use cases.

Cons of RAG

  1. Latency: The retrieval step can introduce additional latency compared to pure generation models.
  2. Complexity: Implementing and maintaining a RAG system can be more complex than using a standalone LLM.
  3. Quality-dependent: The system's performance heavily relies on the quality and coverage of the knowledge base.
  4. Potential for irrelevant retrievals: If the retrieval system is not well-tuned, it may fetch irrelevant information.
  5. Storage requirements: Maintaining a large knowledge base can be resource-intensive.

Pros and Cons of GraphRAG

Pros of GraphRAG

  1. Complex relationship modeling: Can represent and query intricate relationships between entities.
  2. Improved context understanding: Graph structure allows for better capturing of contextual information.
  3. Multi-hop reasoning: Enables answering questions that require following multiple steps or connections.
  4. Flexibility: Can incorporate various types of information and relationships in a unified framework.
  5. Efficient querying: Graph databases can be more efficient for certain types of queries compared to traditional databases.

Cons of GraphRAG

  1. Increased complexity: Building and maintaining a knowledge graph is more complex than a document-based system.
  2. Higher computational requirements: Graph operations can be more computationally intensive.
  3. Data preparation challenges: Converting unstructured data into a graph format can be time-consuming and error-prone.
  4. Potential for overfitting: If the graph structure is too specific, it may not generalize well to new queries.
  5. Scalability concerns: As the graph grows, managing and querying it efficiently can become challenging.

Comparing RAG and GraphRAG

When to Use RAG

  • For general-purpose question-answering systems
  • When dealing with primarily textual information
  • In scenarios where quick implementation and simplicity are priorities
  • For applications that don't require complex relationship modeling

When to Use GraphRAG

  • For domain-specific applications with complex relationships (e.g., scientific research, financial analysis)
  • When multi-hop reasoning is crucial
  • In scenarios where understanding context and relationships is more important than raw text retrieval
  • For applications that can benefit from a structured knowledge representation

Future Directions and Challenges

Advancements in RAG

  1. Improved retrieval algorithms
  2. Better integration with LLMs
  3. Real-time knowledge base updates
  4. Multi-modal RAG (incorporating images, audio, etc.)

Advancements in GraphRAG

  1. More efficient graph embedding techniques
  2. Integration with other AI techniques (e.g., reinforcement learning)
  3. Automated graph construction and maintenance
  4. Explainable AI through graph structures

Common Challenges

  1. Ensuring data privacy and security
  2. Handling biases in knowledge bases
  3. Improving computational efficiency
  4. Enhancing the interpretability of results

Conclusion

Both RAG and GraphRAG represent significant advancements in augmenting language models with external knowledge. While RAG offers a more straightforward approach suitable for many general applications, GraphRAG provides a powerful framework for handling complex, relationship-rich domains. The choice between the two depends on the specific requirements of the application, the nature of the data, and the complexity of the reasoning tasks involved. As these technologies continue to evolve, we can expect to see even more sophisticated and efficient ways of combining retrieval, reasoning, and generation in AI systems.

Learning Notes #54 – Architecture Decision Records

Last few days, i was learning on how to make a accountable decision on deciding technical stuffs. Then i came across ADR. So far i haven’t used or seen used by our team. I think this is a necessary step to be incorporated to make accountable decisions. In this blog i share details on ADR for my future reference.

What is an ADR?

An Architectural Decision Record (ADR) is a concise document that captures a single architectural decision, its context, the reasoning behind it, and its consequences. ADRs help teams document, share, and revisit architectural choices, ensuring transparency and better collaboration.

Why Use ADRs?

  1. Documentation: ADRs serve as a historical record of why certain decisions were made.
  2. Collaboration: They promote better understanding across teams.
  3. Traceability: ADRs link architectural decisions to specific project requirements and constraints.
  4. Accountability: They clarify who made a decision and when.
  5. Change Management: ADRs help evaluate the impact of changes and facilitate discussions around reversals or updates.

ADR Structure

A typical ADR document follows a standard format. Here’s an example:

  1. Title: A clear and concise title describing the decision.
  2. Context: Background information explaining the problem or opportunity.
  3. Decision: A summary of the chosen solution.
  4. Consequences: The positive and negative outcomes of the decision.
  5. Status: Indicates whether the decision is proposed, accepted, superseded, or deprecated.

Example:

Optimistic locking on MongoDB https://docs.google.com/document/d/1olCbicQeQzYpCxB0ejPDtnri9rWb2Qhs9_JZuvANAxM/edit?usp=sharing

References

  1. https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
  2. https://www.infoq.com/podcasts/architecture-advice-process/
  3. Recommended: https://github.com/joelparkerhenderson/architecture-decision-record/tree/main

Learning Notes #52 – Hybrid Origin Failover Pattern

Today, i learnt about failover patterns from AWS https://aws.amazon.com/blogs/networking-and-content-delivery/three-advanced-design-patterns-for-high-available-applications-using-amazon-cloudfront/ . In this blog i jot down my understanding on this pattern for future reference,

Hybrid origin failover is a strategy that combines two distinct approaches to handle origin failures effectively, balancing speed and resilience.

The Need for Origin Failover

When an application’s primary origin server becomes unavailable, the ability to reroute traffic to a secondary origin ensures continuity. The failover process determines how quickly and effectively this switch happens. Broadly, there are two approaches to implement origin failover:

  1. Stateful Failover with DNS-based Routing
  2. Stateless Failover with Application Logic

Each has its strengths and limitations, which the hybrid approach aims to mitigate.

Stateful Failover

Stateful failover is a system that allows a standby server to take over for a failed server and continue active sessions. It’s used to create a resilient network infrastructure and avoid service interruptions.

This method relies on a DNS service with health checks to detect when the primary origin is unavailable. Here’s how it works,

  1. Health Checks: The DNS service continuously monitors the health of the primary origin using health checks (e.g., HTTP, HTTPS).
  2. DNS Failover: When the primary origin is marked unhealthy, the DNS service resolves the origin’s domain name to the secondary origin’s IP address.
  3. TTL Impact: The failover process honors the DNS Time-to-Live (TTL) settings. A low TTL ensures faster propagation, but even in the most optimal configurations, this process introduces a delay—often around 60 to 70 seconds.
  4. Stateful Behavior: Once failover occurs, all traffic is routed to the secondary origin until the primary origin is marked healthy again.

Implementation from AWS (as-is from aws blog)

The first approach is using Amazon Route 53 Failover routing policy with health checks on the origin domain name that’s configured as the origin in CloudFront. When the primary origin becomes unhealthy, Route 53 detects it, and then starts resolving the origin domain name with the IP address of the secondary origin. CloudFront honors the origin DNS TTL, which means that traffic will start flowing to the secondary origin within the DNS TTLs. The most optimal configuration (Fast Check activated, a failover threshold of 1, and 60 second DNS TTL) means that the failover will take 70 seconds at minimum to occur. When it does, all of the traffic is switched to the secondary origin, since it’s a stateful failover. Note that this design can be further extended with Route 53 Application Recovery Control for more sophisticated application failover across multiple AWS Regions, Availability Zones, and on-premises.

The second approach is using origin failover, a native feature of CloudFront. This capability of CloudFront tries for the primary origin of every request, and if a configured 4xx or 5xx error is received, then CloudFront attempts a retry with the secondary origin. This approach is simple to configure and provides immediate failover. However, it’s stateless, which means every request must fail independently, thus introducing latency to failed requests. For transient origin issues, this additional latency is an acceptable tradeoff with the speed of failover, but it’s not ideal when the origin is completely out of service. Finally, this approach only works for the GET/HEAD/OPTIONS HTTP methods, because other HTTP methods are not allowed on a CloudFront cache behavior with Origin Failover enabled.

Advantages

  • Works for all HTTP methods and request types.
  • Ensures complete switchover, minimizing ongoing failures.

Disadvantages

  • Relatively slower failover due to DNS propagation time.
  • Requires a reliable health-check mechanism.

Approach 2: Stateless Failover with Application Logic

This method handles failover at the application level. If a request to the primary origin fails (e.g., due to a 4xx or 5xx HTTP response), the application or CDN immediately retries the request with the secondary origin.

How It Works

  1. Primary Request: The application sends a request to the primary origin.
  2. Failure Handling: If the response indicates a failure (configurable for specific error codes), the request is retried with the secondary origin.
  3. Stateless Behavior: Each request operates independently, so failover happens on a per-request basis without waiting for a stateful switchover.

Implementation from AWS (as-is from aws blog)

The hybrid origin failover pattern combines both approaches to get the best of both worlds. First, you configure both of your origins with a Failover Policy in Route 53 behind a single origin domain name. Then, you configure an origin failover group with the single origin domain name as primary origin, and the secondary origin domain name as secondary origin. This means that when the primary origin becomes unavailable, requests are immediately retried with the secondary origin until the stateful failover of Route 53 kicks in within tens of seconds, after which requests go directly to the secondary origin without any latency penalty. Note that this pattern only works with the GET/HEAD/OPTIONS HTTP methods.

Advantages

  • Near-instantaneous failover for failed requests.
  • Simple to configure and doesn’t depend on DNS TTL.

Disadvantages

  • Adds latency for failed requests due to retries.
  • Limited to specific HTTP methods like GET, HEAD, and OPTIONS.
  • Not suitable for scenarios where the primary origin is entirely down, as every request must fail first.

The Hybrid Origin Failover Pattern

The hybrid origin failover pattern combines the strengths of both approaches, mitigating their individual limitations. Here’s how it works:

  1. DNS-based Stateful Failover: A DNS service with health checks monitors the primary origin and switches to the secondary origin if the primary becomes unhealthy. This ensures a complete and stateful failover within tens of seconds.
  2. Application-level Stateless Failover: Simultaneously, the application or CDN is configured to retry failed requests with a secondary origin. This provides an immediate failover mechanism for transient or initial failures.

Implementation Steps

  1. DNS Configuration
    • Set up health checks on the primary origin.
    • Define a failover policy in the DNS service, which resolves the origin domain name to the secondary origin when the primary is unhealthy.
  2. Application Configuration
    • Configure the application or CDN to use an origin failover group.
    • Specify the primary origin domain as the primary origin and the secondary origin domain as the backup.

Behavior

  • Initially, if the primary origin encounters issues, requests are retried immediately with the secondary origin.
  • Meanwhile, the DNS failover switches all traffic to the secondary origin within tens of seconds, eliminating retry latencies for subsequent requests.

Benefits of Hybrid Origin Failover

  1. Faster Failover: Immediate retries for failed requests minimize initial impact, while DNS failover ensures long-term stability.
  2. Reduced Latency: After DNS failover, subsequent requests don’t experience retry delays.
  3. High Resilience: Combines stateful and stateless failover for robust redundancy.
  4. Simplicity and Scalability: Leverages existing DNS and application/CDN features without complex configurations.

Limitations and Considerations

  1. HTTP Method Constraints: Stateless failover works only for GET, HEAD, and OPTIONS methods, limiting its use for POST or PUT requests.
  2. TTL Impact: Low TTLs reduce propagation delays but increase DNS query rates, which could lead to higher costs.
  3. Configuration Complexity: Combining DNS and application-level failover requires careful setup and testing to avoid misconfigurations.
  4. Secondary Origin Capacity: Ensure the secondary origin can handle full traffic loads during failover.

POTD #19 – Count the number of possible triangles | Geeks For Geeks

Problem Statement

Geeks For Geeks – https://www.geeksforgeeks.org/problems/count-possible-triangles-1587115620/1

Given an integer array arr[]. Find the number of triangles that can be formed with three different array elements as lengths of three sides of the triangle.  A triangle with three given sides is only possible if sum of any two sides is always greater than the third side.


Input: arr[] = [4, 6, 3, 7]
Output: 3
Explanation: There are three triangles possible [3, 4, 6], [4, 6, 7] and [3, 6, 7]. Note that [3, 4, 7] is not a possible triangle.  


Input: arr[] = [10, 21, 22, 100, 101, 200, 300]
Output: 6
Explanation: There can be 6 possible triangles: [10, 21, 22], [21, 100, 101], [22, 100, 101], [10, 100, 101], [100, 101, 200] and [101, 200, 300]

My Approach


class Solution:
    #Function to count the number of possible triangles.
    def countTriangles(self, arr):
        # code here
        arr.sort()
        n = len(arr)
        cnt = 0
        for itr in range(2, n):
            left = 0
            right = itr - 1
            
            while left < right:
                
                if arr[left] + arr[right] > arr[itr]:
                    cnt += right - left
                    right -= 1
                else:
                    left += 1
        return cnt

POTD #11 – Longest Consecutive Subsequence | Geeks For Geeks

Problem Statement

Geeks For Geeks – https://www.geeksforgeeks.org/problems/longest-consecutive-subsequence2449/1

Given an array arr[] of non-negative integers. Find the length of the longest sub-sequence such that elements in the subsequence are consecutive integers, the consecutive numbers can be in any order.


Input: arr[] = [2, 6, 1, 9, 4, 5, 3]
Output: 6
Explanation: The consecutive numbers here are 1, 2, 3, 4, 5, 6. These 6 numbers form the longest consecutive subsquence.


Input: arr[] = [1, 9, 3, 10, 4, 20, 2]
Output: 4
Explanation: 1, 2, 3, 4 is the longest consecutive subsequence.

My Approach

1. Sort the array.Initialize two variables:

  • max_sequence to 1 (to store the length of the longest consecutive subsequence).
  • cont_sub_sequence to 1 (to track the current consecutive subsequence length).

2. Loop through the array starting from the second element:

  • If the current element is equal to the previous one, skip it (handle duplicates).
  • Else, if the difference between the current and previous element is 1:
    • Increment cont_sub_sequence by 1.
  • Otherwise:
    • Update max_sequence as the maximum of max_sequence and cont_sub_sequence.
    • Reset cont_sub_sequence to 1.

3. After the loop, update max_sequence one final time as the maximum of max_sequence and cont_sub_sequence.

4. Return max_sequence.


class Solution:
    
    # arr[] : the input array
    
    #Function to return length of longest subsequence of consecutive integers.
    def longestConsecutive(self,arr):
        #code here
        arr.sort()
        max_sequence = 1
        cont_sub_sequence = 1
        for itr in range(1, len(arr)):
            if arr[itr] == arr[itr-1]:
                continue
            elif arr[itr] - arr[itr-1] == 1:
                cont_sub_sequence += 1
            else:
                if cont_sub_sequence > max_sequence:
                    max_sequence = cont_sub_sequence
                cont_sub_sequence = 1
        
        if cont_sub_sequence > max_sequence:
            max_sequence = cont_sub_sequence
        return max_sequence

Learning Notes #11 – Sidecar Pattern | Cloud Patterns

Today, I learnt about Sidecar Pattern. Its seems like offloading the common functionalities (logging, networking, …) aside within a pod to be used by other apps within the pod.

Its just not only about pods, but other deployments aswell. In this blog, i am going to curate the items i have learnt for my future self. Its a pattern, not an strict rule.

What is a Sidecar?

Imagine you’re riding a motorbike, and you attach a little sidecar to carry your friend or groceries. The sidecar isn’t part of the motorbike’s engine or core mechanism, but it helps you achieve your goals—whether it’s carrying more stuff or having a buddy ride along.

In the software world, a sidecar is a similar concept. It’s a separate process or container that runs alongside a primary application. Like the motorbike’s sidecar, it supports the main application by offloading or enhancing certain tasks without interfering with its core functionality.

Why Use a Sidecar?

In traditional applications, all responsibilities (logging, communication, monitoring, etc.) are bundled into the main application. This approach can make the application complex and harder to manage. Sidecars address this by handling auxiliary tasks separately, so the main application can focus on its primary purpose.

Here are some key reasons to use a sidecar

  1. Modularity: Sidecars separate responsibilities, making the system easier to develop, test, and maintain.
  2. Reusability: The same sidecar can be used across multiple services. And its language agnostic.
  3. Scalability: You can scale the sidecar independently from the main application.
  4. Isolation: Sidecars provide a level of isolation, reducing the risk of one part affecting the other.

Real-Life Analogies

To make the concept clearer, here are some real-world analogies:

  1. Coffee Maker with a Milk Frother:
    • The coffee maker (main application) brews coffee.
    • The milk frother (sidecar) prepares frothed milk for your latte.
    • Both work independently but combine their outputs for a better experience.
  2. Movie Subtitles:
    • The movie (main application) provides the visuals and sound.
    • The subtitles (sidecar) add clarity for those who need them.
    • You can watch the movie with or without subtitles—they’re optional but enhance the experience.
  3. A School with a Sports Coach:
    • The school (main application) handles education.
    • The sports coach (sidecar) focuses on physical training.
    • Both have distinct roles but contribute to the overall development of students.

Some Random Sidecar Ideas in Software

Let’s look at how sidecars are used in actual software scenarios

  1. Service Meshes (e.g., Istio, Linkerd):
    • A service mesh helps microservices communicate with each other reliably and securely.
    • The sidecar (proxy like Envoy) handles tasks like load balancing, encryption, and monitoring, so the main application doesn’t have to.
  2. Logging and Monitoring:
    • Instead of the main application generating and managing logs, a sidecar can collect, format, and send logs to a centralized system like Elasticsearch or Splunk.
  3. Authentication and Security:
    • A sidecar can act as a gatekeeper, handling user authentication and ensuring that only authorized requests reach the main application.
  4. Data Caching:
    • If an application frequently queries a database, a sidecar can serve as a local cache, reducing database load and speeding up responses.
  5. Service Discovery:
    • Sidecars can aid in service discovery by automatically registering the main application with a registry service or load balancer, ensuring seamless communication in dynamic environments.

How Sidecars Work

In modern environments like Kubernetes, sidecars are often deployed as separate containers within the same pod as the main application. They share the same network and storage, making communication between the two seamless.

Here’s a simplified workflow

  1. The main application focuses on its core tasks (e.g., serving a web page).
  2. The sidecar handles auxiliary tasks (e.g., compressing and encrypting logs).
  3. The two communicate over local connections within the pod.

Pros and Cons of Sidecars

Pros:

  • Simplifies the main application.
  • Encourages reusability and modular design.
  • Improves scalability and flexibility.
  • Enhances observability with centralized logging and metrics.
  • Facilitates experimentation—you can deploy or update sidecars independently.

Cons:

  • Adds complexity to deployment and orchestration.
  • Consumes additional resources (CPU, memory).
  • Requires careful design to avoid tight coupling between the sidecar and the main application.
  • Latency (You are adding an another hop).

Do we always need to use sidecars

No. Not at all.

a. When there is a latency between the parent application and sidecar, then Reconsider.

b. If your application is small, then reconsider.

c. When you are scaling differently or independently from the parent application, then Reconsider.

Some other examples

1. Adding HTTPS to a Legacy Application

Consider a legacy web service which services requests over unencrypted HTTP. We have a requirement to enhance the same legacy system to service requests with HTTPS in future.

The legacy app is configured to serve request exclusively on localhost, which means that only services that share the local network with the server able to access legacy application. In addition to the main container (legacy app) we can add Nginx Sidecar container which runs in the same network namespace as the main container so that it can access the service running on localhost.

2. For Logging (Image from ByteByteGo)

Sidecars are not just technical solutions; they embody the principle of collaboration and specialization. By dividing responsibilities, they empower the main application to shine while ensuring auxiliary tasks are handled efficiently. Next time you hear about sidecars, you’ll know they’re more than just cool attachments for motorcycle they’re an essential part of scalable, maintainable software systems.

Also, do you feel its closely related to Adapter and Ambassador Pattern ? I Do.

References:

  1. Hussein Nasser – https://www.youtube.com/watch?v=zcJWvhzkPsw&pp=ygUHc2lkZWNhcg%3D%3D
  2. Sudo Code – https://www.youtube.com/watch?v=QU5WcwuFpZU&pp=ygUPc2lkZWNhciBwYXR0ZXJu
  3. Software Dude – https://www.youtube.com/watch?v=poPUzN33Oug&pp=ygUPc2lkZWNhciBwYXR0ZXJu
  4. https://medium.com/nerd-for-tech/microservice-design-pattern-sidecar-sidekick-pattern-dbcea9bed783
  5. https://dzone.com/articles/sidecar-design-pattern-in-your-microservices-ecosy-1

❌