Monday, March 31, 2025

How is the Weather today - An MCP Example

Many blogs and YouTube channels are currently emphasizing the relevance of Antrophic‘s Model Context Protocol MCP. They do this for a reason. MCP is the first attempt of an open standard model that connects LLM applications with data sources or services in a standardized way. Unfortunately, most explanations of MCP are either too basic or too difficult, and do not help grasp the idea behind MCP.  In this article you‘ll mostly find a code example for weather requests from a user prompt. Play with it, change it, extend it, use it as a template for your project.


MCP introduces various roles for software components. There are LLMs on the client side which are hosted by inference tools like Ollama, HuggingFace or llama.cpp.  MCP clients call remote services via the MCP Protocol. As a common prerequisite, the LLM or the Host should support tool calling. The tool respectively method implements the interaction between the MCP Client and MCP Server using the MCP Protocol. It is called whenever the LLM recognizes a location in the user prompt such as „How is the weather in San Francisco today?


Below is an example that implements an MCP‑conformant weather service using real REST calls between a client and a server. In this example the server exposes an MCP endpoint that expects a JSON request with the following structure:


```json

{

  "mcp_version": "1.0",

  "service": "weather",

  "payload": {

    "prompt": "What is the weather in Paris?"

  }

}

```


The server uses a local language model (via Hugging Face’s NER pipeline) to extract a location entity (e.g. a geopolitical entity) from the prompt and then “tool calls” an external real weather provider (wttr.in) to retrieve current weather conditions. If the request is successful, the server responds with an MCP‑compliant JSON payload; for example:


```json

{

  "mcp_version": "1.0",

  "status": "ok",

  "result": {

    "location": "Paris",

    "weather": "Sunny, 25°C"

  },

  "debug": "Extracted location and retrieved weather data successfully."

}

```


The client, which might be hosted by Ollama in a real deployment, collects a prompt from the user, assembles an MCP‑compliant request, posts it via REST to the server, and prints the JSON result.


Below is the full source code. Save it as, for example, `mcp_weather.py`. (Make sure you install the dependencies with `pip install flask requests transformers` prior to running.)


```python

import sys

import requests

from flask import Flask, request, jsonify

from transformers import pipeline


app = Flask(__name__)


# MCP configuration

MCP_VERSION = "1.0"

SERVICE_NAME = "weather"


# Create a local LLM using Hugging Face’s NER pipeline.

# This leverages a Named Entity Recognition model to extract location entities.

ner_pipeline = pipeline("ner", grouped_entities=True)


def extract_location(prompt):

    """

    Extracts a location from the prompt using NER.

    It scans for entity groups 'LOC' or 'GPE' and returns the first match.

    """

    entities = ner_pipeline(prompt)

    for ent in entities:

        if ent["entity_group"] in ["LOC", "GPE"]:

            # Clean the extracted word (sometimes artifacts occur).

            return ent["word"].strip()

    return None


def get_weather(location):

    """

    Retrieves current weather data using the wttr.in service.

    Returns a formatted string with the weather description and temperature (°C).

    """

    url = f"http://wttr.in/{location}?format=j1"

    try:

        response = requests.get(url, timeout=5)

        response.raise_for_status()

    except Exception as e:

        return f"Error fetching weather data for {location}: {e}"

    data = response.json()

    # Extract current condition: temperature and weather description.

    current = data.get("current_condition", [{}])[0]

    temp = current.get("temp_C", "Unknown")

    desc = current.get("weatherDesc", [{}])[0].get("value", "Unknown")

    return f"{desc}, {temp}°C"


@app.route("/mcp", methods=["POST"])

def mcp_endpoint():

    """

    MCP endpoint for weather queries.

    Expects an MCP-conformant JSON payload in the following form:

      {

         "mcp_version": "1.0",

         "service": "weather",

         "payload": { "prompt": "What is the weather in ..." }

      }

    Processes the request, extracting the location via the local LLM and then calling the weather tool.

    """

    data = request.get_json()

    if not data:

        return jsonify({

            "mcp_version": MCP_VERSION,

            "status": "error",

            "error": "Empty MCP request payload."

        }), 400


    if data.get("mcp_version") != MCP_VERSION:

        return jsonify({

            "mcp_version": MCP_VERSION,

            "status": "error",

            "error": "Unsupported MCP version."

        }), 400


    if data.get("service") != SERVICE_NAME:

        return jsonify({

            "mcp_version": MCP_VERSION,

            "status": "error",

            "error": f"Unsupported service: {data.get('service')}"

        }), 400


    payload = data.get("payload")

    if not payload or "prompt" not in payload:

        return jsonify({

            "mcp_version": MCP_VERSION,

            "status": "error",

            "error": "Missing required payload: 'prompt'."

        }), 400


    prompt = payload["prompt"]

    location = extract_location(prompt)

    if not location:

        return jsonify({

            "mcp_version": MCP_VERSION,

            "status": "error",

            "error": "No valid location identified in prompt."

        }), 400


    weather_result = get_weather(location)

    return jsonify({

        "mcp_version": MCP_VERSION,

        "status": "ok",

        "result": {

            "location": location,

            "weather": weather_result

        },

        "debug": "Extracted location and retrieved weather data successfully."

    })


def run_server():

    """

    Runs the MCP-compliant weather server on port 5000.

    """

    print("Starting MCP-compliant Weather Server on port 5000 with MCP version", MCP_VERSION)

    app.run(port=5000)


def run_client():

    """

    Runs the MCP client that collects a prompt from the user,

    assembles an MCP request, posts it to the server, and prints the response.

    """

    print("MCP-compliant Weather Client")

    prompt = input("Enter your weather query (e.g., 'What is the weather in London?'): ")

    mcp_request = {

        "mcp_version": MCP_VERSION,

        "service": SERVICE_NAME,

        "payload": {

            "prompt": prompt

        }

    }

    url = "http://localhost:5000/mcp"

    try:

        response = requests.post(url, json=mcp_request)

        response.raise_for_status()

    except Exception as e:

        print("Error connecting to MCP server:", e)

        return

    try:

        response_json = response.json()

        print("MCP Server Response:")

        print(response_json)

    except Exception as e:

        print("Error parsing response JSON:", e)

        print("Raw response:", response.text)


if __name__ == "__main__":

    if len(sys.argv) > 1 and sys.argv[1].lower() == "server":

        run_server()

    else:

        run_client()

```


---


How to Run the Example


1. Start the MCP Server:

   Open a terminal and run:

   

   ```bash

   python mcp_weather.py server

   ```


   This starts the Flask server on port 5000.


2. Run the MCP Client:

   Open a second terminal and run:

   

   ```bash

   python mcp_weather.py

   ```

   

   You’ll be prompted to enter a weather query. For example:

   

   ```

   What is the weather in New York?

   ```


3. View the Result:

   The client sends an MCP‑compliant JSON payload to the server. The server uses the local NER pipeline to extract the requested location, fetches the current weather from wttr.in, and returns an MCP response which the client prints.


This example demonstrates how to integrate a local LLM with real tool invocation while maintaining adherence to a REST‑based MCP protocol.

Comprehensive Software Design and Architecture Patterns Catalog

„Old“ pattern books like the Gang of Four patterns and the Pattern Oriented Software Architecture patterns were published 30 years ago. Since that time new technologies emerged and new experiences with software engineering were collected. There are a lot of unchartered territories for which new patterns have been identified, but not always documented. This article reworks some of the classical patterns. It adds new architecture and design patterns that may be interesting to document using one of  the pattern templates (for example, GoF or POSA style).

Hint: I wrote the original version of this article using format, but left some parts in their Markdown format. Some would define it as laziness. And they are right.


Refined Classical Patterns


Bounded Singleton

**Context:**  

Traditional singletons enforce a strict limit of one instance, but many systems benefit from a controlled number of instances while maintaining the core benefits of instance control.

**Problem:**  

The classic Singleton pattern is too restrictive for scenarios requiring limited concurrency, load balancing, or fault tolerance. However, unrestricted instantiation leads to resource contention and inconsistent state.

**Solution:**  

The Bounded Singleton pattern extends the traditional Singleton by allowing a configurable, fixed number of instances. It maintains a registry of active instances, manages their lifecycle, and provides instance selection strategies for clients.

**Participants:**

- **Instance Registry**: Tracks and limits the number of instances

- **Instance Factory**: Creates and initializes new instances when permitted

- **Selection Strategy**: Determines which instance to provide to clients

- **Instance Monitor**: Tracks health and usage of instances

**Consequences:**

- **Positive**: Enables controlled concurrency while preventing proliferation

- **Positive**: Supports load balancing across limited instances

- **Positive**: Facilitates resource pooling with upper bounds

- **Negative**: More complex implementation than traditional Singleton

- **Negative**: Potential bottlenecks at the registry level

**Known Uses:**

- Database connection pools with maximum connection limits

- Thread-safe object pools in high-performance systems

- License-constrained service managers


Event Sourcing+

**Context:**  

Long-lived systems that rely on event sourcing face challenges when domain models evolve over time. Traditional event sourcing captures state changes as immutable events but struggles with schema evolution.

**Problem:**  

As systems mature, the structure of events inevitably changes. New fields are added, semantics shift, and relationships between entities evolve. Without a mechanism to handle this evolution, systems become brittle and difficult to maintain, often requiring complex migration scripts or maintaining multiple versions of event handlers.

**Solution:**  

Event Sourcing+ extends traditional event sourcing by incorporating versioning and schema evolution directly into the event model. Events are stored with rich metadata including schema version, transformation rules, and semantic context. The system maintains transformation functions that can convert events between versions, allowing older events to be interpreted correctly by newer code.

**Participants:**

- **Event Store**: Persists events with version metadata

- **Schema Registry**: Maintains event schemas across versions

- **Event Transformer**: Contains rules to transform events between schema versions

- **Event Processor**: Applies appropriate transformations before processing events

**Consequences:**

- **Positive**: Systems can evolve without expensive migrations

- **Positive**: Historical data remains accessible and meaningful

- **Positive**: Reduces technical debt from schema drift

- **Negative**: Increased complexity in event processing pipeline

- **Negative**: Performance overhead from transformation operations

**Known Uses:**

- Financial systems with decade-long audit requirements

- Healthcare record systems that evolve with regulatory changes

- E-commerce platforms that maintain order history across major platform revisions


 Composite Microservice

**Context:**  

Microservice architectures often grow organically, leading to complex interaction patterns and dependencies that become difficult to manage and understand.

**Problem:**  

Direct point-to-point communication between many microservices creates a tangled web of dependencies. Client applications must understand complex orchestration logic, and changes to service interactions require updates across multiple services.

**Solution:**  

The Composite Microservice pattern creates a hierarchy where microservices can be atomic or composite. Composite services orchestrate other services while presenting a unified interface to clients. This creates a tree-like structure that simplifies complex operations while maintaining the microservice philosophy.

**Participants:**

- **Atomic Service**: Performs a single business capability

- **Composite Service**: Orchestrates multiple services while maintaining the same contract style

- **Service Registry**: Tracks available services and their capabilities

- **Client**: Interacts with either atomic or composite services without needing to know the difference

**Consequences:**

- **Positive**: Reduces client complexity by abstracting orchestration

- **Positive**: Enables incremental refactoring of service boundaries

- **Positive**: Improves system comprehensibility through hierarchical organization

- **Negative**: Can introduce additional network hops

- **Negative**: Risk of creating monolithic services if overused

**Known Uses:**

- E-commerce order processing pipelines

- Financial transaction processing systems

- Travel booking platforms that coordinate multiple reservation systems


Reactive Observer

**Context:**  

Modern distributed systems process high volumes of events across services with varying processing capabilities and reliability characteristics.

**Problem:**  

Traditional observer patterns can lead to message flooding, where fast producers overwhelm slow consumers. Additionally, when observers fail, the entire notification chain can be disrupted.

**Solution:**  

Reactive Observer extends the observer pattern with backpressure handling and failure isolation mechanisms. Observers signal their processing capacity to subjects, and the pattern incorporates circuit-breaking to isolate failing observers.

**Participants:**

- **Subject**: Maintains observer registry and respects backpressure signals

- **Observer**: Processes notifications and signals processing capacity

- **Backpressure Controller**: Manages flow control between subjects and observers

- **Circuit Breaker**: Monitors observer health and temporarily removes failing observers

**Consequences:**

- **Positive**: Prevents system overload during traffic spikes

- **Positive**: Improves system resilience through failure isolation

- **Positive**: Enables self-healing notification chains

- **Negative**: Increased complexity in notification logic

- **Negative**: Potential for reduced throughput due to conservative backpressure

**Known Uses:**

- Real-time analytics processing pipelines

- IoT sensor data collection systems

- Financial market data distribution networks


Cloud-Native Patterns

Containerization Pattern Family

Container Boundary

**Context:**  

Modern applications are increasingly deployed as containers, requiring clear principles for determining container boundaries and responsibilities.

**Problem:**  

Without clear guidelines for containerization, teams often create containers that are either too granular (increasing orchestration complexity) or too coarse (losing isolation benefits). Inappropriate container boundaries lead to deployment inefficiencies and operational challenges.

**Solution:**  

The Container Boundary pattern provides principles for defining optimal container boundaries based on deployment lifecycle, scaling characteristics, and resource profiles. It establishes guidelines for what should be included in a single container versus split across multiple containers.

**Participants:**

- **Primary Process**: The main application process that defines the container's purpose

- **Sidecar Processes**: Optional helper processes that support the primary process

- **Resource Definition**: Explicit declaration of container resource requirements

- **Lifecycle Hooks**: Entry points for container lifecycle management

**Consequences:**

- **Positive**: Optimized resource utilization through appropriate container sizing

- **Positive**: Simplified deployment and scaling operations

- **Positive**: Clear separation of concerns between containers

- **Negative**: Requires careful analysis of application characteristics

- **Negative**: May necessitate application refactoring to align with container boundaries

**Known Uses:**

- Microservice architectures deployed on Kubernetes

- Cloud-native application modernization projects

- DevOps pipeline containerization


Immutable Container

**Context:**  

Container-based deployments benefit from immutability to ensure consistency across environments and simplify operations.

**Problem:**  

Modifying running containers creates snowflake instances that drift from their original configuration, leading to environment inconsistencies, troubleshooting difficulties, and deployment unpredictability.

**Solution:**  

The Immutable Container pattern enforces that containers never change after deployment. Configuration changes, updates, or fixes require building new container images and redeploying. Runtime state is externalized to dedicated stateful services.

**Participants:**

- **Container Image**: Immutable blueprint defining the container

- **Configuration Injection**: External mechanism for providing configuration

- **State Store**: External system for maintaining persistent state

- **Deployment Orchestrator**: System that replaces containers rather than modifying them

**Consequences:**

- **Positive**: Consistent behavior across all environments

- **Positive**: Simplified rollback through image versioning

- **Positive**: Improved security through reduced attack surface

- **Negative**: Requires robust CI/CD for frequent rebuilds

- **Negative**: Necessitates external state management

**Known Uses:**

- Production Kubernetes deployments

- Serverless container platforms

- Highly regulated environments requiring deployment validation


Kubernetes Operator

**Context:**  

Complex applications on Kubernetes require domain-specific knowledge for proper deployment, scaling, and management that goes beyond generic orchestration.

**Problem:**  

Standard Kubernetes resources lack domain-specific knowledge about application lifecycle, scaling patterns, and recovery procedures, leading to manual operational overhead and inconsistent management.

**Solution:**  

The Kubernetes Operator pattern extends Kubernetes with custom controllers that encode domain-specific operational knowledge. Operators watch for custom resource changes and execute complex workflows to achieve the desired state, automating domain-specific operations.

**Participants:**

- **Custom Resource Definition**: Extends Kubernetes API with application-specific resources

- **Controller**: Watches custom resources and executes reconciliation logic

- **Reconciliation Loop**: Continuously works to achieve and maintain desired state

- **Status Reporter**: Updates resource status to reflect current state

**Consequences:**

- **Positive**: Automates complex application-specific operations

- **Positive**: Encapsulates operational expertise in code

- **Positive**: Enables self-healing at the application level

- **Negative**: Requires significant development investment

- **Negative**: Increases complexity of the Kubernetes cluster

**Known Uses:**

- Database deployments on Kubernetes (e.g., PostgreSQL, MongoDB)

- Message broker management (e.g., Kafka, RabbitMQ)

- Complex stateful applications with specific scaling requirements


Sidecar Configuration

**Context:**  

Modern cloud applications require dynamic configuration management that can adapt to changing environments without application restarts.

**Problem:**  

Embedding configuration management directly into applications creates tight coupling between business logic and infrastructure concerns. This makes applications less portable and complicates configuration updates.

**Solution:**  

The Sidecar Configuration pattern externalizes configuration management to a dedicated sidecar container or process. The main application remains configuration-agnostic, interacting with a simple local API to retrieve settings. The sidecar handles dynamic updates, validation, and distribution.

**Participants:**

- **Main Application**: Focuses on business logic, retrieves configuration through local API

- **Configuration Sidecar**: Manages configuration lifecycle, including updates and validation

- **Configuration Source**: External system providing configuration values (e.g., etcd, Consul)

- **Configuration API**: Local interface between main application and sidecar

**Consequences:**

- **Positive**: Separation of concerns between business logic and configuration management

- **Positive**: Enables zero-downtime configuration updates

- **Positive**: Simplifies application code by externalizing configuration complexity

- **Negative**: Additional deployment complexity

- **Negative**: Potential single point of failure if not properly designed

**Known Uses:**

- Kubernetes-based applications using ConfigMaps

- Service mesh implementations like Istio

- Cloud-native databases with dynamic configuration requirements


Boundary Polyglot

**Context:**  

Modern systems often benefit from using different programming languages for different components, leveraging language-specific strengths.

**Problem:**  

Mixing languages in a system introduces complexity in communication, deployment, and maintenance. Without clear boundaries, polyglot systems can become chaotic and difficult to evolve.

**Solution:**  

The Boundary Polyglot pattern formalizes how to design language transition points at domain boundaries with well-defined contracts. It specifies serialization formats, error handling approaches, and deployment strategies that minimize translation overhead.

**Participants:**

- **Domain Boundary**: Well-defined interface where language transition occurs

- **Contract Definition**: Language-neutral specification of the interface

- **Serialization Layer**: Handles data translation between language-specific formats

- **Error Mapping**: Translates exceptions and errors between language paradigms

**Consequences:**

- **Positive**: Enables using the best language for each component

- **Positive**: Creates clear boundaries that improve system modularity

- **Positive**: Facilitates incremental language migration

- **Negative**: Increased complexity in build and deployment pipelines

- **Negative**: Potential performance overhead from serialization/deserialization

**Known Uses:**

- Systems with performance-critical components in languages like Rust alongside business logic in higher-level languages

- Data processing systems using Python for analytics with Java for infrastructure

- Web applications with JavaScript frontends and statically-typed backend languages


Resilient State Transfer

**Context:**  

Distributed systems must maintain data consistency across service boundaries despite network failures, partial outages, and varying load conditions.

**Problem:**  

Traditional request-response patterns are vulnerable to network partitions and service failures, leading to inconsistent state across services or blocked operations.

**Solution:**  

Resilient State Transfer implements a combination of optimistic updates, conflict resolution, and eventual consistency guarantees. Services maintain local state that can diverge temporarily but will eventually converge through background reconciliation processes.

**Participants:**

- **State Owner**: Service that has primary authority over a piece of state

- **State Consumer**: Service that maintains a local copy of state

- **Change Log**: Append-only record of state modifications

- **Reconciliation Engine**: Background process that resolves conflicts and ensures consistency

**Consequences:**

- **Positive**: Operations can continue during partial system outages

- **Positive**: Improved responsiveness by avoiding synchronous dependencies

- **Positive**: Natural audit trail through the change log

- **Negative**: Increased complexity in conflict resolution

- **Negative**: Temporary inconsistency between services

**Known Uses:**

- Multi-region database systems

- Collaborative editing applications

- Inventory management across distributed warehouses


AI and LLM Application Patterns


Prompt Chain Responsibility

**Context:**  

Complex AI tasks often require multiple steps of reasoning or processing that exceed the capabilities of a single prompt-response interaction.

**Problem:**  

Attempting to solve complex problems with a single prompt often leads to incomplete reasoning, hallucinations, or responses that miss critical aspects of the problem.

**Solution:**  

Prompt Chain Responsibility organizes LLM interactions as a chain of specialized prompts, each handling a specific aspect of a complex task. Each prompt in the chain has clear responsibilities and passes its output to the next prompt, enabling complex reasoning through decomposition.

**Participants:**

- **Chain Coordinator**: Manages the flow between prompts and aggregates results

- **Specialized Prompts**: Individual prompts with focused responsibilities

- **Context Manager**: Ensures relevant information is passed between chain links

- **Output Validator**: Verifies each step meets quality criteria before proceeding

**Consequences:**

- **Positive**: Enables complex multi-step reasoning

- **Positive**: Improves reliability through focused, verifiable steps

- **Positive**: Creates traceable reasoning paths

- **Negative**: Increased token usage and API costs

- **Negative**: Higher latency due to multiple LLM calls

**Known Uses:**

- Complex legal document analysis

- Multi-step mathematical problem solving

- Research synthesis applications


Context Window Management

**Context:**  

LLMs have finite context windows that limit the amount of information they can process in a single interaction, creating challenges for applications dealing with large documents or extended conversations.

**Problem:**  

When information exceeds the context window, LLMs lose access to potentially critical details, leading to incomplete or incorrect responses. Simply truncating content often removes important context.

**Solution:**  

The Context Window Management pattern defines strategies for information prioritization, summarization, and retrieval. It implements techniques like sliding windows, hierarchical summarization, and semantic chunking to maintain coherence across large datasets or conversations.

**Participants:**

- **Content Chunker**: Divides large content into semantically meaningful segments

- **Priority Manager**: Determines which chunks should remain in context

- **Summary Generator**: Creates condensed representations of out-of-window content

- **Context Assembler**: Constructs the optimal context window for each interaction

**Consequences:**

- **Positive**: Enables working with documents larger than the context window

- **Positive**: Maintains conversation coherence over extended interactions

- **Positive**: Optimizes token usage by prioritizing relevant content

- **Negative**: Potential information loss through summarization

- **Negative**: Computational overhead from content management

**Known Uses:**

- Document analysis systems processing large legal or technical documents

- Long-running customer support chatbots

- Research assistants working with multiple academic papers


Hallucination Guard

**Context:**  

LLMs can generate plausible-sounding but factually incorrect information, creating risks for applications where accuracy is critical.

**Problem:**  

Hallucinations undermine trust in AI systems and can lead to serious consequences in domains like healthcare, finance, or legal applications. Traditional prompt engineering alone is insufficient to prevent hallucinations.

**Solution:**  

The Hallucination Guard pattern implements verification layers around LLM outputs. It combines techniques like grounding in trusted sources, fact-checking, confidence scoring, and explicit uncertainty flagging to minimize hallucinations.

**Participants:**

- **Source Grounding Engine**: Links LLM statements to trusted reference material

- **Fact Checker**: Verifies factual claims against reliable sources

- **Confidence Analyzer**: Assesses LLM certainty and flags potential hallucinations

- **Uncertainty Communicator**: Explicitly represents uncertainty in responses to users

**Consequences:**

- **Positive**: Significantly reduced hallucination rate

- **Positive**: Appropriate expression of uncertainty when information is limited

- **Positive**: Increased user trust through verifiable responses

- **Negative**: Higher computational cost and latency

- **Negative**: Potential for overly cautious responses

**Known Uses:**

- Medical diagnosis assistance systems

- Financial advisory applications

- Educational tutoring platforms


Prompt Template Strategy

**Context:**  

Prompt engineering is both art and science, with different prompt structures yielding significantly different results for the same underlying task.

**Problem:**  

Static prompts cannot adapt to different user needs, content types, or evolving LLM capabilities. Finding the optimal prompt often requires experimentation that's difficult to systematize.

**Solution:**  

The Prompt Template Strategy pattern applies the Strategy pattern to prompt engineering. It defines a family of interchangeable prompt templates that can be selected dynamically based on context, user needs, or performance metrics.

**Participants:**

- **Template Registry**: Maintains available prompt templates for each task type

- **Template Selector**: Chooses the appropriate template based on context

- **Performance Monitor**: Tracks effectiveness of different templates

- **Template Evolver**: Generates and tests new template variations

**Consequences:**

- **Positive**: Enables continuous prompt optimization

- **Positive**: Adapts to different user needs and content types

- **Positive**: Facilitates systematic A/B testing of prompts

- **Negative**: Increased system complexity

- **Negative**: Potential inconsistency in responses across different templates

**Known Uses:**

- Enterprise chatbots serving diverse user populations

- Content generation platforms with varying stylistic requirements

- Educational systems adapting to different learning styles


RAG Composition

**Context:**  

Retrieval-Augmented Generation (RAG) systems combine information retrieval with generative AI to ground responses in specific knowledge bases.

**Problem:**  

Building effective RAG systems requires integrating multiple components (retrievers, rankers, generators) that each have different implementation options and performance characteristics.

**Solution:**  

The RAG Composition pattern formalizes how to compose RAG systems from modular components. It defines interfaces between retrievers, rankers, and generators, allowing for mix-and-match capabilities while maintaining system coherence.

**Participants:**

- **Knowledge Store**: Contains the documents or information to be retrieved

- **Query Processor**: Transforms user queries into effective retrieval queries

- **Retriever**: Finds relevant documents or passages from the knowledge store

- **Ranker**: Prioritizes retrieved information by relevance

- **Context Assembler**: Constructs the prompt with retrieved information

- **Generator**: Produces the final response based on the assembled context

**Consequences:**

- **Positive**: Enables experimentation with different component combinations

- **Positive**: Facilitates incremental improvement of individual components

- **Positive**: Creates clear separation of concerns

- **Negative**: Potential integration challenges between components

- **Negative**: Performance interdependencies between components

**Known Uses:**

- Enterprise knowledge base assistants

- Research tools integrating multiple data sources

- Customer support systems with diverse product documentation


Semantic Caching

**Context:**  

LLM applications often make repeated similar queries that don't require fresh computation each time, creating opportunities for performance optimization.

**Problem:**  

Traditional exact-match caching is ineffective for LLM applications because queries are rarely identical even when seeking the same information. This leads to unnecessary API calls, increased costs, and higher latency.

**Solution:**  

Semantic Caching stores responses along with semantic representations of queries. New queries are compared semantically to cached entries, and sufficiently similar matches return cached results, potentially with minor adaptations.

**Participants:**

- **Query Embedder**: Converts queries into semantic vector representations

- **Similarity Calculator**: Determines semantic proximity between queries

- **Cache Store**: Maintains query-response pairs with semantic metadata

- **Response Adapter**: Adjusts cached responses to match new query nuances

**Consequences:**

- **Positive**: Reduced API costs through fewer LLM calls

- **Positive**: Lower latency for semantically repeated queries

- **Positive**: Improved consistency across similar questions

- **Negative**: Potential for returning slightly misaligned responses

- **Negative**: Memory and computational overhead for semantic matching

**Known Uses:**

- Customer support chatbots handling common questions

- Educational platforms with recurring concept explanations

- Documentation assistants answering standard queries


Multimodal Orchestration

**Context:**  

Modern AI applications increasingly work across multiple modalities (text, images, audio, video) requiring coordination between specialized AI models.

**Problem:**  

Different modalities require different processing approaches, and information must be integrated coherently across these modalities to provide unified experiences.

**Solution:**  

The Multimodal Orchestration pattern defines how specialized AI models for different modalities communicate and coordinate. It establishes protocols for cross-modal information exchange, synchronization, and integrated reasoning.

**Participants:**

- **Modal Specialists**: AI models specialized for specific modalities

- **Cross-Modal Translator**: Converts information between modality-specific representations

- **Orchestration Controller**: Coordinates processing across modalities

- **Integration Engine**: Combines insights from different modalities into coherent outputs

**Consequences:**

- **Positive**: Enables rich multi-sensory AI experiences

- **Positive**: Leverages specialized models for each modality

- **Positive**: Creates more natural human-AI interactions

- **Negative**: Increased system complexity

- **Negative**: Challenges in resolving contradictions between modalities

**Known Uses:**

- Virtual assistants processing voice, text, and visual inputs

- Content moderation systems analyzing text and images

- Accessibility tools translating between modalities

Conclusion

This comprehensive pattern catalog represents the evolution of software design thinking to address modern challenges across traditional, cloud-native, and AI domains. While building on the solid foundation established by GoF and POSA, these patterns extend into new territories shaped by distributed systems, cloud computing, containerization, and artificial intelligence. 

The inclusion of the Bounded Singleton pattern addresses limitations in the classic Singleton while maintaining controlled instantiation, while the Containerization pattern family provides structured approaches to container-based deployment and orchestration challenges in modern cloud environments.

By formalizing these patterns, developers can leverage proven solutions to common problems, accelerating development while improving system quality and maintainability. As technology continues to evolve, this pattern catalog will expand to incorporate new approaches that address emerging challenges in software design and architecture.

Beyond Transformers: Revolutionizing LLMs with New Neural Architectures

The transformer architecture has dominated AI development since its introduction in 2017, powering virtually all modern large language models (LLMs). However, despite their remarkable capabilities, transformers face significant limitations—particularly with handling long contexts and efficiently managing memory. Recent breakthroughs in neural network design suggest we may be on the cusp of a post-transformer era, with several promising architectures emerging as potential successors.


The Challenge: Context Length and Memory Limitations

Current LLMs struggle with two fundamental issues:

1. Quadratic scaling complexity: Transformer attention mechanisms scale quadratically with input length, making processing very long contexts computationally prohibitive.

2. Memory inefficiency: Models must store the entire context in memory, limiting practical context windows even on high-end hardware.

Everyone of us has made this experience of LLMs forgetting information from earlier in a conversation or document analysis.

Emerging Alternative Architectures

Three groundbreaking architectures have emerged as potential transformer replacements, each taking a different approach to addressing these limitations:

1. State Space Models (SSMs) and Mamba

State Space Models represent a fundamentally different approach to sequence modeling that combines the best aspects of recurrent neural networks and transformers.

According to research from [Maarten Grootendorst](https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-mamba-and-state), "A State Space Model (SSM), like the Transformer and RNN, processes sequences of information, like text but also signals." The key innovation is how SSMs handle sequential data:

- They use a continuous-time representation that can be efficiently discretized

- They offer both recurrent (for inference) and convolutional (for training) representations

- They scale linearly with sequence length rather than quadratically

Mamba, developed by researchers at Carnegie Mellon and Princeton, represents the most advanced implementation of SSMs. As [DeepLearning.AI](https://www.deeplearning.ai/the-batch/mamba-a-new-approach-that-may-outperform-transformers/) reports, "A relatively small Mamba produced tokens five times faster and achieved better accuracy than a vanilla transformer."

The architecture excels at "information-dense data such as language modeling, where previous subquadratic models fall short of Transformers," according to the [official Mamba repository](https://github.com/state-spaces/mamba).

Google's Titans Architecture

Google Research recently introduced Titans, a neural architecture that fundamentally rethinks how AI models store and access memory. According to [Google's research paper](https://arxiv.org/abs/2501.00663), Titans introduces "a new neural long-term memory module that learns to memorize historical context and helps attention to attend to the current context while utilizing long past information."

The architecture implements a three-tiered memory system:

- Short-term memory: Traditional attention for immediate context

- Long-term memory: Neural memory module for historical information

- Persistent memory: Task-specific knowledge in learnable parameters

This approach allows Titans to effectively process sequences exceeding 2 million tokens in length, far beyond what current transformers can handle efficiently. As [AI-Stack.ai](https://ai-stack.ai/en/google-titans) explains, "Titans implements a novel three-tiered memory system that mirrors human cognitive processes."

3. Sakana AI's Transformer-Squared

Sakana AI, a Tokyo-based startup, has developed Transformer-Squared, a self-adaptive framework that enables LLMs to dynamically adjust their behavior during inference.

According to [Sakana AI's official description](https://sakana.ai/transformer-squared/), "Transformer-Squared employs a two-pass mechanism: first, a dispatch system identifies the task properties, and then task-specific 'expert' vectors, trained using reinforcement learning, are dynamically mixed to obtain targeted behavior for the incoming prompt."

The architecture focuses on selective adaptation rather than complete architectural redesign. As [Jailbreak AI](https://jailbreakai.substack.com/p/transformers2-a-revolution-in-self) explains, it "selectively adjusts only the singular components of their weight matrices" using a technique called Singular Value Fine-tuning (SVF).

This approach allows models to adapt to new tasks without extensive retraining, potentially addressing the static nature of traditional transformer models.


Comparative Advantages

Each architecture offers distinct advantages:

1. Mamba/SSMs: Linear scaling with sequence length, efficient inference, and potentially unlimited context windows.

2. Titans: Superior memory management through its three-tiered system, excelling at "needle-in-haystack" tasks requiring retrieval from very long contexts.

3. Transformer-Squared: Dynamic adaptation to different tasks without retraining, potentially solving the problem of models being "jacks of all trades, masters of none."


The Future of Neural Architectures

These innovations suggest we're entering a new era of AI architecture design where:

1. Hybrid approaches may combine the strengths of different architectures

2. Task-specific adaptation becomes more dynamic and efficient

3. Memory management becomes a central focus of architecture design

4. Scaling laws may be redefined beyond simply increasing parameter counts

As [Decrypt](https://decrypt.co/301639/beyond-transformers-ai-architecture-revolution) notes, "If this new generation of neural networks gains traction, then future models won't have to rely on huge scales to achieve greater versatility and performance."


Conclusion

While transformers will likely remain important for years to come, these emerging architectures represent significant steps toward more efficient, adaptable, and capable AI systems. By addressing the fundamental limitations of transformers—particularly around context length and memory management—these new approaches may enable the next generation of AI models to handle increasingly complex tasks with greater efficiency.


The era of AI companies bragging about model size may soon give way to a focus on architectural innovation, with these new approaches potentially delivering superior performance without the computational demands of ever-larger transformer models.

Saturday, September 28, 2024

Hitchhiker‘s Guide to Vogon Culture

The Hitchhiker's Guide to the Galaxy - Vogons: A Comprehensive Overview

Introduction

The Hitchhiker's Guide to the Galaxy famously notes that if there is one species you should never, under any circumstances, attempt to reason with, it’s the Vogons. Their love for bureaucracy, their complete lack of empathy, and their talent for creating the third worst poetry in the universe have made them a cosmic byword for misery and paperwork. The Guide goes on to describe the Vogons as "slug-like creatures" whose devotion to form-filling, stamping, and the regulation of intergalactic travel is rivaled only by their enthusiasm for torturing other species through mind-numbing bureaucracy.

This chapter offers a comprehensive guide to all things Vogon, including their language, legal systems, court scenarios, reproduction, and, of course, their utterly joyless social life. Read on at your own risk.

Chapter 1: The Vogon Language

Vogon language, much like the creatures themselves, is a harsh, guttural, and needlessly complex form of communication designed to cause maximum discomfort to the listener. The Vogon language is characterized by awkward consonant clusters, over-enunciated vowels, and a grammatical structure so convoluted that entire civilizations have been known to collapse after merely attempting to translate one Vogon court document.

Phonetics and Phonology

Vogon speech is designed to be as unappealing as possible, with a reliance on guttural consonants and nasal vowels. Words typically follow a C-C-V-C pattern (Consonant-Consonant-Vowel-Consonant), with consonants clustering at the beginning and end of words.

Example: Splornk (spaceship).

Stress patterns are equally jarring, with stress usually placed on the first syllable, though formal Vogon speech tends to randomly stress syllables to complicate things further. This makes the language sound as though the speaker is both complaining and issuing a bureaucratic directive at the same time.

Grammar

The Vogon language utilizes a highly convoluted grammar system that ensures even the simplest statement is buried under layers of nested clauses, bureaucratic redundancies, and arbitrary pronoun shifts.

  • Sentence Structure: VSO (Verb-Subject-Object) is the default word order. However, to confuse others (and themselves), Vogons often switch to SOV or even scrambled orders during formal exchanges.
  • Example: Nzzif kaak splornk. Translation: "I destroy the spaceship."
  • Verb Conjugation: Vogon verbs are conjugated for tense, mood, voice, and emotional state. In particular, verbs take on additional suffixes depending on how annoyed the speaker is, a feature that is used frequently.
  • Annoyance Level Example: Nzzifrk (I slightly destroy) → Nzzifgrrrrk (I completely destroy, out of utter frustration).
  • Pronouns: Vogon pronouns are unnecessarily complex, changing based on mood, hierarchy, and disdain for the listener.
  • Examples: Kaak (I, formal), Zagg (you, informal but polite), Thnggrz (they, bureaucratic third-party).

Advanced Vogon Poetry

Vogon poetry is considered the third worst in the universe, and for good reason. Full of meaningless metaphors, awkward sounds, and forced rhyme schemes, Vogon poetry is a tool of torture. Here’s an example:

"Fnorg tzzzl brrzl splornk,
Grzzrk Urrghk tssnif plrnkk.
Fnarrt zzgrk blorrrkfl tzrk,
Thrurg splurtz zzrrrk thrrknk."

Translation: "Life and paperwork is meaningless,
The love of form is all but endless.
Rot and decay fill my soul,
The smell of green is a terrible toll."

Chapter 2: Vogon Bureaucracy

Vogons have elevated bureaucracy to an art form. If you ever find yourself dealing with a Vogon, it is essential to understand that their minds operate on a single principle: the more forms, the better. There is nothing the Vogons enjoy more than filling out forms in triplicate and forcing others to do the same.

Legal Texts

Vogon legal documents are designed to confuse, confound, and trap the reader in an endless cycle of paperwork. Filled with multiple nested clauses, contradictory requirements, and circular references, a single Vogon legal document can take years to decode.

Example of a Legal Document:

Title: Form 78-L: Authorization for Minor Interplanetary Travel (Revision 56-J)

Section 1: General Requirements
"Splurnkfnrgrr splurtzn thzzrkfnr form 92-B, to be submitted in quadruplicate along with supporting documentation, referencing Appendix 12-F and Clause 43-E."

Translation: "The applicant must submit form 92-B, along with multiple supporting forms, unless an additional form overrides the request, in which case further clarification will be required."

Court Scenarios

Vogon courtrooms are places of immense tedium, where legal cases are decided based not on evidence or logic but on how many forms the litigants have filed. The judge, typically a Supreme Bureaucrat, evaluates not the arguments, but the accuracy of the paperwork.

Example Dialogue in a Vogon Courtroom:

Judge (Supreme Bureaucrat Fnarrpftjrl):
"Tssrkfnll splornkfnrgr splurtzzkr tssrkzn form 92-C, in compliance with subsections 43-F and 99-Q, I declare that the claimant has failed to submit the proper forms for cross-examination. Case dismissed!"

Claimant (Vogon A):
"Fnzzgrptzn kaak splurtfnrll form 42-B, thzzrkzn brrzlgn form fnzzkrk!"
Translation: "I have already filed form 42-B, with supporting documentation."

Chapter 3: Vogon Reproduction

One might hope that a species so dispassionate and bureaucratic would have an equally sterile approach to reproduction, and they would be right. For Vogons, reproduction is not an act of love or intimacy, but a tedious and necessary bureaucratic process, regulated by government forms and monitored by officials.

The Reproductive Process

  1. Filing for Reproduction Approval: Vogons must submit Form 54-R: Reproduction Request to the Bureau of Species Continuation. This form must be submitted in quadruplicate, along with supporting documentation such as the Individual Fitness Report and the Reproduction Quota Compliance Form.
  2. Official Selection of Mates: Mating is not a personal choice. The Bureau of Genetic Appropriateness selects mates based on genetic fitness and bureaucratic rank. Once paired, the couple receives an Official Reproduction License (Form 78-B).
  3. Clinical Reproduction: Vogon reproduction likely takes place in designated reproduction centers, where the process is monitored to ensure all steps are followed correctly. Physical contact is minimal, and reproduction may even be artificial, with in vitro fertilization preferred for its efficiency.
  4. Post-Reproduction Paperwork: After reproduction, the couple is required to submit Form 43-R: Reproduction Completion, outlining the details of the procedure. This is followed by Growth and Development Reports and Education Authorization Forms for the offspring.

Chapter 4: Vogon Social Life

If you're picturing a Vogon social gathering as a lively event filled with conversation, laughter, and joy, then you clearly have no understanding of Vogons. Social interactions among Vogons are cold, formal, and revolve around their one true passion: bureaucracy.

Social Hierarchy

In Vogon society, status is determined by one's position in the bureaucratic system. The higher a Vogon's rank, the more respect they command. The most powerful Vogons are the Supreme Bureaucrats, while the lowest-ranking are Junior Clerks tasked with filing endless paperwork.

Social Events

Vogons do not host parties, as those would imply enjoyment. Instead, they participate in form-signing ceremonies and public readings of bureaucratic documents.

  • Form-Signing Ceremonies: When a major form (such as an interstellar travel permit) is signed, Vogons hold a formal gala where the form is signed in triplicate, reviewed, stamped, and filed.
  • Public Readings: High-ranking bureaucrats read aloud especially complex forms, much to the admiration of lower-ranking Vogons, who attempt to decipher the labyrinthine clauses.

Romantic Life

In typical Vogon fashion, romantic interactions are devoid of affection. Romantic conversations, if they can be called that, often involve sarcastic compliments about bureaucratic efficiency.

Example of Romantic Dialogue:

Vogon A (Krzzrk A):
"Grzzxlzzx urrghkrk fnzzgrpt kaak splurtfnll zzfnrrkn."
Translation: "Your bureaucratic skills are unmatched, and your form-filing technique is impeccable."

Chapter 5: Vogon Punishments

For Vogons, the most effective punishments are bureaucratic. Rather than physical penalties, guilty parties are subjected to form overloads or bureaucratic imprisonment.

Form Overload

The guilty party must submit hundreds of forms in a limited time, each with its own supporting documentation. Any errors result in the entire process restarting.

Bureaucratic Imprisonment

The most severe punishment. The convicted Vogon is confined to a room filled with forms to complete, with new forms arriving faster than they can be filed.

Conclusion

The Vogon way of life is a model of how not to run a civilization. Their language, legal system, reproduction, and social interactions are all dominated by a fanatical adherence to rules and regulations. Vogons have perfected the art of making life as joyless and cumbersome as possible, and they take great pride in that accomplishment.

As the Guide wisely advises, if you ever encounter a Vogon, there’s really only one thing you can do: run. If they don’t get you with their bureaucracy, they’ll surely get you with their poetry.

Wednesday, September 18, 2024

Technical Debt Records (TDRs) and the Tool to Create Them

Introduction 

In today's fast-paced software development landscape, teams face the challenge of continuously delivering new features while maintaining code quality. This often leads to compromises known as **Technical Debt**. To systematically document and manage this debt, **Technical Debt Records (TDRs)** have emerged as a vital tool. This article explores the significance of TDRs, how they benefit developers, architects, and testers, and introduces a tool that simplifies the creation of TDRs.

What are Technical Debt Records (TDRs)?

A **Technical Debt Record (TDR)** is a structured document that captures details about technical debt within a software project. Technical debt arises when short-term solutions are chosen for immediate gains, leading to increased maintenance costs, reduced performance, or other long-term disadvantages. TDRs provide a clear overview of existing technical debt, its impacts, and the measures needed to address it.

Motivation for TDRs

Unmanaged technical debt can accumulate over time, resulting in significant negative consequences:

- **Code Quality:** Increased maintenance efforts and declining code quality.
- **Scalability:** Challenges in scaling and adapting the software.
- **Performance:** Potential performance degradation due to suboptimal implementations.
- **Risk Management:** Elevated risks of system failures or security vulnerabilities.

By systematically documenting technical debt through TDRs, teams can proactively identify, prioritize, and address these issues before they become unmanageable.

Benefits of TDRs for Developers, Architects, and Testers

For Developers:

- **Transparency:** Clear documentation of existing technical debt enhances understanding of the codebase.
- **Prioritization:** Helps focus on critical areas that require immediate attention.
- **Reusability:** Awareness of known issues prevents duplicate efforts in troubleshooting and fixing problems.

For Architects:

- **Strategic Planning:** Assists in planning refactoring efforts and architectural improvements.
- **Risk Assessment:** Evaluates the impact of technical debt on the overall system architecture.
- **Decision-Making:** Provides data-driven insights for making informed decisions about system evolution.

For Testers:

- **Focused Testing:** Knowledge of problematic areas allows for more targeted and effective testing strategies.
- **Enhanced Test Coverage:** Ensures that areas affected by technical debt receive adequate testing attention.
- **Quality Assurance:** Guarantees that resolved debts contribute to overall software quality improvements.

The TDR Template and Its Fields

A well-structured TDR template is crucial for effective documentation of technical debt. The tool we present generates TDRs with the following fields:

1. **Title:** A concise name for the technical debt.
2. **Author:** The individual who identified or is documenting the debt.
3. **Version:** The version of the project or component where the debt exists.
4. **Date:** The date when the debt was identified or recorded.
5. **State:** The current workflow stage of the technical debt (e.g., Identified, Analyzed, Approved, In Progress, Resolved, Closed, Rejected).
6. **Relations:** Links to other related TDRs to establish connections between different debt items.
7. **Summary:** A brief overview explaining the nature and significance of the technical debt.
8. **Context:** Detailed background information, including why the debt was incurred (e.g., time constraints, outdated technologies).
9. **Impact:**
   - **Technical Impact:** How the debt affects system performance, scalability, maintainability, etc.
   - **Business Impact:** The repercussions on business operations, customer satisfaction, risk levels, etc.
10. **Symptoms:** Observable signs indicating the presence of technical debt (e.g., frequent bugs, slow performance).
11. **Severity:** The criticality level of the debt (Critical, High, Medium, Low).
12. **Potential Risks:** Possible adverse outcomes if the debt remains unaddressed (e.g., security vulnerabilities, increased costs).
13. **Proposed Solution:** Recommended actions or strategies to resolve the debt.
14. **Cost of Delay:** Consequences of postponing the resolution of the debt.
15. **Effort to Resolve:** Estimated resources, time, and effort required to address the debt.
16. **Dependencies:** Other tasks, components, or external factors that the resolution of the debt depends on.
17. **Additional Notes:** Any other relevant information or considerations related to the debt.

Rationale for the `State` Field

The `State` field reflects the workflow stages of handling technical debt. It helps track the progress of each debt item and ensures that no debts remain unattended. The defined states are:

- **Identified:** The technical debt has been recognized.
- **Analyzed:** The impact and effort required to address the debt have been assessed.
- **Approved:** The resolution of the technical debt has been approved.
- **In Progress:** Work to resolve the technical debt is underway.
- **Resolved:** The technical debt has been addressed.
- **Closed:** The technical debt record is closed.
- **Rejected:** The resolution of the technical debt has been rejected.

Adjusting Fields Based on State

When initially identifying a technical debt, some fields may remain empty and be filled out as the debt progresses through different states:

- **Initial Identification (`Identified`):**
  - **Filled:** Title, Author, Version, Date, State, Summary, Context.
  - **Empty:** Impact, Symptoms, Severity, Potential Risks, Proposed Solution, Cost of Delay, Effort to Resolve, Dependencies, Additional Notes.

- **Analysis Phase (`Analyzed`):**
  - **Filled:** All fields from `Identified` plus Impact, Symptoms, Severity, Potential Risks.

- **Approval Phase (`Approved`):**
  - **Filled:** All previous fields plus Proposed Solution, Cost of Delay.

- **Implementation Phase (`In Progress`):**
  - **Filled:** All previous fields plus Effort to Resolve, Dependencies.

- **Completion Phase (`Resolved` & `Closed`):**
  - **Filled:** All fields including Additional Notes.

This phased approach ensures that TDRs remain up-to-date and accurately reflect the current status of each technical debt item.

The Tool to Create TDRs

Our **TDR Generator** is a Go-based tool that automates the creation of Technical Debt Records in multiple formats. It supports **Markdown**, **Plain ASCII**, **PDF**, and **Excel**, facilitating integration into various development and documentation workflows.

Features of the TDR Generator

- **User-Friendly:** Interactive prompts guide users through filling out TDR fields.
- **Flexible:** Supports multiple output formats to suit different documentation needs.
- **Automatic Validation:** Ensures input completeness and correctness.
- **Version Control Integration:** Easily check TDRs into systems like Git or SVN.

Repository and Installation

The TDR Generator is available on GitHub. You can access the repository [here](https://github.com/yourusername/technical-debt-generator).

Installation Steps:

1. **Clone the Repository:**

   ```bash
   git clone https://github.com/yourusername/technical-debt-generator.git
   cd technical-debt-generator
   ```

2. **Initialize the Go Module:**

   ```bash
   go mod init technical_debt_generator
   ```

3. **Install Dependencies:**

   The program relies on two external libraries:
   
   - `gofpdf` for PDF generation.
   - `excelize` for Excel file creation.

   Install them using:

   ```bash
   go get github.com/phpdave11/gofpdf
   go get github.com/xuri/excelize/v2
   ```

4. **Save the Program:**

   Create a file named `generate-td.go` and paste the complete program code provided above into it.

Using the TDR Generator

The program can be executed via the command line with various options to customize the output.

Available Options:

- `-format`: Specifies the output format. Supported formats are:
  - `markdown` (default)
  - `ascii`
  - `pdf`
  - `excel`

  **Example:**

  ```bash
  ./generate_td -format pdf
  ```

- `-output`: (Optional) Specifies the output filename. If not provided, a default filename with the appropriate extension is generated based on the selected format.

  **Example:**

  ```bash
  ./generate_td -format markdown -output my_debt_record.md
  ```

- `-empty`: (Optional) If set, the program generates an empty TDR template with placeholders without prompting for input.

  **Example:**

  ```bash
  ./generate_td -format excel -empty
  ```

- `--help` or `-h`: Displays a help message with usage instructions.

  **Example:**

  ```bash
  ./generate_td --help
  ```
Interactive Prompts:

When generating a non-empty TDR, the program will interactively prompt you to enter values for each field, including the new `State` field.

**Sample Interaction:**

```bash
./generate_td -format markdown
```

```
Enter the Title of the Technical Debt: Outdated Authentication Library
Enter the Author of the Document: Jane Doe
Enter the Version (e.g., 1.0.0): 1.2.3
Enter the Date (YYYY-MM-DD) [Leave blank for today]: 

Select the State of the Technical Debt:
  1) Identified
  2) Analyzed
  3) Approved
  4) In Progress
  5) Resolved
  6) Closed
  7) Rejected
Enter the number corresponding to the state: 2

Enter related Technical Debt IDs (leave blank to finish):
 - Related TD ID: TD-101
 - Related TD ID: TD-202
 - Related TD ID: 

Enter Summary: The current authentication library is outdated and poses security risks.
Enter Context: Selected early to meet project deadlines, now incompatible with new security standards.
Enter Technical Impact: Incompatibility with the latest framework version.
Enter Business Impact: Increased risk of security breaches affecting customer trust.
Enter Symptoms: Frequent security audit failures and increased bug reports.
Enter Severity (Critical / High / Medium / Low): High
Enter Potential Risks: Data breaches, legal liabilities, and loss of customer trust.
Enter Proposed Solution: Replace the outdated library with a modern, well-supported alternative.
Enter Cost of Delay: Each month of delay increases security vulnerabilities and complicates future upgrades.
Enter Effort to Resolve: Approximately 6 weeks for two developers.
Enter Dependencies: Completion of the ongoing security audit.
Enter Additional Notes: Coordination with the operations team for seamless integration.

Technical Debt record has been saved to 'technical_debt_record.md'.
```

Output Files:

Depending on the selected format, the program generates the TDR in the specified format:

- **Markdown (`.md`):** Structured and readable documentation suitable for version control and collaborative editing.
- **Plain ASCII (`.txt`):** Simple text format for basic documentation needs.
- **PDF (`.pdf`):** Portable Document Format for sharing and printing.
- **Excel (`.xlsx`):** Spreadsheet format for data analysis and integration with other tools.

Best Practices

Version Control Integration

**Technical Debt Records (TDRs)** are valuable documents that should be maintained alongside your codebase. To ensure that TDRs are effectively tracked and managed, consider the following best practices:

1. **Check TDRs into Version Control:**

   - **Git:** Commit TDRs to your Git repository alongside your code. This approach ensures that TDRs are versioned and can be reviewed, branched, and merged similarly to your source code.
     
     **Example:**
     ```bash
     git add technical_debt_record.md
     git commit -m "Add TDR for Outdated Authentication Library"
     git push origin main
     ```

   - **SVN:** Similarly, commit TDRs to your SVN repository to maintain version history and collaboration.

2. **Organize TDRs:**

   - **Directory Structure:** Maintain a dedicated directory (e.g., `/docs/tdrs/`) within your repository to store all TDRs. This organization facilitates easy navigation and management.
   
   - **Naming Conventions:** Use clear and consistent naming conventions for TDR files, such as `TDR-<ID>-<Title>.<extension>`. For example, `TDR-101-Outdated-Auth-Library.md`.

3. **Link TDRs with Issues or ADRs:**

   - **Issue Tracking Integration:** Reference TDRs in your issue tracker (e.g., Jira, GitHub Issues) to provide context and track resolution progress.
   
   - **Architecture Decision Records (ADRs):** Link related ADRs to TDRs to maintain a comprehensive documentation trail of architectural decisions and their technical debt implications.

4. **Regular Review and Updates:**

   - **Periodic Audits:** Schedule regular reviews of TDRs to assess their current state, prioritize resolutions, and update statuses as work progresses.
   
   - **Continuous Improvement:** Encourage team members to document new technical debt promptly and update existing TDRs to reflect any changes.

5. **Access Control:**

   - **Permissions:** Ensure that only authorized team members can create, modify, or delete TDRs to maintain data integrity and accountability.
   
   - **Collaboration:** Use version control features like pull requests or merge requests to facilitate collaborative reviews and approvals of TDRs.

Conclusion

**Technical Debt Records (TDRs)** are an indispensable tool for managing technical debt in software projects. They provide transparency, facilitate prioritization, and support strategic decisions to enhance code quality and system architecture. The introduced **TDR Generator** simplifies the creation of these essential documents and integrates seamlessly into existing development and version control workflows.

By consistently utilizing TDRs and integrating them into your version control systems like Git or SVN, teams can effectively manage technical debt, ensuring the long-term health and maintainability of their software projects.






Source: https://github.com/ms1963/TechnicalDebtRecords/tree/main

Saturday, July 13, 2024

AI is not about Intelligence

 I am now working on AI topics for several years. As you all know, the current enthusiasm is bot mind-blowing and terrifying.  Laymen often tell me what they think AI is all about. In most cases, they assume AI algorithms, in particular LLMs, are smart in a human sense.

No, they are not smart like humans. Their behavior makes us think they are. I can understand why people are surprised whenever  LLMs provide some elaborate and sophisticated answers.  In reality all of their replies are based on statistics and giant sets of training data. 

It is the same for artificial neural networks (ANN). An ANN is trained with large datasets  in a process called supervised learning.  The outcome of each inference is a probability function. If you teach a CNN network how a cat or dog looks like, it will find some commonalities respectively patterns of each class (such as dog or cat). Given a picute it has not seen before  it just estimates how close the subject in this picture resembles a cat, a dog or anything else. When you feed it with a picture of a cat, it'll only be able to respond that this could be a cat with a probability of 91.65%.

The same holds for transformer models (encoders, decoders) in LLMs. They are trained with a huge amount of documents to create embeddings. These are just vectors that describe in which context a specific fragment is typically being used. To create answers, LLM implementations need to understand the meaning of the prompt,and eventually to create a reply, word by word, where each succeeding word is determined by a probability function. Actually this actual process is much more complex and sophisticated, but the principle remains the same.

What is missing in AI to call them smart in a human sense?

  • Lack of proactivity: AI algorithms only react to input. They are not capable of proactive behavior.
  • No consciousness: They have no consciousness and cannot reflect on themselves. 
  • Lack of free will: This is a consequence of AI lacking proactivity and consciousness. An AI provides answers but makes no decisions.
  • No emotions: AIs can recognize the emotions of humans, for example, by performing a sentiment analysis or by observing gestures. However, they cannot experience their own emotions such as feeling empathy.
  • Learning from Failure: AI is not able to learn from its own errors. And obviously there is no way to interactively teach an AI about its mistakes so that it can dynamically adapt. Errors or biases can only be eliminated by changing the training data or the algorithms which at the end of the day results in a new AI.
  • Constraints: An AI is constrained by the input it receives. It is not able to observe its enviroment outside of its cage.
  • Fear of death: An AI does not care about whether it lives or not. This might sound rather philosophical but is a valid aspect, given the way intelligent life behaves. 
Unfortunately, the Turing test is not able to decide whether an AI is intelligent. It can only figure out whether an AI seems to be intelligent. 

What do you think? How could an appropriate test look like?


Tuesday, September 05, 2023

The Dark Side of Crowdfunding

This post is not going to cover any software architecture topic. Instead I want to share some impressions and experiences with crowdfunding platforms such as Indiegogo or Kickstarter.


Let me start with a success story: Bambu Lab was completely unknown when the upcoming 3D printer company started their X1/X1C campaign via Kickstarter. They eventually gathered almost 55 million HK-$ from 5575 backers. In the following months Bambu Lab completed the X1/X1C product line and sent all the perks to the backers. This new CoreXY 3D printer turned out to be a revolutionary, award-winning and extremely successful product which soon was followed by other products like the P1P and the P1S. Needless to say that Bambu Lab has been a huge success story with a happy end  for the crowdfunding company, the campaign owner, and the backers. 


One of the benefits of crowdfunding can be summarized as: crowdfunding platforms connect innovative campaigners and enthusiastic backers. They enable start-up companies and well established companies to get funding for innovative products.


In hindsight, not all campaigns work that well. In some cases, campaigners fail to provide a product, only create an under average product, run out of money, or turn out to be scams. Year by year millions of US-$ get lost this way. It is never foreseeable whether a project will succeed, as it is the case with joint ventures. Reasons for failure might be infeasibility of the innovation, budget overspending, huge project delays caused by unfortunate conditions such as Covid-19, underestimation of costs, or sharp increases of prices for necessary components.


While project failure can never be avoided, scams can. A chinese campaign owner collected over one million US-$ in his Indiegogo campaign featuring the world‘s smallest Mini-PC, but did not create any of the promised perks. After a while there would be even no communication between campaign backers and the campaign owner. It seemed as if the owner just had disappeared from the surface. When backers asked Indiegogo for help, the crowdfunding company did not feel responsible. They just disabled any further contributions, put a „this campaign is currently under investigation“-label on the project web site, but did never provide any results of the so-called investigation nor a refund to betrayed customers.


Lesson 1: crowdfunding companies do not care (too much) about backers. They earn money by providing a platform for different parties, treat backers as venture capitalists who are supposed to bear all the risks themselves.


Indiegogo, Kickstarter basically act like betting offices for horse races with almost no transpareny about the horse owners (aka campaign owners). Every participant in such scenarios bears high risks with the betting company being the only exception. Obviously, the rules between customers and the crowdfunding platform are defined in such a way that the bank (aka betting office) will always win.


Lesson 2: if you are contributing to a crowdfunding campaign, make sure, you can live with project failure and with complete loss of your contributions.


Every backer should be aware of this reality. She/he may lose her/his whole contribution or get an overpaid or even useless perk. Sure, the majority of campaigns does eventually succeed. However, there is also a significant amount of campaigns that fail. I do not bother about project failure despite of huge efforts of campaign owners. This is a known and acceptable risk backers should keep in mind when contributing. But I bother about scam campaigns where owners just take the collected contributions and vanish.


Lesson 3: If you urgently need a specific type of product, don‘t contribute to a crowdfunding campaign, but buy it from well-established sources instead.


Lesson 4: Currently, no safety nets for backers exist. Neither is there any transparency or accountability with respect to campaign owners. A campaign resembles a game or a bet on the future without sufficient transparency regarding campaign owners. 


Lesson 5:  Do not believe in videos and documents provided by campaigners.  Consider this information as a pure marketing and advertising campaign. Never trust any promises, in particular not those that seem to be unrealistic or very, very challenging to fulfil. Phrases like „the world‘s first“, „the world’s fastest“ or „the world’s smallest“ should make backers sceptical.


What could be done to avoid such situations? Or is the crowdfunding platform inherently unable to protect backers?


In fact, there should be a kind of trust relationship between all players in the game - yes, it is a game! To achieve the right level of trust, a crowdfunding company shall offer the following services:

  • Personal identification of all campaign owners with official and legal documents such as passports, driver licenses, locations of residence. This enables companies like Indiegogo or Kickstarter to keep in touch with campaign owners and track them down. Sure, passports and the like can be faked as well, but this requires a substantial amount of criminal energy.
  • Transparency: If we analyze existing campaigns, lack of transparency is one of the biggest issues. By „lack of transparency“ I am referring to the fact that backers often know almost nothing about campaign owners. This is related to the previous aspect. While backers need to guarantee with credit card payments that they are trustworthy (which is checked by the credit card companies), they only get a tiny amount of  information about campaign owners in return. Wait a minute. I am paying my contribution to people that are mostly anonymous (i.e. hiding behind a campaign web site)? Unfortunately, the answer is yes. It does not suffice when only the crowdfunding company owns detailed information about the campaign owners.
  • Due diligence measures would require a crowdfunding company to technically check whether a campaign respectively project is feasible. For this purpose, they may hire experts in the respective domain to validate the claims campaign owners make. In addition, they should check the background of campaign owners, be it companies or individuals.  If a successful company such as Anker acts as the campaign owner, there is a much higher chance that contributors will receive the offered perks and rewards. If on the other hand the campaign originator is unknown, the risk is significantly higher. Accountability should come to one’s mind when thinking about campaigns and their originators.
  • Check and balances: step-wise transfer of contributions instead of full payment at once. This may be a bit difficult to achieve, because certainly some upfront investments are required by campaign owners. Nonetheless, I’d expect more of a bank (crowdfunding platform)/borrower (campaign owner) attitude in this context. In each step (such as prototyping, testing, final product design, manufacturing, delivery) the crowdfunding company should demand proofs by the campaign owners what they did and achieve so far with the crowdfunding investments. For example, prototyping only requires a smaller amount of money. After coming up with  a successful prototype, they may move forward to completing the product. After the product is ready, they move further to manufactoring.  In each step they obtain predefined percentages of funding. In addition, campaign owners are supposed to provide a concrete time line for all of their activities. If a step is delayed, no further money can be obtained until the step is completed. A kind of traffic light on the project web site could represent the current risk level of a campaign.
  • Shipment: for each project campaign owners need to prove that they actually shipped the perks and rewards to their backers by presenting respective documents from the delivery service. In my experience, some campaign owners marked the perks as being shipped without ever actually sending any items.
  • Insurance: Crowdfunding companies should pay a part of each contribution to an insurance company that covers all risks and pays back a high percentage of the contribution to backers. This is similar to how Paypal works. It would require campaign originators to disclose personal information which can then be rated in terms of credibility, credit history, financial background, and trustability. This puts more burden to the campaign owners and the crowdfunding company, and makes contributions more expensive, but provides a safety net for backers which are those who pay campaign owners and crowdfunding platforms, anyway. I assume, many backers would be willing to pay a slightly higher contribution if they win more security in return. Of course, crowdfunding platforms could act as insurances themselves if they are willing to do so.
  • No selling on other channels: In some campaigns the perk developers started selling their products via their web sites before some backers even received their perks. The contract between campaigners and crowdsourcing plaforms should definitely exclude this possibility. Whenever backers spend funding to product development via a crowdfunding campaign, they must be the first who receive their perks and rewards. In addition, some of the products sold were significantly cheaper than the claimed MSRP. This looks like betrayal, smells like betrayal and is a betrayal.  In such cases I‘d expect campaign owners to have to pay penalties to backers.

Some may argue that all of these measures restrict the freedom of campaign owners. They are right in this respect. However, there currently is an imbalance between contributors, campaign originators, and crowdfunding platforms which puts most risks on the backers. Thus, it seems more than fair to share these risks among all stakeholders. I honestly believe, that crowdfunding evolves to a dead end, if companies like Indiegogo continue to put all burdens to backers, don‘t care much about scams, refuse to create safety nets, or keep the high intransparency. If they realize all or at least some of the aforementioned measures, this clearly will turn out to be more of a Win/Win/Win scenario.