📊 View Lecture Slides Full-screen presentation with navigation

Session 8: Grounding AI — Embeddings Basics

Session Duration: 2 Hours     Block: 2 — AI-Assisted Engineering & Integration

Note on Stack as of August 2026: We use the embedding model gemini-embedding-2. Confirm on ai.google.dev if the recommended embedding model ID changes.

Session clock

Minutes Mode Focus
0–50 Lecture Theoretical Foundation & Concepts
50–110 Core lab Generate Vectors & Compute Similarity
110–120 Checkpoint Pair share / show artifact

Note: Core lab requires generating embeddings for a handful of notes to confirm cosine similarity works. Stretch work involves advanced overlap chunking and embedding massive vaults.


Learning Objectives

By the end of this session, students will be able to:

  • Explain what vector embeddings are and how they mathematically represent semantic meaning.
  • Generate embeddings from text using the Gemini API in a Node.js environment.
  • Calculate cosine similarity in JavaScript to determine how closely related two pieces of text are.
  • Describe how embeddings form the retrieval foundation of a Retrieval-Augmented Generation (RAG) system.

Part 1: Theoretical Foundation — How AI Represents Meaning

1.1 The Problem with Static Knowledge

Every large language model has a knowledge cutoff date. A model trained in 2023 knows nothing about the election results of 2024, the internal API docs you wrote yesterday, or the specific product prices for your startup.

If you ask an ungrounded model about these topics, it will either refuse to answer or, worse, hallucinate a plausible-sounding lie.

Grounding is the process of feeding the model relevant, factual information at query time. We do this by retrieving the right document from your exocortex (your Obsidian vault) and inserting it into the prompt. But how do we find the “right” document out of thousands of notes when a user types a messy, conversational question? Keyword search (like CTRL+F) fails if the user searches for “canines” but the document says “dogs.”

The solution is semantic search powered by embeddings.

1.2 What Is a Vector Embedding?

To a computer, text is just a sequence of ASCII or UTF-8 characters. It has no meaning. AI researchers solved this by converting concepts into geometry.

A vector embedding is a long list of numbers (an array of floating-point values) that represents the semantic meaning of a piece of text. The core rule of embeddings: Similar meaning → similar numbers (closer together in space).

Imagine a simple 3D graph where the X-axis is “Animals”, the Y-axis is “Math”, and the Z-axis is “Food”.

  • The word “Puppy” might have coordinates [0.9, 0.01, 0.2].
  • The word “Dog” might be [0.85, 0.05, 0.15].
  • The word “Algebra” might be [0.01, 0.95, 0.0].

In this space, “Puppy” and “Dog” are geometrically close to each other. “Algebra” is very far away. Real embedding models (like gemini-embedding-2) don’t use 3 dimensions; they use hundreds or thousands of dimensions (e.g., 768) to capture incredibly nuanced semantic relationships, tone, and context.

1.3 Cosine Similarity: Measuring Distance

Once we convert sentences into vectors (arrays of numbers), how do we determine which ones are closest? We use a mathematical formula called Cosine Similarity. It measures the angle between two vectors.

In NLP (Natural Language Processing), cosine similarity yields a score between -1 and 1 (though practically, it’s usually between 0.0 and 1.0 when dealing with text embeddings).

  • 1.0: Identical meaning (or the exact same text).
  • 0.7–0.9: Very highly similar or highly relevant.
  • 0.5–0.7: Somewhat related (sharing some semantic overlap).
  • 0.0 - 0.3: Completely unrelated topics.

At query time, the math is simple:

  1. Embed the user’s question into a vector.
  2. Calculate the cosine similarity score against every chunk in your database.
  3. Keep the top K chunks (e.g., the 3 chunks with the highest scores).

1.4 The Embedding Workflow

Building a semantic search system is a two-step process.

Phase 1: Offline Indexing (Done once, or on a cron job) This happens when you build your knowledge base, before the user ever asks a question.

  1. Read the Markdown files from your vault.
  2. Split them into chunks.
  3. Call the API (embedContent) for each chunk to get its vector.
  4. Store the text chunk and its vector array together in a database (for this course, a simple embeddings.json file).

Phase 2: Online Retrieval (Done at query time — Session 9) This happens instantly when a user clicks ‘Submit’.

  1. Take the user’s text query.
  2. Call the API to embed the query.
  3. Run cosine similarity to find the nearest stored vectors.
  4. Inject those matching text chunks into the Gemini prompt.

1.5 Chunking Strategy

You cannot embed an entire 50-page book as a single vector. The “meaning” gets diluted. You must chunk the text.

  • Target Chunk Size: 200–500 words is a sweet spot for RAG. It’s enough to provide context, but small enough to remain semantically focused.
  • Semantic Boundaries: Do not just split text arbitrarily every 1,000 characters (which might cut a sentence in half). Split on natural boundaries like Markdown headings (##) or double line breaks (paragraphs).
  • Overlap: (Advanced) When chunking, include a 50-100 word overlap between chunk A and chunk B. This ensures that context isn’t lost if a crucial idea crosses a paragraph boundary.

Part 2: Practical Labs — Generate and Explore Embeddings

Vault quality gate: Before you proceed, ensure your Obsidian vault has at least 5 to 10 substantial notes related to your product idea. If you haven’t written them yet, you can use the sample-vault/ provided in the starter kit to test the code.

Lab 8.1 — Generate Your First Embeddings (Core)

In your starter kit, locate lib/embeddings.js. Your task is to implement the embedText function using the Gemini SDK.

import { GoogleGenAI } from '@google/genai';

// Initialize the client
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });

export async function embedText(
  aiClient,
  text,
  taskType = 'RETRIEVAL_DOCUMENT'
) {
  const response = await aiClient.models.embedContent({
    model: 'gemini-embedding-2',
    contents: text,
    config: { taskType }, // Tells the model if it's indexing a doc or processing a query
  });

  // Return the array of floating point numbers
  return response.embeddings[0].values;
}

Test it: Write a quick scratch script to pass the string "I love coffee" into this function and console.log the resulting array. Notice how long the array is (the dimensionality of the model).

Lab 8.2 — Compute Cosine Similarity (Core)

The starter kit already includes a mathematical helper function for cosineSimilarity(vecA, vecB) in lib/embeddings.js.

Write a tiny script to test it:

  1. Generate an embedding for String A: "The artificial intelligence model is training."
  2. Generate an embedding for String B: "Machine learning algorithms are optimizing."
  3. Generate an embedding for String C: "I prefer my espresso with oat milk."

Calculate the similarity between A & B, and A & C. Observation: A and B use completely different words, but their semantic score should be high. A and C should be very low. This proves semantic search works beyond keyword matching!

Lab 8.3 — Embed the Vault Notes (Core)

It’s time to run Phase 1 (Offline Indexing) on your actual vault. We have provided a build script in the kit that reads Markdown files, chunks them, calls your embedText function, and saves them to a file.

  1. Ensure your lib/embeddings.js is fully implemented and exported.
  2. Open your terminal. Run the build script, pointing it to your Obsidian vault. (If your vault is outside the project folder, specify the path).
# If using the provided sample vault:
npm run build-embeddings

# If pointing to your own vault:
VAULT_PATH=/path/to/your/obsidian/vault npm run build-embeddings

This script will process your Markdown files (up to a limit of 10 for Core to avoid rate limits) and output an embeddings.json file in your project root. Open embeddings.json and inspect it. You should see an array of objects containing { file, content, vector }.

Do not proceed to Session 9 until this file successfully generates.

Stretch Goal: Modify the chunking logic inside scripts/build-embeddings.js to split on ## headings rather than raw character counts, ensuring cleaner semantic chunks.


Key Takeaways

  • Vector Embeddings translate semantic meaning into geometry (lists of numbers). Sentences with similar meanings produce similar vectors, regardless of the exact vocabulary used.
  • Cosine similarity is the mathematical operation used to measure the distance (relevance) between a user’s query vector and your stored document vectors.
  • RAG requires an offline indexing phase (generating embeddings.json) and an online retrieval phase (scoring at query time).
  • You now have a mathematical index of your exocortex, ready to be searched instantly in the next session.

Further Reading & Resources

  • Gemini Embeddings Guide: ai.google.dev/gemini-api/docs/embeddings - Read about the different taskType configurations.
  • “What are Word Embeddings?” - A great conceptual explainer video by Jay Alammar or 3Blue1Brown on YouTube to visualize high-dimensional space.