For the complete documentation index, see llms.txt. This page is also available as Markdown.

AI-PDI Pipelines

Key concepts behind interacting with a LLM - Chatbot ..

Overview of typical LLM Use case - Chatbot

Ever wondered whats happening under the hood when you chat with an LLM ..

Here's the big picture - four stages every time you hit send:

Under the hood with a Chatbot

Tokenisation is just the model chopping your message up into manageable pieces. Not always whole words — sometimes syllables or punctuation get their own token. It's a standardisation step before any real processing happens.

Embedding is where it gets interesting. Each token gets mapped to a point in a vast mathematical space, where meaning is encoded as position. Words with similar meanings literally end up close together — that's how the model "knows" that dog and cat are more related than dog and bicycle.

Neural network processing is the heavy lifting. Your tokens flow through layer after layer of the transformer, with each layer building a richer understanding. Early layers catch basic patterns; deeper layers grasp context, nuance, and intent. The attention mechanism is what lets the model link words that are far apart in a sentence — deciding which parts of your prompt are most relevant to each other.

Generation is where the output is built up one token at a time. The model doesn't write the whole sentence in one go — it predicts the single most probable next token, appends it, then repeats. That's why LLMs can feel like they're "thinking out loud."

Tap any of the boxes in the diagram to go deeper on any stage!


Workshops - Key Concepts

Prompt

When a user inputs a prompt, an embedding model processes the text, converting into a numerical vectors.

The vector is then passed through the transformer architecture, which generates a probability distribution over the possible words or phrases that could follow the input.

Finally, based on a bunch of stats - semantic similarity, entropy metrics, perplexity, etc - the model then generates a response.

  1. Take a look at the Python script below.

When you run this script, it will:

  1. The user is prompted to connect to the Ollama server - N (local Ollama server)

  2. A text prompt "What is the capital of France?" is defined.

  3. An embedding for the given text prompt is created using the create_embedding(text, client) function and Ollama' s text-embedding model.

  4. The shape (dimensions) and first 10 dimensions of the resulting embedding vector are printed to provide an overview.

  5. Basic statistics about the embedding vector such as mean, standard deviation, minimum value, and maximum value are calculated and visualized using a histogram plot, line plot, and text summary in a single figure. The visualization is saved as a timestamped PNG file.

  6. A comparison of different text prompts' embeddings is made to demonstrate how similar or dissimilar the text inputs are based on their vector representations. This comparison results in a cosine similarity matrix, which is then visualized with text annotations and saved as another PNG file.


Run Python script - prompt.py

  1. Navigate to: Workshop--LLM/'Key Concepts'/ directory.

  1. Run the script.

Output - prompt.py

So what does this all mean ..?

So we're starting in the deep end .. basically we're taking a prompt - text input in this case - and creating a bunch of vectors (embedding) - a mathematical representation of the prompt. This is then compared with similar texts - vectors - to get an idea of how text can be generated based

A prompt is a way of providing guidelines to how the model responds. The context of the prompt is achieved by splitting the prompt into a number of words that are in a specific structure and format.

Take a look at the embedding_stats graphs:

Embedding Stats

The embedding analysis of the prompt "What is the capital of France?" reveals some interesting characteristics about how this question is represented in the AI model's vector space. This 1536-dimensional vector essentially transforms the text question into a mathematical format that the AI can process.

Looking at the distribution plot (left graph), we can see that most of the vector values cluster tightly around zero, with a clear bell-shaped curve. This suggests that the question has a well-defined, standard representation - which makes sense given that it's a straightforward, common type of geographical question. The narrow spread indicates that the model doesn't need extreme values to encode this query's meaning.

The First 50 dimensions (right graph), displays the first 50 dimensions, with a more detailed view of how the information is encoded. The oscillating pattern between positive and negative values (roughly between -0.03 and 0.03) shows how different aspects of the question - perhaps the interrogative nature ("what is"), the concept of a capital city, and the specific country (France) - are distributed across different dimensions.

Some dimensions show stronger signals (bigger peaks), likely corresponding to key semantic elements of the question. The statistical summary (right) confirms this balanced representation, with a mean very close to zero (-0.0007) and a moderate standard deviation (0.0255), indicating that the embedding effectively captures the question's meaning without requiring extreme values in any particular dimension. This balanced, normalized representation helps the model accurately process and respond to this type of geographical query.

Take a look at the similarity_matrix:

similarity matrix of the different prompts

This similarity matrix provides insights into how the embedding model understands and relates different questions about capital cities. Let's break down what the cosine similarity scores indicate:

The first two questions ("What is the capital of France?" and "Tell me France's capital city") show an extremely high similarity (0.938), which makes perfect sense as they're asking the same thing in slightly different ways. This demonstrates that the embedding model understands semantic equivalence even when the syntax differs.

The third question ("Paris is located in which country?") shows moderately high similarity with the France-related questions (0.877 and 0.863), but noticeably lower than the direct capital questions. This makes sense because while it involves the same entities (Paris and France), it reverses the relationship being asked about - instead of asking what the capital is, it's asking which country contains Paris.

Perhaps most interesting is how the model handles "What is the capital of Germany?" This question has relatively high similarity with the France capital questions (0.900 with the first question), despite being about a different country. This suggests the model recognizes the structural similarity of capital-city questions, while still maintaining enough difference to distinguish between different countries. The lower similarity (0.804) with the Paris question makes sense, as it's both about a different country and asks the relationship in a different direction.

The color gradient in the heatmap effectively visualizes these relationships, with the darkest reds showing perfect self-similarity (1.000) along the diagonal, bright reds for near-equivalent questions, and progressively lighter colors for questions that share less semantic content.

x

Tokenization

We've jumped ahead a bit with our prompt .. the OpenAI model - via API call -handled the important first step of Tokenization.

So .. it all begins begins with tokenization - essentially the model's way of breaking down text into manageable pieces. Think of it like cutting a sentence into puzzle pieces that the model can understand. Some tokenizers work at the word level, while others might split words into subwords or even individual characters.

These tokens then need to be converted into a format that the model can mathematically process. This is where embeddings come in. Each token is transformed into a vector - essentially a long list of numbers - that represents its meaning in a high-dimensional space.

The embedding process captures semantic relationships between tokens. Words with similar meanings will have similar vector representations. For instance, "cat" and "kitten" would have embeddings that are closer together in this vector space than "cat" and "automobile."

The quality of embeddings significantly impacts model performance. Good embeddings preserve meaningful relationships between concepts and allow the model to make relevant connections. Poor embeddings might lose important semantic distinctions or create misleading relationships between unrelated concepts.

Modern language models often learn their embeddings during pre-training. This allows them to develop nuanced representations that capture both obvious relationships and subtle distinctions in meaning. The embedding space becomes a rich semantic landscape where similar concepts cluster together and related ideas can be found in proximity to each other.

The interaction between tokenization and embedding is crucial. A token that's too large (like a whole phrase) might lose important nuances in its embedding. Conversely, tokens that are too small (like individual letters) might fail to capture meaningful semantic units. Finding the right balance is key to effective language model performance.

Context windows in language models are typically measured in tokens, not raw text. This means that both tokenization and embedding strategies directly impact how much information can be processed in a single prompt. Efficient tokenization can help maximize the effective use of this context window.

Tokenization
  1. Take a look at the Python script below:

Script Walkthrough

When you run this script, it will:

  1. Explore and analyze the tokenizer's vocabulary by saving information about the vocabulary to a text file in the output directory.

  2. Analyze individual texts for their token mapping by printing the token-to-text mappings for each input text.

  3. Visualize how text is broken down into tokens by generating plots that show the tokenization process and saving these plots as images in the output directory.

  4. Compare tokenization of similar texts to identify any differences or patterns in tokenization behavior. These comparisons are saved as plots in the output directory.

  5. Analyze token statistics for a list of example texts by calculating statistics such as the number of tokens, average token length, and standard deviation of token length. The results of this analysis are saved as a plot in the output directory.

  6. Compare different encodings available in tiktoken to identify any differences or patterns in encoding behavior. This comparison is saved as a text file in the output directory.


Run Python script - tokenization.py

  1. Navigate to: Workshop--LLM/'Key Concepts'/ directory.

  1. Run the script.

output - tokenization

What does it mean?

Ok .. there's a lot going on here .. but its pretty simple ..!!

The first section shows a sample of the base vocabulary from the cl100k_base tokenizer, displaying basic tokens like punctuation marks and common characters. This demonstrates how the tokenizer breaks down text at its most fundamental level.

The analysis then examines several test cases, starting with "OpenAI". Interestingly, "OpenAI" is split into two tokens: "Open" (token ID 5169) and "AI" (token ID 16836). This shows how the tokenizer handles compound words by breaking them into meaningful subcomponents.

For "machine learning", the tokenizer also splits it into two tokens (IDs 13156 and 6972). This is a common pattern where frequently occurring compound phrases are tokenized as separate words, which helps maintain semantic meaning while keeping the vocabulary size manageable.

The URL example "https://example.com" demonstrates how the tokenizer handles special strings. It breaks the URL into four distinct tokens: "https", "://", "example", and ".com". This granular breakdown allows the model to recognize common URL patterns and components.

"Python3.9" is tokenized into four pieces: "Python", "3", ".", and "9". This shows how the tokenizer handles version numbers and technical strings by separating numbers, dots, and text into individual tokens.

The final comparison of different encodings (cl100k_base, p50k_base, and r50k_base) is particularly interesting. While they all produced 13 tokens for the test phrase, they use different token IDs for the same components. This highlights how different encoding schemes can represent the same text differently while maintaining the ability to reconstruct the original input accurately.

What's particularly notable is that in all test cases, the "Matches original: True" confirmation shows that the tokenization process is reversible - the tokens can be correctly decoded back into the original text, which is crucial for maintaining text integrity in language models.

Tokenization Directory

Finally take a look at the output in the /tokenization_plot directory. Here you'll find the tokenization of our prompt: "What is the capital of France?"

Prompt tokenization
Comparison of the tokenization of the different prompts
Prompts - token counts

Based on the TokenIDs we're now ready to create the embedding vectors - mathematically representations.

Why is embedding so important ..?

Its creating a numerical representation of a piece of text, such as a word, sentence, or paragraph. It is created by mapping the text to a high-dimensional vector space, where each dimension corresponds to a specific feature or attribute of the text.

For example, suppose we want to create an embedding for the word "orange". We might represent the word as a vector in a high-dimensional space, where each dimension represents a characteristic of the word, such as its size, color, or whether it is a noun or a verb, its position in the sentence, the localization, and so on .. its context ..

  • Fruit: In the context of a discussion about fruit, "orange" would likely refer to the citrus fruit that is round and typically orange in color.

  • Color: In the context of discussing color, "orange" might refer to the color that is a mix of red and yellow, similar to the color of an orange fruit.

  • Juice: In the context of discussing beverages, "orange" might refer to orange juice, which is a popular drink made from squeezing the juice from oranges.

  • Clothing: In the context of discussing clothing, "orange" might refer to a garment or accessory that is colored orange.

By training a machine learning model on a large corpus of text, the model can learn to map words to vectors in such a way that words with similar meanings or contexts are mapped to similar vectors.

Embedding
  1. Take a look at the Python script below:

  • define the EmbeddingAnalyzer class that encapsulates embedding operations

  • set up the Ollama client with either default or custom host URL

  • analyze the results to calculate similarities


Run Python script - embedding.py

  1. Navigate to: Workshop--LLM/'Key Concepts'/ directory.

  1. Run the script.

Out - embedding.py

So what does this all mean ?

Jumping ahead a bit you can see how the heatmap - Semantic Similarity - adds context. It defines the semantic relationship between the words in the prompts.

This becomes clearer with topic clustering - each topic is clearly separated - which helps pinpoint the vector cluster in the model that will help generate a response.

Take a look at the similarity_heatmap graph:

Similarity matrix

Basically the same as discussed in the 'Prompt' section ..

This heatmap visualizes how similar different phrases are to each other, using data from OpenAI's text embedding model. The darkness and numbers in each square show how closely related two pieces of text are - with darker reds showing stronger relationships (closer to 1.0) and lighter yellows showing weaker relationships (closer to 0.8).

Looking at the pattern, we can see that the first three texts are very closely related (showing dark red with scores around 0.93-0.95), suggesting they're asking similar questions. The fourth text is also fairly similar to these first three but slightly less so. The fifth text stands out as being the most different from all others, showing consistently lighter colors (scores around 0.83-0.85) across its row and column.

This kind of visualization is particularly useful for understanding how language models group similar concepts together and distinguish between different topics, even when they share some common elements or words.

Take a look at the embedding_clusters graph:

This visualization shows how different topics cluster together when their text embeddings are reduced to 2D space using t-SNE (as implemented in the code's visualize_embedding_clusters method). Each point represents a question or statement, color-coded into three categories: Tech (blue dots), Sports (orange X's), and Cooking (green squares).

The plot demonstrates clear topic separation, with tech-related questions clustering in the lower portion of the plot, sports questions scattered across the middle, and cooking-related queries grouped in the upper region. This clustering shows how the embedding model effectively captures the semantic relationships between similar topics, keeping related concepts close together in the vector space while separating different subject matters.

From the code, we can see these points represent questions like "How do computers process information?" (Tech), "Who won the last World Cup?" (Sports), and "What's the best way to cook pasta?" (Cooking).

The clear separation between these clusters validates that the embedding model is successfully capturing the distinct semantic meanings of these different topics - content classification.

Topic clustering

Take a look at the embedding_distribution graph:

Distribution of vectors

Again this was discussed in the prompt section ..

But what is a dimension ..?

A text embedding with 1536 dimensions means that each piece of text is converted into a list of 1536 different numbers. Think of it like a very detailed fingerprint of the text, where each number captures a different aspect of its meaning. While we can easily picture things in 2 or 3 dimensions (like length, width, and height), this embedding uses many more dimensions to capture the rich complexity of language.

These 1536 numbers work together to represent subtle patterns in the text - everything from the topic and tone to the structure and style. When we want to compare two pieces of text, we can compare their 1536-dimensional fingerprints to see how similar they are, as we saw in the earlier heatmap. The high number of dimensions allows the model to be very precise in distinguishing between different types of text while recognizing similarities.

Since humans can't visualize 1536 dimensions, we use techniques to reduce it down to 2 dimensions for visualization - topic cluster plot. This is similar to taking a complex 3D object and drawing its shadow on a flat surface - you lose some detail, but you can still see the basic relationships between different points.

Everything is now in place for the LLM to deal with our prompt ..

So let's dive into the heart of the LLM - Transformers..!

Transformer

Understanding the Encoder Structure Looking at the green section (ENCODER) in the diagram, we can see how an input sequence gets processed. The encoder starts with raw "Inputs" at the bottom and transforms them through several stages.

Input Processing Path The diagram shows how inputs first become "Input Embeddings" (yellow box), which combine with "Positional Encodings" through an addition operation (+). This combination ensures the model knows both what the words mean and where they appear in the sequence.

Positional Understanding At the bottom of the encoder section, we see "Positional Encodings" being added to the input embeddings, showing how the model maintains awareness of word order throughout processing.

The Main Processing Block (Nx) The diagram shows a green block labeled "Nx" which means this section repeats N times. Inside this block, we see two main components:

  1. "Multi-Head Attention" (handling self-attention)

  2. "Feed Forward" (processing individual positions) Each component is followed by "Add & Norm" boxes, representing residual connections and layer normalization.

Multi-Head Attention Layer In the diagram, we see the "Multi-Head Attention" box with multiple arrows pointing in, showing how it allows each position to attend to all positions. This creates context-aware representations by letting each word "look at" all other words in the input.

Feed Forward Processing After attention, the diagram shows a "Feed Forward" box. This is an independent processing step that works on each position separately, transforming the attention-processed information further.

Add & Norm Operations The diagram shows "Add & Norm" boxes after both the attention and feed-forward components. These represent:

  • Addition operations for residual connections

  • Normalization to keep values in a manageable range

Final Output The processed information from the encoder (after going through Nx blocks) connects to the decoder (blue section), showing how the encoder's output becomes input for the next stage of processing.

This architectural design creates a powerful system for understanding input sequences, with each component playing a crucial role in transforming raw inputs into rich, context-aware representations.

The decoder's fundamental purpose is to transform encoded representations into meaningful outputs through a sophisticated multi-layer architecture. Let's break down each component in detail:

Initial Input Processing The decoder begins at the bottom with output embeddings, which are combined with positional encodings using an addition operation (shown by the + symbol in the diagram). This combination ensures the model understands both the content and the sequential position of each element in the output sequence.

Core Processing Blocks (Nx Times) The blue section marked with "Nx" indicates that this entire stack of layers repeats N times. Each repetition contains three distinct processing blocks:

Masked Multi-Head Attention Block

This first attention layer is specifically marked as "Masked" in the diagram

The masking prevents the decoder from looking at future positions during training

The output passes through an Add & Norm layer (shown in purple)

This normalization helps maintain stable training by controlling the scale of values

Cross-Attention Mechanism

The regular "Multi-Head Attention" block connects to both:

  • The output of the previous masked attention layer

  • The encoder's output (shown by the horizontal line from the encoder)

This allows the decoder to reference the entire input sequence while generating each output element

Another Add & Norm layer follows this attention mechanism

Feed-Forward Processing

The final block in each layer is the "Feed Forward" network (shown in orange)

Like the previous components, it's followed by an Add & Norm layer

This feed-forward network processes each position independently, applying the same transformations to each element

Output Generation After passing through all Nx layers, the decoder's final stages are:

  • A Linear transformation layer that projects the representations into the desired output dimension

  • A Softmax layer that converts these values into probability distributions over the possible output tokens

Residual Connections Throughout the architecture, residual connections (represented by the addition symbols) allow information to flow directly from lower layers to higher ones, helping prevent information loss and enabling better gradient flow during training.

The entire structure is designed to work in concert with the encoder (shown in green on the left), creating a complete system that can handle complex sequence-to-sequence tasks like translation, summarization, or question-answering. The careful balance of attention mechanisms, normalization, and feed-forward processing enables the model to generate contextually appropriate and coherent outputs while maintaining awareness of both the input sequence and the previously generated outputs.

This architecture reflects key insights about sequence processing: the importance of position awareness, the need for both local and global context through different types of attention, and the value of repeated processing through identical layers to extract increasingly sophisticated patterns from the data.

Link to a great blog on Transformers
  1. Take a look at the Python script below.


Run Python script - transformers.py

  1. Navigate to: Workshop--LLM/'Key Concepts'/ directory.

  1. Run the script.

Output - transformers.py

The transformer architecture consists of six key sequential processing stages, as shown in the diagram.

Transformer stages

Input Embedding forms the foundation of the process. Here, each token (like "What", "is", etc.) is converted into a dense vector representation. These embeddings capture semantic meaning by mapping similar words to similar vector spaces. In your code, this is simulated by retrieving embeddings from the llama3.2 model via the Ollama API.

Positional Encoding addresses a critical limitation of the basic transformer architecture—lack of sequence awareness. Since transformers process all tokens simultaneously rather than sequentially, positional encodings are added to the token embeddings to provide information about token position within the sequence. This helps the model distinguish between different arrangements of the same words.

Self-Attention is perhaps the most innovative aspect of transformers. In this stage, each token looks at all other tokens in the sequence (including itself) and computes attention weights indicating relevance. Your token attention matrix visualizes exactly this—how each token in "What is the capital of France?" attends to other tokens in the sequence.

Feed Forward networks follow the attention mechanism. After tokens gather contextual information via self-attention, each token's representation passes through a fully-connected neural network. This consists of linear transformations with non-linear activation functions that process each token independently, allowing the model to transform the contextualized representations further.

Layer Normalization stabilizes the learning process. This statistical normalization technique standardizes the activations, making training more efficient and preventing internal covariate shift. In transformers, layer normalization is typically applied both after the self-attention and after the feed-forward networks.

Final Representation emerges after these processing stages. The output is a set of contextualized token representations that capture both the semantic meaning of each token and its relationship to other tokens in the sequence. These final representations can then be used for various tasks, like predicting the next token ("Paris" in response to "What is the capital of France?").

Last updated

Was this helpful?