<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Vijay Gokarn, Author at Vijay Gokarn</title>
	<atom:link href="https://vijay-gokarn.com/author/vijaygokarn130/feed/" rel="self" type="application/rss+xml" />
	<link>https://vijay-gokarn.com/author/vijaygokarn130/</link>
	<description>&#34;Ignite Curiosity. Fuel the Future.&#34;</description>
	<lastBuildDate>Sun, 19 Apr 2026 03:33:59 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://i0.wp.com/vijay-gokarn.com/wp-content/uploads/2023/09/cropped-ideogram.jpeg?fit=32%2C32&#038;ssl=1</url>
	<title>Vijay Gokarn, Author at Vijay Gokarn</title>
	<link>https://vijay-gokarn.com/author/vijaygokarn130/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">230943525</site>	<item>
		<title>From Amazon Reviews to Numbers: A Hands-On Tour of One-Hot, Bag of Words, and TF-IDF</title>
		<link>https://vijay-gokarn.com/from-amazon-reviews-to-numbers-a-hands-on-tour-of-one-hot-bag-of-words-and-tf-idf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=from-amazon-reviews-to-numbers-a-hands-on-tour-of-one-hot-bag-of-words-and-tf-idf</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Sat, 11 Apr 2026 15:02:33 +0000</pubDate>
				<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[data-analysis]]></category>
		<category><![CDATA[pandas]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=263</guid>

					<description><![CDATA[<p>NLP · Machine Learning · Text Feature Engineering From Amazon Reviews to Numbers: A Hands-On Tour of One-Hot, Bag of Words, and TF-IDF Corpus128 real reviews TechniquesOHE · BoW · TF-IDF StackPython · sklearn · BeautifulSoup SourceGitHub ↗ How I took 128 real Amazon product reviews and turned them into features a machine-learning model can [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/from-amazon-reviews-to-numbers-a-hands-on-tour-of-one-hot-bag-of-words-and-tf-idf/">From Amazon Reviews to Numbers: A Hands-On Tour of One-Hot, Bag of Words, and TF-IDF</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
  .vg-blog-wrap {
    --ink: #0e0e0e;
    --paper: #f7f4ef;
    --paper-dark: #ede9e1;
    --teal: #0f6e56;
    --teal-light: #1d9e75;
    --teal-muted: #e1f5ee;
    --amber: #ba7517;
    --amber-light: #fac775;
    --amber-muted: #faeeda;
    --charcoal: #2c2c2a;
    --muted: #888780;
    --border: rgba(14,14,14,0.12);
    --border-strong: rgba(14,14,14,0.25);
    font-family: 'DM Sans', sans-serif;
    font-weight: 300;
    color: var(--ink);
    background: var(--paper);
    line-height: 1.75;
    font-size: 16px;
    overflow-x: hidden;
  }
  .vg-blog-wrap *, .vg-blog-wrap *::before, .vg-blog-wrap *::after {
    box-sizing: border-box; margin: 0; padding: 0;
  }

  /* ── HERO ── */
  .vg-post-hero {
    background: var(--ink);
    padding: 5rem 4rem 4rem;
    position: relative;
    overflow: hidden;
  }
  .vg-post-hero::after {
    content: '';
    position: absolute;
    bottom: 0; right: 0;
    width: 40%;
    height: 100%;
    background: rgba(15,110,86,0.12);
    clip-path: polygon(20% 0%, 100% 0%, 100% 100%, 0% 100%);
  }
  .vg-post-hero-inner { position: relative; z-index: 1; max-width: 860px; }
  .vg-post-eyebrow {
    font-size: 0.7rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--teal-light);
    font-weight: 500;
    margin-bottom: 1.25rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
  }
  .vg-post-eyebrow::before {
    content: '';
    display: inline-block;
    width: 1.5rem; height: 1px;
    background: var(--teal-light);
  }
  .vg-post-title {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(2.2rem, 5vw, 3.8rem);
    font-weight: 300;
    line-height: 1.1;
    color: var(--paper);
    letter-spacing: -0.02em;
    margin-bottom: 1.5rem;
    max-width: 22ch;
  }
  .vg-post-title em { font-style: italic; color: var(--amber-light); }
  .vg-post-meta {
    display: flex;
    gap: 2rem;
    flex-wrap: wrap;
  }
  .vg-meta-item {
    font-size: 0.72rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(247,244,239,0.4);
  }
  .vg-meta-item span { color: rgba(247,244,239,0.75); margin-left: 0.4rem; }

  /* ── INTRO BAND ── */
  .vg-intro-band {
    background: var(--teal-muted);
    padding: 2.5rem 4rem;
    border-left: 4px solid var(--teal);
  }
  .vg-intro-band p {
    font-size: 1.05rem;
    line-height: 1.85;
    color: var(--charcoal);
    font-weight: 300;
    max-width: 80ch;
  }
  .vg-intro-band strong { color: var(--teal); font-weight: 500; }

  /* ── BODY LAYOUT ── */
  .vg-post-body {
    max-width: 860px;
    margin: 0 auto;
    padding: 4rem 4rem;
  }

  /* ── SECTION HEADERS ── */
  .vg-step {
    margin-bottom: 3.5rem;
  }
  .vg-step-label {
    font-size: 0.65rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--teal);
    font-weight: 500;
    margin-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.6rem;
  }
  .vg-step-label::before {
    content: '';
    display: inline-block;
    width: 1.25rem; height: 1px;
    background: var(--teal);
  }
  .vg-step h2 {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(1.5rem, 3vw, 2.1rem);
    font-weight: 300;
    line-height: 1.2;
    color: var(--ink);
    margin-bottom: 1.25rem;
  }
  .vg-step h2 em { font-style: italic; color: var(--teal); }
  .vg-step p {
    font-size: 0.94rem;
    line-height: 1.9;
    color: var(--charcoal);
    font-weight: 300;
    margin-bottom: 1rem;
  }
  .vg-step p strong { color: var(--ink); font-weight: 500; }

  /* ── CALLOUT / TIP BOXES ── */
  .vg-callout {
    background: var(--paper-dark);
    border-left: 3px solid var(--amber);
    padding: 1.25rem 1.5rem;
    margin: 1.5rem 0;
    font-size: 0.88rem;
    line-height: 1.8;
    color: var(--charcoal);
  }
  .vg-callout strong { color: var(--amber); font-weight: 500; }
  .vg-callout code {
    font-family: 'DM Mono', monospace;
    font-size: 0.82rem;
    background: rgba(14,14,14,0.06);
    padding: 0.1rem 0.4rem;
    color: var(--ink);
  }

  /* ── TECHNIQUE CARDS ── */
  .vg-technique-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.25rem;
    margin: 2rem 0;
  }
  .vg-technique-card {
    background: var(--paper);
    border: 0.5px solid var(--border-strong);
    padding: 1.5rem;
    position: relative;
  }
  .vg-technique-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 3px;
  }
  .vg-technique-card.ohe::before { background: var(--muted); }
  .vg-technique-card.bow::before { background: var(--amber); }
  .vg-technique-card.tfidf::before { background: var(--teal); }
  .vg-technique-card h3 {
    font-family: 'Cormorant Garamond', serif;
    font-size: 1.2rem;
    font-weight: 400;
    color: var(--ink);
    margin-bottom: 0.4rem;
  }
  .vg-technique-card .vg-abbr {
    font-family: 'DM Mono', monospace;
    font-size: 0.68rem;
    color: var(--muted);
    letter-spacing: 0.1em;
    margin-bottom: 0.75rem;
    display: block;
  }
  .vg-technique-card p {
    font-size: 0.82rem;
    line-height: 1.7;
    color: var(--charcoal);
    margin-bottom: 0.75rem !important;
  }
  .vg-technique-card .vg-weakness {
    font-size: 0.75rem;
    color: var(--muted);
    border-top: 0.5px solid var(--border);
    padding-top: 0.6rem;
    margin-top: 0.5rem;
    font-style: italic;
  }

  /* ── FORMULA BLOCK ── */
  .vg-formula {
    background: var(--ink);
    padding: 1.5rem 2rem;
    margin: 1.5rem 0;
    font-family: 'DM Mono', monospace;
    font-size: 0.9rem;
    color: var(--amber-light);
    letter-spacing: 0.04em;
    overflow-x: auto;
    white-space: nowrap;
  }
  .vg-formula .vg-formula-label {
    font-family: 'DM Sans', sans-serif;
    font-size: 0.65rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(247,244,239,0.3);
    margin-bottom: 0.5rem;
    display: block;
    white-space: normal;
  }

  /* ── STAT ROW ── */
  .vg-stat-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin: 2rem 0;
  }
  .vg-stat-box {
    background: var(--paper-dark);
    border: 0.5px solid var(--border);
    padding: 1.25rem;
    text-align: center;
  }
  .vg-stat-box .vg-stat-n {
    font-family: 'Cormorant Garamond', serif;
    font-size: 2.2rem;
    font-weight: 300;
    line-height: 1;
    color: var(--teal);
    letter-spacing: -0.02em;
  }
  .vg-stat-box .vg-stat-l {
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted);
    margin-top: 0.35rem;
  }

  /* ── COMPARISON TABLE ── */
  .vg-table-wrap { overflow-x: auto; margin: 1.5rem 0; }
  .vg-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.83rem;
  }
  .vg-table th {
    background: var(--ink);
    color: var(--paper);
    font-family: 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: 0.68rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    padding: 0.75rem 1rem;
    text-align: left;
  }
  .vg-table td {
    padding: 0.7rem 1rem;
    border-bottom: 0.5px solid var(--border);
    color: var(--charcoal);
    vertical-align: top;
    line-height: 1.55;
  }
  .vg-table tr:nth-child(even) td { background: var(--paper-dark); }
  .vg-table .vg-chip {
    display: inline-block;
    font-size: 0.65rem;
    letter-spacing: 0.08em;
    padding: 0.2rem 0.55rem;
    border-radius: 2px;
    font-weight: 400;
  }
  .vg-chip-green { background: var(--teal-muted); color: var(--teal); }
  .vg-chip-amber { background: var(--amber-muted); color: var(--amber); }
  .vg-chip-gray  { background: var(--paper-dark); color: var(--muted); border: 0.5px solid var(--border); }

  /* ── DIVIDER ── */
  .vg-divider {
    border: none;
    border-top: 0.5px solid var(--border);
    margin: 3rem 0;
  }

  /* ── KEY TAKEAWAYS ── */
  .vg-takeaways-section {
    background: var(--ink);
    padding: 4rem;
  }
  .vg-takeaways-section .vg-section-eyebrow {
    font-size: 0.68rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--amber-light);
    font-weight: 500;
    margin-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.6rem;
  }
  .vg-takeaways-section .vg-section-eyebrow::before {
    content: '';
    display: inline-block;
    width: 1.25rem; height: 1px;
    background: var(--amber-light);
  }
  .vg-takeaways-section h2 {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(1.6rem, 3vw, 2.4rem);
    font-weight: 300;
    color: var(--paper);
    margin-bottom: 2.5rem;
  }
  .vg-takeaways-section h2 em { font-style: italic; color: var(--amber-light); }
  .vg-takeaways-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.25rem;
  }
  .vg-takeaway-card {
    border: 0.5px solid rgba(247,244,239,0.12);
    padding: 1.5rem;
    position: relative;
  }
  .vg-takeaway-card::before {
    content: attr(data-num);
    font-family: 'Cormorant Garamond', serif;
    font-size: 3rem;
    font-weight: 300;
    color: rgba(250,199,117,0.15);
    position: absolute;
    top: 0.5rem; right: 1rem;
    line-height: 1;
  }
  .vg-takeaway-card h4 {
    font-family: 'Cormorant Garamond', serif;
    font-size: 1.1rem;
    font-weight: 400;
    color: var(--amber-light);
    margin-bottom: 0.5rem;
  }
  .vg-takeaway-card p {
    font-size: 0.82rem;
    line-height: 1.75;
    color: rgba(247,244,239,0.65);
    font-weight: 300;
  }

  /* ── INTERVIEW CHEAT SHEET ── */
  .vg-interview-section {
    background: var(--teal-muted);
    padding: 4rem;
  }
  .vg-interview-section .vg-section-eyebrow {
    font-size: 0.68rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--teal);
    font-weight: 500;
    margin-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.6rem;
  }
  .vg-interview-section .vg-section-eyebrow::before {
    content: '';
    display: inline-block;
    width: 1.25rem; height: 1px;
    background: var(--teal);
  }
  .vg-interview-section h2 {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(1.6rem, 3vw, 2.4rem);
    font-weight: 300;
    color: var(--ink);
    margin-bottom: 2.5rem;
  }
  .vg-interview-section h2 em { font-style: italic; color: var(--teal); }
  .vg-qa-list { display: flex; flex-direction: column; gap: 0; }
  .vg-qa-item {
    border-top: 0.5px solid rgba(14,14,14,0.12);
    padding: 1.5rem 0;
    display: grid;
    grid-template-columns: 1fr 1.4fr;
    gap: 2rem;
    align-items: start;
  }
  .vg-qa-item:last-child { border-bottom: 0.5px solid rgba(14,14,14,0.12); }
  .vg-qa-q {
    font-family: 'Cormorant Garamond', serif;
    font-size: 1.05rem;
    font-weight: 400;
    color: var(--ink);
    line-height: 1.4;
  }
  .vg-qa-q .vg-q-badge {
    font-family: 'DM Mono', monospace;
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    background: var(--teal);
    color: var(--paper);
    padding: 0.15rem 0.5rem;
    margin-bottom: 0.5rem;
    display: inline-block;
  }
  .vg-qa-a {
    font-size: 0.85rem;
    line-height: 1.75;
    color: var(--charcoal);
    font-weight: 300;
  }
  .vg-qa-a strong { color: var(--teal); font-weight: 500; }
  .vg-qa-a code {
    font-family: 'DM Mono', monospace;
    font-size: 0.78rem;
    background: rgba(14,14,14,0.07);
    padding: 0.1rem 0.35rem;
    color: var(--ink);
  }

  /* ── MEMORY PILLS ── */
  .vg-memory-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 0.75rem;
  }
  .vg-memory-pill {
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    padding: 0.3rem 0.85rem;
    background: var(--paper);
    border: 0.5px solid var(--border-strong);
    color: var(--charcoal);
    font-weight: 400;
  }
  .vg-memory-pill.teal { border-color: var(--teal); color: var(--teal); background: var(--teal-muted); }
  .vg-memory-pill.amber { border-color: var(--amber); color: var(--amber); background: var(--amber-muted); }

  /* ── FOOTER CTA ── */
  .vg-post-footer {
    background: var(--paper-dark);
    padding: 3rem 4rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 1.5rem;
    border-top: 0.5px solid var(--border);
  }
  .vg-post-footer p {
    font-size: 0.85rem;
    color: var(--muted);
    font-weight: 300;
  }
  .vg-post-footer p strong { color: var(--ink); font-weight: 400; }
  .vg-source-link {
    display: inline-block;
    padding: 0.65rem 1.75rem;
    background: var(--ink);
    color: var(--paper);
    font-size: 0.72rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    text-decoration: none;
    font-weight: 400;
    transition: background 0.2s;
  }
  .vg-source-link:hover { background: var(--teal); }

  /* ── SCROLL REVEAL ── */
  .vg-reveal {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.55s ease, transform 0.55s ease;
  }
  .vg-reveal.vg-visible { opacity: 1; transform: translateY(0); }
  .vg-d1 { transition-delay: 0.1s; }
  .vg-d2 { transition-delay: 0.2s; }
  .vg-d3 { transition-delay: 0.3s; }
</style>

<div class="vg-blog-wrap">

  <!-- HERO -->
  <div class="vg-post-hero">
    <div class="vg-post-hero-inner">
      <p class="vg-post-eyebrow">NLP · Machine Learning · Text Feature Engineering</p>
      <h1 class="vg-post-title">From Amazon Reviews to Numbers: A Hands-On Tour of <em>One-Hot, Bag of Words, and TF-IDF</em></h1>
      <div class="vg-post-meta">
        <p class="vg-meta-item">Corpus<span>128 real reviews</span></p>
        <p class="vg-meta-item">Techniques<span>OHE · BoW · TF-IDF</span></p>
        <p class="vg-meta-item">Stack<span>Python · sklearn · BeautifulSoup</span></p>
        <p class="vg-meta-item">Source<span>GitHub ↗</span></p>
      </div>
    </div>
  </div>

  <!-- INTRO BAND -->
  <div class="vg-intro-band">
    <p>How I took <strong>128 real Amazon product reviews</strong> and turned them into features a machine-learning model can actually chew on — and what I learned about where these classical techniques still shine in 2026.</p>
  </div>

  <!-- BODY -->
  <div class="vg-post-body">

    <!-- WHY CLASSICAL -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Context</p>
      <h2>Why bother with &#8220;classical&#8221; text features <em>at all?</em></h2>
      <p>If you have been anywhere near an LLM in the last two years, you have probably heard that &#8220;embeddings solved text.&#8221; They did — for a lot of problems. But if you are building a spam filter with 100k labelled examples, a BM25-powered search box, a cold-start classifier for a brand-new product line, or a compliance-audited system where a human needs to understand why the model fired — then Bag of Words and TF-IDF are still in the toolbox.</p>
      <p>They are <strong>fast, deterministic, interpretable,</strong> and an honest baseline you should always beat before reaching for a neural model.</p>
    </div>

    <hr class="vg-divider">

    <!-- DATA -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 1</p>
      <h2>Get real data — <em>not toy sentences</em></h2>
      <p>Every blog post on TF-IDF uses the same three cooked-up sentences about cats and dogs. I wanted the messiness of real user-generated content, so I wrote a BeautifulSoup scraper across ~20 popular ASINs — Echo Dots, AirPods Pro, Kindles, an Apple Watch, a Ninja blender, a PS5 controller, a Nespresso machine, and so on.</p>
      <div class="vg-stat-row">
        <div class="vg-stat-box vg-reveal vg-d1">
          <div class="vg-stat-n">128</div>
          <div class="vg-stat-l">Real Reviews</div>
        </div>
        <div class="vg-stat-box vg-reveal vg-d2">
          <div class="vg-stat-n">14</div>
          <div class="vg-stat-l">Products</div>
        </div>
        <div class="vg-stat-box vg-reveal vg-d3">
          <div class="vg-stat-n">3,461</div>
          <div class="vg-stat-l">Unique Tokens</div>
        </div>
      </div>
      <div class="vg-callout">
        <strong>Scraper gotchas:</strong> Set a real <code>User-Agent</code> header or Amazon returns a stripped page. Anchor on <code>[data-hook="review-body"]</code> inside <code>celwidget</code> blocks — not the <code>div[data-hook="review"]</code> wrapper on the dedicated reviews page. A few reviews came back in Spanish and Arabic — a lovely reminder that real data never matches the shape your slides promised.
      </div>
    </div>

    <hr class="vg-divider">

    <!-- CLEANING -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 2</p>
      <h2>Clean the text — <em>the boring part that matters most</em></h2>
      <p>A review like &#8220;I LOVE it!!! Sound is 🔥. Read more&#8221; is not something a counting-based model can work with. Each cleaning step kills a specific kind of noise:</p>
      <div class="vg-table-wrap">
        <table class="vg-table">
          <thead><tr><th>Step</th><th>What it kills</th><th>Why it matters</th></tr></thead>
          <tbody>
            <tr><td>Lowercase</td><td>LOVE vs love</td><td>Avoids vocabulary duplicates</td></tr>
            <tr><td>Drop &#8220;Read more&#8221;</td><td>Amazon truncation marker</td><td>Otherwise becomes one of the most frequent tokens</td></tr>
            <tr><td>Strip punctuation / digits</td><td>!!!, $199</td><td>They rarely help classical models</td></tr>
            <tr><td>Tokenize</td><td>—</td><td>Gives you units to count</td></tr>
            <tr><td>Remove stopwords</td><td>the, and, is</td><td>Appear in every document → no signal</td></tr>
            <tr><td>Lemmatize</td><td>speakers → speaker</td><td>Tightens the vocabulary</td></tr>
          </tbody>
        </table>
      </div>
      <p>After processing: <strong>11,138 tokens</strong> spanning a <strong>3,461-word vocabulary</strong>. Top words were exactly the product-review clichés you would expect — use, one, like, great, noise, sound, quality — a perfect sanity check.</p>
    </div>

    <hr class="vg-divider">

    <!-- THREE ENCODINGS -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 3</p>
      <h2>Three ways to turn text into <em>numbers</em></h2>
      <div class="vg-technique-grid">
        <div class="vg-technique-card ohe vg-reveal vg-d1">
          <h3>One-Hot Encoding</h3>
          <span class="vg-abbr">OHE · Binary presence</span>
          <p>For each review, build a binary vector over the whole vocabulary: 1 if the word appears, 0 otherwise. Simplest thing that works, easiest to explain to a non-technical stakeholder.</p>
          <p class="vg-weakness">⚠ Throws away frequency — &#8220;amazing&#8221; once and ten times look identical.</p>
        </div>
        <div class="vg-technique-card bow vg-reveal vg-d2">
          <h3>Bag of Words</h3>
          <span class="vg-abbr">BoW · CountVectorizer</span>
          <p>Same vector shape, but store actual counts. A review that hammers on &#8220;sound&#8221; three times ranks differently from one that drops the word once. Frequency-aware.</p>
          <p class="vg-weakness">⚠ Still order-blind — &#8220;not good, very bad&#8221; ≈ &#8220;good, not very bad&#8221;.</p>
        </div>
        <div class="vg-technique-card tfidf vg-reveal vg-d3">
          <h3>TF-IDF</h3>
          <span class="vg-abbr">TfidfVectorizer · The trick</span>
          <p>Take the BoW count and divide by how common the word is across the whole corpus. Generic words like &#8220;good&#8221; get pushed toward zero. Rare, distinctive words like &#8220;cancellation&#8221; stay loud.</p>
          <p class="vg-weakness">✓ Best signal for downstream classifiers.</p>
        </div>
      </div>
      <div class="vg-formula">
        <span class="vg-formula-label">TF-IDF Formula</span>
        tfidf(t, d) = tf(t, d) · log( N / (1 + df(t)) )
      </div>
      <p>In my corpus, the highest-IDF words were exactly the long-tail product features that appeared in just one review. The lowest-IDF words were the generic review vocabulary. That is the <strong>whole story of TF-IDF in one experiment.</strong></p>
    </div>

    <hr class="vg-divider">

    <!-- AHA MOMENT -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 4</p>
      <h2>The &#8220;aha&#8221; moment — <em>one review, three lenses</em></h2>
      <p>Encode the same review three times and print the top-weighted tokens:</p>
      <div class="vg-callout">
        <strong>OHE</strong> just lists every unique word in the review. No ranking.<br><br>
        <strong>BoW</strong> surfaces the most repeated words — almost always filler like <code>one</code>, <code>like</code>, <code>use</code>.<br><br>
        <strong>TF-IDF</strong> surfaces the words <em>this</em> review says that few others do. That is exactly what a downstream classifier wants to see.<br><br>
        Once you have seen this side-by-side even once, you stop reaching for plain BoW unless you have a very specific reason. (Naive Bayes is one — its underlying math prefers raw counts.)
      </div>
    </div>

    <hr class="vg-divider">

    <!-- SPARSITY -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 5</p>
      <h2>Sparsity — <em>the thing nobody warns you about</em></h2>
      <p>Every one of my three matrices came out <strong>~98.15% zero.</strong> That is normal — reviews are short, vocabularies are long, and most words do not appear in most documents. Two huge practical implications:</p>
      <div class="vg-callout">
        <strong>Never store these dense.</strong> A 1-million-document × 200k-vocab corpus is a 200-billion-cell matrix. It must live in CSR or equivalent compressed form.<br><br>
        <strong>Classical pipelines do not scale forever.</strong> Once you are in the tens-of-millions-of-documents range, even sparse storage becomes painful — which is one reason industry moved to dense embedding pipelines for web-scale retrieval.
      </div>
    </div>

    <hr class="vg-divider">

    <!-- CLASSIFIER -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 6</p>
      <h2>A mini sentiment classifier — <em>and a class imbalance lesson</em></h2>
      <p>4–5 star = positive, 1–2 star = negative, 3-star dropped. Two models per feature set: Logistic Regression with <code>class_weight="balanced"</code> and Multinomial Naive Bayes.</p>
      <p>Headline accuracy looks great — <strong>~97% on the test split.</strong> But the test split has 31 positives and 1 negative. The interesting metric is recall on the negative class, and with only five one-star reviews in the whole corpus, no model is going to learn that cleanly. Amazon surfaces highly-rated reviews first, so any pipeline that scrapes top-of-page reviews inherits the same lopsided distribution.</p>
      <div class="vg-callout">
        <strong>TF-IDF</strong> gives Logistic Regression a small, consistent edge by silencing filler words.<br><br>
        <strong>Naive Bayes</strong> prefers raw BoW counts — rescaling with IDF can actually hurt it.<br><br>
        <strong>Never trust a single accuracy number on imbalanced data.</strong> Always print per-class precision/recall.
      </div>
    </div>

    <hr class="vg-divider">

    <!-- WHERE IT BREAKS -->
    <div class="vg-step vg-reveal">
      <p class="vg-step-label">Step 7</p>
      <h2>Where these techniques break — <em>and where they still win</em></h2>
      <div class="vg-table-wrap">
        <table class="vg-table">
          <thead><tr><th>Scenario</th><th>BoW / TF-IDF</th><th>Embeddings</th></tr></thead>
          <tbody>
            <tr>
              <td>Semantic similarity<br><em style="font-size:0.78rem;color:var(--muted)">&#8220;audio excellent&#8221; vs &#8220;sound great&#8221;</em></td>
              <td><span class="vg-chip vg-chip-gray">Zero shared tokens → fails</span></td>
              <td><span class="vg-chip vg-chip-green">Maps synonyms close ✓</span></td>
            </tr>
            <tr>
              <td>Negation<br><em style="font-size:0.78rem;color:var(--muted)">&#8220;battery lasts&#8221; vs &#8220;battery dies&#8221;</em></td>
              <td><span class="vg-chip vg-chip-gray">Near-identical vectors → fails</span></td>
              <td><span class="vg-chip vg-chip-green">Directional context ✓</span></td>
            </tr>
            <tr>
              <td>Interpretability</td>
              <td><span class="vg-chip vg-chip-green">Each feature is a word ✓</span></td>
              <td><span class="vg-chip vg-chip-amber">1024-dim black box</span></td>
            </tr>
            <tr>
              <td>Training speed</td>
              <td><span class="vg-chip vg-chip-green">Millions of docs, minutes, laptop ✓</span></td>
              <td><span class="vg-chip vg-chip-amber">GPU required at scale</span></td>
            </tr>
            <tr>
              <td>Exact keyword / ID retrieval</td>
              <td><span class="vg-chip vg-chip-green">BM25 still wins ✓</span></td>
              <td><span class="vg-chip vg-chip-amber">Can miss rare tokens</span></td>
            </tr>
            <tr>
              <td>Cold start (zero labels)</td>
              <td><span class="vg-chip vg-chip-green">Cosine sim on day one ✓</span></td>
              <td><span class="vg-chip vg-chip-amber">Needs fine-tuning data</span></td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

  </div><!-- /vg-post-body -->

  <!-- KEY TAKEAWAYS -->
  <div class="vg-takeaways-section">
    <p class="vg-section-eyebrow">Summary</p>
    <h2>Key <em>takeaways</em></h2>
    <div class="vg-takeaways-grid">
      <div class="vg-takeaway-card vg-reveal" data-num="01">
        <h4>Preprocessing is 80% of the game</h4>
        <p>Before you touch any encoder, understand exactly what &#8220;a token&#8221; means in your corpus. Lowercase, stopwords, lemmatization — each step has a specific purpose.</p>
      </div>
      <div class="vg-takeaway-card vg-reveal vg-d1" data-num="02">
        <h4>Always inspect a single document&#8217;s top features</h4>
        <p>It is the fastest way to develop intuition about what your encoding is actually rewarding. Print OHE vs BoW vs TF-IDF side-by-side at least once.</p>
      </div>
      <div class="vg-takeaway-card vg-reveal vg-d2" data-num="03">
        <h4>Watch sparsity and class imbalance</h4>
        <p>Both will bite you long before modelling choices do. Use CSR storage. Never trust a single accuracy number on skewed data — always check per-class recall.</p>
      </div>
      <div class="vg-takeaway-card vg-reveal vg-d3" data-num="04">
        <h4>Know why you would pick the classical tool</h4>
        <p>If your answer is only &#8220;because it is in every tutorial&#8221;, reach for an embedding model. If your answer is &#8220;interpretability and speed&#8221; — BoW/TF-IDF are still excellent choices.</p>
      </div>
    </div>
  </div>

  <!-- INTERVIEW CHEAT SHEET -->
  <div class="vg-interview-section">
    <p class="vg-section-eyebrow">Interview Prep</p>
    <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
    <div class="vg-qa-list">

      <div class="vg-qa-item vg-reveal">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Define</span><br>
          What is One-Hot Encoding in NLP?
        </div>
        <div class="vg-qa-a">
          <strong>Binary presence vector</strong> over the vocabulary. 1 if the word appears in the document, 0 otherwise. No frequency, no order. Size = vocabulary length.
          <div class="vg-memory-row">
            <span class="vg-memory-pill">Binary: 0 or 1</span>
            <span class="vg-memory-pill">Ignores frequency</span>
            <span class="vg-memory-pill amber">Simplest encoder</span>
          </div>
        </div>
      </div>

      <div class="vg-qa-item vg-reveal vg-d1">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Define</span><br>
          What is Bag of Words?
        </div>
        <div class="vg-qa-a">
          <strong>Word count vector</strong> over the vocabulary. Stores how many times each word appears. Frequency-aware but order-blind — treats a document as an unordered bag of tokens.
          <div class="vg-memory-row">
            <span class="vg-memory-pill">Counts, not binary</span>
            <span class="vg-memory-pill">Order-blind</span>
            <span class="vg-memory-pill amber">CountVectorizer in sklearn</span>
          </div>
        </div>
      </div>

      <div class="vg-qa-item vg-reveal vg-d2">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Define</span><br>
          What is TF-IDF and why does it outperform BoW?
        </div>
        <div class="vg-qa-a">
          <strong>Term Frequency × Inverse Document Frequency.</strong> Scales BoW counts down for words that appear in many documents. Words like &#8220;good&#8221; that are everywhere get suppressed; rare words that are distinctive get amplified. Formula: <code>tf(t,d) · log(N / (1 + df(t)))</code>
          <div class="vg-memory-row">
            <span class="vg-memory-pill teal">Rewards rarity</span>
            <span class="vg-memory-pill teal">Penalises ubiquity</span>
            <span class="vg-memory-pill">TfidfVectorizer</span>
          </div>
        </div>
      </div>

      <div class="vg-qa-item vg-reveal">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Compare</span><br>
          When would you use BoW over TF-IDF?
        </div>
        <div class="vg-qa-a">
          Use raw BoW counts with <strong>Naive Bayes</strong> — its probability estimates are count-based; IDF rescaling can hurt it. Otherwise, TF-IDF almost always gives a better signal for classifiers.
          <div class="vg-memory-row">
            <span class="vg-memory-pill amber">Naive Bayes → BoW</span>
            <span class="vg-memory-pill teal">Logistic Regression → TF-IDF</span>
          </div>
        </div>
      </div>

      <div class="vg-qa-item vg-reveal vg-d1">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Gotcha</span><br>
          What is sparsity and why does it matter?
        </div>
        <div class="vg-qa-a">
          A BoW/TF-IDF matrix is typically <strong>95–99% zeros</strong> because documents are short and vocabularies are large. Always store in <strong>sparse format (CSR)</strong> — a dense matrix of 1M docs × 200k vocab = 200B cells, which won&#8217;t fit in RAM.
          <div class="vg-memory-row">
            <span class="vg-memory-pill">98% zeros = normal</span>
            <span class="vg-memory-pill amber">Always use CSR format</span>
          </div>
        </div>
      </div>

      <div class="vg-qa-item vg-reveal vg-d2">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Weakness</span><br>
          What can&#8217;t BoW/TF-IDF do that embeddings can?
        </div>
        <div class="vg-qa-a">
          They are <strong>lexical, not semantic.</strong> &#8220;Audio is excellent&#8221; and &#8220;sound is great&#8221; share zero tokens → zero similarity. &#8220;Battery lasts&#8221; and &#8220;battery dies&#8221; share most tokens → high similarity. Embeddings fix both by mapping meaning, not just words.
          <div class="vg-memory-row">
            <span class="vg-memory-pill">No synonyms</span>
            <span class="vg-memory-pill">No negation</span>
            <span class="vg-memory-pill teal">Use embeddings for semantics</span>
          </div>
        </div>
      </div>

      <div class="vg-qa-item vg-reveal">
        <div class="vg-qa-q">
          <span class="vg-q-badge">Use Case</span><br>
          When do classical methods still win in 2026?
        </div>
        <div class="vg-qa-a">
          <strong>4 scenarios where BoW/TF-IDF beat neural alternatives:</strong> (1) exact-match / keyword search — BM25 still outperforms embeddings for identifier queries; (2) interpretability requirements; (3) training speed at millions of documents on a laptop; (4) cold-start with zero labelled data.
          <div class="vg-memory-row">
            <span class="vg-memory-pill teal">BM25 search</span>
            <span class="vg-memory-pill teal">Interpretability</span>
            <span class="vg-memory-pill teal">Cold start</span>
            <span class="vg-memory-pill teal">Speed</span>
          </div>
        </div>
      </div>

    </div>
  </div>

  <!-- FOOTER CTA -->
  <div class="vg-post-footer">
    <p>Full pipeline — scraper to classifier — in the <strong>GenAI Mastery Series</strong> source repo.</p>
    <a href="https://github.com/vijaygokarn130/ml-classic-concepts" class="vg-source-link" target="_blank">View Source on GitHub ↗</a>
  </div>

</div><!-- /vg-blog-wrap -->

<script>
(function(){
  var obs = new IntersectionObserver(function(entries){
    entries.forEach(function(e){ if(e.isIntersecting) e.target.classList.add('vg-visible'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>
<p>The post <a href="https://vijay-gokarn.com/from-amazon-reviews-to-numbers-a-hands-on-tour-of-one-hot-bag-of-words-and-tf-idf/">From Amazon Reviews to Numbers: A Hands-On Tour of One-Hot, Bag of Words, and TF-IDF</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">263</post-id>	</item>
		<item>
		<title>The GenAI Landscape: From Zero to Transformer Series name: GenAI Mastery Series — Chapter 02</title>
		<link>https://vijay-gokarn.com/the-genai-landscape-from-zero-to-transformer-series-name-genai-mastery-series-chapter-02/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-genai-landscape-from-zero-to-transformer-series-name-genai-mastery-series-chapter-02</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Sun, 29 Mar 2026 14:48:39 +0000</pubDate>
				<category><![CDATA[generative-ai]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=236</guid>

					<description><![CDATA[<p>GenAI Mastery Series · Chapter 02 · March 28, 2026 Coding Assistants, the AI/ML Roadmap, and How Machines Learn to Understand Language Read~14 min SessionMarch 28, 2026 TopicsNLP · Embeddings · Transformers · Tools Three Pillars AI Coding Assistants AI/ML Family Tree RNN → Transformer Encoding &#038; Embeddings GenAI Tool Stack Career Paths Build Path [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/the-genai-landscape-from-zero-to-transformer-series-name-genai-mastery-series-chapter-02/">The GenAI Landscape: From Zero to Transformer Series name: GenAI Mastery Series — Chapter 02</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg2 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  font-family: 'DM Sans', sans-serif;
  font-weight: 300; color: var(--ink);
  background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg2 *, .vg2 *::before, .vg2 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg2-hero {
  background: var(--ink); padding: 5rem 4rem 4rem; position: relative; overflow: hidden;
}
.vg2-hero::before {
  content: '02'; font-family: 'Cormorant Garamond', serif; font-size: 20rem;
  font-weight: 300; color: rgba(255,255,255,0.03); position: absolute;
  right: -2rem; bottom: -4rem; line-height: 1; letter-spacing: -0.05em; pointer-events: none;
}
.vg2-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg2-eyebrow {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.vg2-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg2-hero h1 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem);
  font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em;
  margin-bottom: 1.5rem; max-width: 28ch;
}
.vg2-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg2-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; margin-bottom: 2rem; }
.vg2-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg2-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }
.vg2-toc {
  display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 2rem;
  border-top: 0.5px solid rgba(247,244,239,0.1); padding-top: 1.5rem;
}
.vg2-toc-item {
  font-size: 0.68rem; letter-spacing: 0.06em; padding: 0.3rem 0.85rem;
  border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); font-weight: 300;
}

/* INTRO BAND */
.vg2-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg2-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg2-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg2-body { max-width: 900px; margin: 0 auto; padding: 4rem; }

/* SECTION */
.vg2-section { margin-bottom: 3.5rem; }
.vg2-section-label {
  font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal); font-weight: 500; margin-bottom: 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.vg2-section-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg2-section h2 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1.25rem;
}
.vg2-section h2 em { font-style: italic; color: var(--teal); }
.vg2-section p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg2-section p strong { color: var(--ink); font-weight: 500; }
.vg2-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg2-callout {
  background: var(--paper-dark); border-left: 3px solid var(--amber);
  padding: 1.25rem 1.5rem; margin: 1.5rem 0;
  font-size: 0.87rem; line-height: 1.8; color: var(--charcoal);
}
.vg2-callout strong { color: var(--amber); font-weight: 500; }
.vg2-callout.teal { border-color: var(--teal); }
.vg2-callout.teal strong { color: var(--teal); }
.vg2-callout code { font-family: 'DM Mono', monospace; font-size: 0.8rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.4rem; }

/* TABLES */
.vg2-table-wrap { overflow-x: auto; margin: 1.5rem 0; }
.vg2-table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
.vg2-table th {
  background: var(--ink); color: var(--paper); font-family: 'DM Sans', sans-serif;
  font-weight: 400; font-size: 0.65rem; letter-spacing: 0.14em;
  text-transform: uppercase; padding: 0.75rem 1rem; text-align: left;
}
.vg2-table td { padding: 0.75rem 1rem; border-bottom: 0.5px solid var(--border); color: var(--charcoal); vertical-align: top; line-height: 1.55; }
.vg2-table tr:nth-child(even) td { background: var(--paper-dark); }
.vg2-table td strong { color: var(--ink); font-weight: 500; }
.vg2-table td em { color: var(--muted); font-style: italic; font-size: 0.8rem; }

/* PILLAR CARDS */
.vg2-pillar-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--border); border: 0.5px solid var(--border); margin: 1.5rem 0; }
.vg2-pillar {
  background: var(--paper); padding: 1.75rem 1.5rem; position: relative;
}
.vg2-pillar::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; }
.vg2-pillar:nth-child(1)::before { background: var(--muted); }
.vg2-pillar:nth-child(2)::before { background: var(--amber); }
.vg2-pillar:nth-child(3)::before { background: var(--teal); }
.vg2-pillar-num { font-family: 'Cormorant Garamond', serif; font-size: 2.5rem; font-weight: 300; color: var(--border-strong); line-height: 1; margin-bottom: 0.5rem; letter-spacing: -0.03em; }
.vg2-pillar h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.15rem; font-weight: 400; color: var(--ink); margin-bottom: 0.4rem; }
.vg2-pillar .vg2-pillar-sub { font-size: 0.7rem; letter-spacing: 0.08em; color: var(--muted); margin-bottom: 0.75rem; text-transform: uppercase; }
.vg2-pillar p { font-size: 0.8rem; line-height: 1.65; color: var(--charcoal); font-weight: 300; }

/* TOOL CARDS */
.vg2-tool-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin: 1.5rem 0; }
.vg2-tool-card { background: var(--paper); border: 0.5px solid var(--border-strong); padding: 1.25rem 1.5rem; display: flex; gap: 1rem; align-items: flex-start; }
.vg2-tool-num { font-family: 'DM Mono', monospace; font-size: 0.7rem; color: var(--teal); min-width: 1.5rem; margin-top: 0.15rem; }
.vg2-tool-body h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.1rem; font-weight: 400; color: var(--ink); margin-bottom: 0.3rem; }
.vg2-tool-body p { font-size: 0.79rem; line-height: 1.65; color: var(--charcoal); font-weight: 300; }

/* EVOLUTION TIMELINE */
.vg2-timeline { display: flex; flex-direction: column; gap: 0; margin: 1.5rem 0; }
.vg2-evo-item { display: grid; grid-template-columns: 110px 1fr; gap: 1.5rem; padding: 1.5rem 0; border-top: 0.5px solid var(--border); align-items: start; }
.vg2-evo-item:last-child { border-bottom: 0.5px solid var(--border); }
.vg2-evo-era { font-family: 'DM Mono', monospace; font-size: 0.7rem; color: var(--muted); letter-spacing: 0.05em; line-height: 1.5; }
.vg2-evo-label { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.35rem; }
.vg2-evo-body h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.15rem; font-weight: 400; color: var(--ink); margin-bottom: 0.35rem; }
.vg2-evo-body p { font-size: 0.82rem; line-height: 1.75; color: var(--charcoal); font-weight: 300; }
.vg2-evo-body p strong { color: var(--ink); font-weight: 500; }

/* ENCODING VS EMBEDDING */
.vg2-compare-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin: 1.5rem 0; }
.vg2-compare-card { border: 0.5px solid var(--border-strong); padding: 1.75rem; position: relative; }
.vg2-compare-card.encoding::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: var(--muted); }
.vg2-compare-card.embedding::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: var(--teal); }
.vg2-compare-card h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.25rem; font-weight: 400; color: var(--ink); margin-bottom: 0.3rem; }
.vg2-compare-card .vg2-compare-sub { font-size: 0.65rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin-bottom: 1rem; display: block; }
.vg2-compare-card ul { list-style: none; display: flex; flex-direction: column; gap: 0.6rem; }
.vg2-compare-card ul li { font-size: 0.82rem; line-height: 1.6; color: var(--charcoal); font-weight: 300; padding-left: 1rem; position: relative; }
.vg2-compare-card ul li::before { content: '—'; position: absolute; left: 0; color: var(--border-strong); }
.vg2-compare-card.embedding ul li::before { color: var(--teal); }

/* FORMULA */
.vg2-formula { background: var(--ink); padding: 1.5rem 2rem; margin: 1.5rem 0; overflow-x: auto; }
.vg2-formula-label { font-family: 'DM Sans', sans-serif; font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.5rem; display: block; }
.vg2-formula code { font-family: 'DM Mono', monospace; font-size: 0.88rem; color: var(--amber-light); white-space: nowrap; }

/* CAREER PATH */
.vg2-career-section { background: var(--charcoal); padding: 4rem; }
.vg2-career-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg2-career-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg2-career-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg2-career-section h2 em { font-style: italic; color: var(--amber-light); }
.vg2-ladder { display: flex; align-items: center; gap: 0; flex-wrap: wrap; margin-bottom: 2.5rem; }
.vg2-ladder-step { background: rgba(247,244,239,0.06); border: 0.5px solid rgba(247,244,239,0.12); padding: 0.75rem 1.1rem; }
.vg2-ladder-step span { font-size: 0.72rem; letter-spacing: 0.06em; color: rgba(247,244,239,0.6); display: block; }
.vg2-ladder-step strong { font-size: 0.82rem; color: var(--paper); font-weight: 400; }
.vg2-ladder-arrow { font-size: 0.7rem; color: rgba(247,244,239,0.2); padding: 0 0.4rem; }
.vg2-roles-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.vg2-role-card { border: 0.5px solid rgba(247,244,239,0.1); padding: 1.25rem; }
.vg2-role-card h4 { font-family: 'Cormorant Garamond', serif; font-size: 1rem; font-weight: 400; color: var(--amber-light); margin-bottom: 0.4rem; }
.vg2-role-card p { font-size: 0.78rem; line-height: 1.65; color: rgba(247,244,239,0.55); font-weight: 300; }

/* BUILD PATH */
.vg2-build-section { background: var(--teal-muted); padding: 4rem; }
.vg2-build-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg2-build-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg2-build-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2rem; }
.vg2-build-section h2 em { font-style: italic; color: var(--teal); }
.vg2-stages { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: rgba(14,14,14,0.1); border: 0.5px solid rgba(14,14,14,0.1); margin-bottom: 2rem; }
.vg2-stage { background: var(--paper); padding: 1.5rem 1.25rem; }
.vg2-stage-num { font-family: 'Cormorant Garamond', serif; font-size: 2rem; font-weight: 300; color: var(--teal-light); line-height: 1; margin-bottom: 0.5rem; opacity: 0.5; }
.vg2-stage h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--ink); margin-bottom: 0.4rem; }
.vg2-stage p { font-size: 0.78rem; line-height: 1.65; color: var(--charcoal); font-weight: 300; }
.vg2-poc-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: rgba(14,14,14,0.1); border: 0.5px solid rgba(14,14,14,0.1); }
.vg2-poc-phase { background: var(--paper); padding: 1.25rem 1rem; }
.vg2-poc-phase .vg2-phase-tag { font-family: 'DM Mono', monospace; font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--teal); margin-bottom: 0.5rem; display: block; }
.vg2-poc-phase h5 { font-family: 'Cormorant Garamond', serif; font-size: 1rem; font-weight: 400; color: var(--ink); margin-bottom: 0.3rem; }
.vg2-poc-phase p { font-size: 0.75rem; line-height: 1.6; color: var(--charcoal); font-weight: 300; }

/* INTERVIEW / CHEAT SHEET */
.vg2-interview-section { background: var(--ink); padding: 4rem; }
.vg2-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg2-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg2-interview-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg2-interview-section h2 em { font-style: italic; color: var(--amber-light); }
.vg2-qa-list { display: flex; flex-direction: column; gap: 0; }
.vg2-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(247,244,239,0.1); align-items: start; }
.vg2-qa-item:last-child { border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg2-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--paper); line-height: 1.4; }
.vg2-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg2-qa-a { font-size: 0.83rem; line-height: 1.8; color: rgba(247,244,239,0.65); font-weight: 300; }
.vg2-qa-a strong { color: var(--amber-light); font-weight: 400; }
.vg2-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(247,244,239,0.08); padding: 0.1rem 0.35rem; color: var(--paper); }
.vg2-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg2-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); font-weight: 300; }
.vg2-pill.t { border-color: var(--teal-light); color: var(--teal-light); }
.vg2-pill.a { border-color: var(--amber-light); color: var(--amber-light); }

/* CHECKLIST */
.vg2-checklist-section { background: var(--paper-dark); padding: 4rem; }
.vg2-checklist-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg2-checklist-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg2-checklist-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.2rem); font-weight: 300; color: var(--ink); margin-bottom: 2rem; }
.vg2-checklist-section h2 em { font-style: italic; color: var(--teal); }
.vg2-checklist { display: flex; flex-direction: column; gap: 0; }
.vg2-check-item { display: flex; gap: 1.25rem; align-items: flex-start; padding: 1.25rem 0; border-top: 0.5px solid var(--border); }
.vg2-check-item:last-child { border-bottom: 0.5px solid var(--border); }
.vg2-check-box { width: 20px; height: 20px; border: 1.5px solid var(--teal); flex-shrink: 0; margin-top: 0.15rem; }
.vg2-check-body h4 { font-size: 0.88rem; font-weight: 500; color: var(--ink); margin-bottom: 0.2rem; }
.vg2-check-body p { font-size: 0.8rem; line-height: 1.65; color: var(--muted); font-weight: 300; }

/* FOOTER */
.vg2-footer { background: var(--ink); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; border-top: 0.5px solid rgba(247,244,239,0.08); }
.vg2-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg2-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg2-next-btn { display: inline-block; padding: 0.65rem 1.75rem; background: var(--teal); color: var(--paper); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }

/* REVEAL */
.vg2-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg2-reveal.vg2-vis { opacity: 1; transform: translateY(0); }
.vg2-d1 { transition-delay: 0.1s; } .vg2-d2 { transition-delay: 0.2s; } .vg2-d3 { transition-delay: 0.3s; }
</style>

<div class="vg2">

<!-- HERO -->
<div class="vg2-hero">
  <div class="vg2-hero-inner">
    <p class="vg2-eyebrow">GenAI Mastery Series · Chapter 02 · March 28, 2026</p>
    <h1>Coding Assistants, the AI/ML Roadmap, and How Machines Learn to <em>Understand Language</em></h1>
    <div class="vg2-meta-row">
      <p class="vg2-meta">Read<span>~14 min</span></p>
      <p class="vg2-meta">Session<span>March 28, 2026</span></p>
      <p class="vg2-meta">Topics<span>NLP · Embeddings · Transformers · Tools</span></p>
    </div>
    <div class="vg2-toc">
      <span class="vg2-toc-item">Three Pillars</span>
      <span class="vg2-toc-item">AI Coding Assistants</span>
      <span class="vg2-toc-item">AI/ML Family Tree</span>
      <span class="vg2-toc-item">RNN → Transformer</span>
      <span class="vg2-toc-item">Encoding &#038; Embeddings</span>
      <span class="vg2-toc-item">GenAI Tool Stack</span>
      <span class="vg2-toc-item">Career Paths</span>
      <span class="vg2-toc-item">Build Path</span>
      <span class="vg2-toc-item">Interview Prep</span>
    </div>
  </div>
</div>

<!-- INTRO BAND -->
<div class="vg2-intro">
  <p>If you&#8217;ve ever wondered what it actually takes to go from <strong>&#8220;I know some Python&#8221;</strong> to <strong>&#8220;I build AI-powered applications for a living&#8221;</strong> — this chapter maps out the entire journey. From the complete AI/ML family tree to the fundamental concept that makes all of modern NLP possible: teaching machines to understand the meaning of words.</p>
</div>

<!-- BODY -->
<div class="vg2-body">

  <!-- THREE PILLARS -->
  <div class="vg2-section vg2-reveal">
    <p class="vg2-section-label">Foundation</p>
    <h2>The three <em>pillars</em> of this course</h2>
    <p>Before diving into any specific technology, understand the structure. This course is built on three pillars, each supporting the next. Think of it as a building: Python is the foundation, ML/DL is the structure, and GenAI is the penthouse. <strong>You can&#8217;t skip floors.</strong></p>
    <div class="vg2-pillar-grid">
      <div class="vg2-pillar vg2-reveal vg2-d1">
        <div class="vg2-pillar-num">01</div>
        <h3>Python App Dev</h3>
        <p class="vg2-pillar-sub">The Foundation</p>
        <p>Building real applications, Git, VS Code, practical coding. You need hands that can build things before you can build AI things.</p>
      </div>
      <div class="vg2-pillar vg2-reveal vg2-d2">
        <div class="vg2-pillar-num">02</div>
        <h3>ML / DL / NLP / CV</h3>
        <p class="vg2-pillar-sub">The Structure</p>
        <p>Classical ML, deep learning, NLP, and computer vision theory. The brain — the conceptual foundation everything else sits on.</p>
      </div>
      <div class="vg2-pillar vg2-reveal vg2-d3">
        <div class="vg2-pillar-num">03</div>
        <h3>Generative AI</h3>
        <p class="vg2-pillar-sub">The Destination</p>
        <p>Transformers, LLMs, RAG, fine-tuning, agents, LLMOps. Where the industry is heading and where the jobs are.</p>
      </div>
    </div>
    <div class="vg2-callout teal">
      <strong>Practical Takeaway:</strong> You don&#8217;t need to master classical ML before touching GenAI, but you do need to be comfortable with Python and understand the basics of how models learn. Run all three tracks in parallel — build all three muscles simultaneously.
    </div>
  </div>

  <hr class="vg2-divider">

  <!-- CODING ASSISTANTS -->
  <div class="vg2-section vg2-reveal">
    <p class="vg2-section-label">Tooling</p>
    <h2>AI coding assistants — <em>your new pair programmer</em></h2>
    <p>In 2026, writing code without an AI assistant is like writing a document without spell-check. The industry has standardized around a few key tools.</p>
    <div class="vg2-tool-grid">
      <div class="vg2-tool-card vg2-reveal vg2-d1">
        <span class="vg2-tool-num">01</span>
        <div class="vg2-tool-body">
          <h4>GitHub Copilot</h4>
          <p>Most widely adopted. Built into VS Code and PyCharm. Free tier includes GPT-4.1, GPT-4o, GPT-4.5. Paid tier ($10/mo) unlocks Opus-6.5 and GPT-5.3 for complex reasoning and multi-file tasks.</p>
        </div>
      </div>
      <div class="vg2-tool-card vg2-reveal vg2-d2">
        <span class="vg2-tool-num">02</span>
        <div class="vg2-tool-body">
          <h4>Claude Code</h4>
          <p>Anthropic&#8217;s coding assistant integrated directly with VS Code. Strong performance on code understanding and generation, especially for complex reasoning tasks.</p>
        </div>
      </div>
      <div class="vg2-tool-card vg2-reveal vg2-d1">
        <span class="vg2-tool-num">03</span>
        <div class="vg2-tool-body">
          <h4>OpenAI Codex</h4>
          <p>OpenAI&#8217;s dedicated code generation engine. Less of a daily-driver IDE plugin; powers many code-generation features across the ecosystem.</p>
        </div>
      </div>
      <div class="vg2-tool-card vg2-reveal vg2-d2">
        <span class="vg2-tool-num">04</span>
        <div class="vg2-tool-body">
          <h4>Cursor / Anysphere</h4>
          <p>AI-native code editors that rethink the entire IDE experience rather than adding AI as a plugin. Worth experimenting with as you advance.</p>
        </div>
      </div>
    </div>
    <div class="vg2-callout">
      <strong>Recommended Setup:</strong> Start with VS Code + GitHub Copilot free tier — covers 90% of what you&#8217;ll need. Experiment with Claude Code for strong reasoning. Upgrade Copilot only when free models aren&#8217;t keeping up.
    </div>
  </div>

  <hr class="vg2-divider">

  <!-- AI/ML FAMILY TREE -->
  <div class="vg2-section vg2-reveal">
    <p class="vg2-section-label">Big Picture</p>
    <h2>The complete <em>AI/ML family tree</em></h2>
    <p>At the highest level, AI splits into three research branches — each with its own tools, techniques, and career paths.</p>
    <div class="vg2-table-wrap">
      <table class="vg2-table">
        <thead><tr><th>Branch</th><th>Core Libraries</th><th>Specializations</th><th>Best For</th></tr></thead>
        <tbody>
          <tr>
            <td><strong>Machine Learning</strong></td>
            <td>Pandas, NumPy, Scikit-learn</td>
            <td>Decision Trees, SVMs, Ensemble Methods, EDA, Feature Engineering</td>
            <td>Structured tabular data, classical classification/regression</td>
          </tr>
          <tr>
            <td><strong>Deep Learning</strong></td>
            <td>PyTorch, TensorFlow, Keras</td>
            <td>CNNs (Vision), RNNs (Sequences), GANs (Synthesis), DRL (Agents)</td>
            <td>Images, text, audio, generative models</td>
          </tr>
          <tr>
            <td><strong>Reinforcement Learning</strong></td>
            <td>Stable Baselines, Ray RLlib</td>
            <td>Q-Learning, PPO, RLHF (LLM fine-tuning)</td>
            <td>Games, robotics, LLM alignment</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>

  <hr class="vg2-divider">

  <!-- RNN TO TRANSFORMER -->
  <div class="vg2-section vg2-reveal">
    <p class="vg2-section-label">NLP History</p>
    <h2>From RNNs to Transformers — <em>the five-step revolution</em></h2>
    <p>This is the story that matters most for understanding GenAI. A story of limitations breeding innovation. Understanding this progression is <strong>non-negotiable for anyone working in GenAI</strong> — it explains why modern architectures are designed the way they are.</p>
    <div class="vg2-timeline">
      <div class="vg2-evo-item vg2-reveal">
        <div class="vg2-evo-era">~2014–2016</div>
        <div class="vg2-evo-body">
          <p class="vg2-evo-label">Step 01</p>
          <h4>RNNs — Sequential Processing</h4>
          <p>Processed text one word at a time, passing a hidden state forward. Could handle sequences but <strong>struggled badly with long-range dependencies</strong> — by the end of a long paragraph, the model had largely forgotten the beginning.</p>
        </div>
      </div>
      <div class="vg2-evo-item vg2-reveal vg2-d1">
        <div class="vg2-evo-era">~2018–2019</div>
        <div class="vg2-evo-body">
          <p class="vg2-evo-label">Step 02</p>
          <h4>LSTM &#038; GRU — Memory Gates</h4>
          <p>Added memory gates that could selectively remember and forget. Solved the <strong>vanishing gradient problem</strong>, but processing was still painfully sequential — you couldn&#8217;t parallelize training effectively.</p>
        </div>
      </div>
      <div class="vg2-evo-item vg2-reveal vg2-d2">
        <div class="vg2-evo-era">~2014–2016</div>
        <div class="vg2-evo-body">
          <p class="vg2-evo-label">Step 03</p>
          <h4>Encoder-Decoder — The Context Vector</h4>
          <p>Compress the entire input into a <strong>fixed-size numerical representation</strong> (the context vector), then decode that into output. This is what made machine translation actually work.</p>
        </div>
      </div>
      <div class="vg2-evo-item vg2-reveal">
        <div class="vg2-evo-era">2017</div>
        <div class="vg2-evo-body">
          <p class="vg2-evo-label">Step 04 — The Breakthrough</p>
          <h4>Transformers — &#8220;Attention Is All You Need&#8221;</h4>
          <p>Removed the sequential bottleneck entirely. Instead of reading one word at a time, transformers <strong>process all words simultaneously</strong> using self-attention — every word in a sentence directly attends to every other word.</p>
        </div>
      </div>
      <div class="vg2-evo-item vg2-reveal vg2-d1">
        <div class="vg2-evo-era">2020–Today</div>
        <div class="vg2-evo-body">
          <p class="vg2-evo-label">Step 05 — Where We Are</p>
          <h4>LLMs, SLMs &#038; Multimodal LLMs</h4>
          <p>Scale the transformer to <strong>billions of parameters</strong>, train on internet-scale data, and you get GPT-4, Claude, Llama, and their peers. SLMs run on-device; Multimodal LLMs understand text, images, audio, and more.</p>
        </div>
      </div>
    </div>
  </div>

  <hr class="vg2-divider">

  <!-- ENCODING & EMBEDDINGS -->
  <div class="vg2-section vg2-reveal">
    <p class="vg2-section-label">Core Concept</p>
    <h2>Encoding, embeddings &#038; tokenization — <em>making machines read</em></h2>
    <p>This is arguably the single most important concept in all of NLP. Computers understand numbers. Humans understand words. Encoding and embedding are the bridge — and how well you build that bridge determines how well your AI understands language.</p>

    <div class="vg2-callout teal">
      <strong>The Pipeline — when you type into an LLM:</strong><br><br>
      <strong>1. Tokenize</strong> — Break sentence into pieces. &#8220;unbelievable&#8221; → [&#8220;un&#8221;, &#8220;believ&#8221;, &#8220;able&#8221;] (BPE / WordPiece / SentencePiece)<br><br>
      <strong>2. Encode</strong> — Map each token to a numerical ID from a vocabulary table. &#8220;cat&#8221; = 4523. Arbitrary — carries no meaning.<br><br>
      <strong>3. Embed</strong> — Map each ID to a <em>dense learned vector</em>. Now &#8220;cat&#8221; is [0.23, -0.51, 0.87, …] — a point in high-dimensional space where similar concepts cluster together.
    </div>

    <div class="vg2-compare-grid">
      <div class="vg2-compare-card encoding vg2-reveal vg2-d1">
        <h3>Encoding</h3>
        <span class="vg2-compare-sub">Arbitrary integer mapping</span>
        <ul>
          <li>Assigns a random number to each token</li>
          <li>&#8220;king&#8221; = 42, &#8220;queen&#8221; = 7891 — look completely unrelated</li>
          <li>Single integer output</li>
          <li>Static lookup table — not trained</li>
          <li>Analogy: giving every student a random ID badge number</li>
          <li>Does not capture meaning</li>
        </ul>
      </div>
      <div class="vg2-compare-card embedding vg2-reveal vg2-d2">
        <h3>Embedding</h3>
        <span class="vg2-compare-sub">Learned dense vector</span>
        <ul>
          <li>Assigns a meaningful vector trained by a neural network</li>
          <li>&#8220;king&#8221; and &#8220;queen&#8221; end up near each other in vector space</li>
          <li>768 to 4096+ dimension vector output</li>
          <li>Trained — learned from data</li>
          <li>Analogy: placing students on a campus map by major, interests, and friend group</li>
          <li>Captures semantic meaning ✓</li>
        </ul>
      </div>
    </div>

    <p>Once you have good embeddings, entirely new capabilities emerge. <strong>Semantic search</strong> becomes possible — instead of matching keywords, you match meaning. A search for &#8220;I&#8217;m hungry and want something cheesy&#8221; can return results about pizza even if the word &#8220;pizza&#8221; never appears in the query.</p>
  </div>

  <hr class="vg2-divider">

  <!-- TOOL STACK -->
  <div class="vg2-section vg2-reveal">
    <p class="vg2-section-label">Ecosystem</p>
    <h2>The GenAI tool stack — <em>10 frameworks you&#8217;ll need</em></h2>
    <p>The modern GenAI engineer&#8217;s toolkit, in the order you&#8217;ll typically encounter them.</p>
    <div class="vg2-table-wrap">
      <table class="vg2-table">
        <thead><tr><th>#</th><th>Tool</th><th>What It Does</th><th>When to Add It</th></tr></thead>
        <tbody>
          <tr><td>01</td><td><strong>PyTorch</strong></td><td>The dominant deep learning framework. Most LLM research and production code runs on it.</td><td>Day one</td></tr>
          <tr><td>02</td><td><strong>Hugging Face</strong></td><td>Model hub and library ecosystem — tokenizers, transformers, datasets. Think &#8220;npm for ML&#8221;.</td><td>Day one</td></tr>
          <tr><td>03</td><td><strong>Unsloth</strong></td><td>Optimized fine-tuning library. Makes training LLMs dramatically faster and cheaper.</td><td>When fine-tuning</td></tr>
          <tr><td>04</td><td><strong>LangChain</strong></td><td>Framework for building LLM apps with chains, agents, memory, and tool integration.</td><td>When building apps</td></tr>
          <tr><td>05</td><td><strong>LlamaIndex</strong></td><td>Specialized for RAG pipelines — connects your private data to LLMs.</td><td>When building RAG</td></tr>
          <tr><td>06</td><td><strong>LangGraph</strong></td><td>Builds stateful, multi-step agent workflows as directed graphs.</td><td>When building agents</td></tr>
          <tr><td>07</td><td><strong>VDB / Cloud</strong></td><td>Vector databases (Pinecone, Weaviate, pgvector) and cloud infrastructure.</td><td>When scaling</td></tr>
          <tr><td>08</td><td><strong>OpenAI SDK</strong></td><td>Standard API pattern for LLM interaction — most providers mirror this interface.</td><td>Day one</td></tr>
          <tr><td>09</td><td><strong>Guardrails</strong></td><td>Safety and validation layer ensuring LLM outputs meet business rules and constraints.</td><td>Before production</td></tr>
          <tr><td>10</td><td><strong>MCP</strong></td><td>Model Context Protocol — standardized way to connect LLMs to external tools and data.</td><td>When connecting tools</td></tr>
        </tbody>
      </table>
    </div>
    <div class="vg2-callout">
      <strong>Pro Tip:</strong> Start with PyTorch + Hugging Face for understanding models, add LangChain when you start building apps, layer in the rest as your projects demand them.
    </div>
  </div>

</div><!-- /vg2-body -->

<!-- CAREER PATHS -->
<div class="vg2-career-section">
  <p class="vg2-career-eyebrow">Career</p>
  <h2>Where this knowledge <em>takes you</em></h2>
  <div class="vg2-ladder">
    <div class="vg2-ladder-step"><span>Start</span><strong>Data Analyst / BA</strong></div>
    <span class="vg2-ladder-arrow">→</span>
    <div class="vg2-ladder-step"><span>&nbsp;</span><strong>Data Engineer</strong></div>
    <span class="vg2-ladder-arrow">→</span>
    <div class="vg2-ladder-step"><span>&nbsp;</span><strong>Data Scientist</strong></div>
    <span class="vg2-ladder-arrow">→</span>
    <div class="vg2-ladder-step"><span>&nbsp;</span><strong>MLE / MLOps</strong></div>
    <span class="vg2-ladder-arrow">→</span>
    <div class="vg2-ladder-step"><span>Senior</span><strong>DL Engineer</strong></div>
  </div>
  <div class="vg2-roles-grid">
    <div class="vg2-role-card vg2-reveal vg2-d1"><h4>AI Architect</h4><p>Designs end-to-end AI systems and makes technology choices across the stack.</p></div>
    <div class="vg2-role-card vg2-reveal vg2-d2"><h4>AI Product Manager</h4><p>Bridges business strategy and AI capabilities. No-code path into the space.</p></div>
    <div class="vg2-role-card vg2-reveal vg2-d3"><h4>AI Engineer</h4><p>Builds and integrates AI features into products. The generalist role.</p></div>
    <div class="vg2-role-card vg2-reveal"><h4>GenAI Engineer ★</h4><p>Specializes in LLM-powered applications. Strongest demand right now.</p></div>
    <div class="vg2-role-card vg2-reveal vg2-d1"><h4>Agentic AI Engineer ★</h4><p>Builds autonomous multi-step agent systems. The frontier role.</p></div>
    <div class="vg2-role-card vg2-reveal vg2-d2"><h4>Techno-Functional</h4><p>Combines deep domain expertise with AI skills. High leverage in enterprise.</p></div>
  </div>
</div>

<!-- BUILD PATH -->
<div class="vg2-build-section">
  <p class="vg2-build-eyebrow">Build Path</p>
  <h2>From learning to <em>shipping</em></h2>
  <div class="vg2-stages">
    <div class="vg2-stage vg2-reveal"><div class="vg2-stage-num">1</div><h4>Theory → Base</h4><p>Encodings, embeddings, transformers, LLMs, SLMs, multimodal. Your conceptual foundation.</p></div>
    <div class="vg2-stage vg2-reveal vg2-d1"><div class="vg2-stage-num">2</div><h4>Interview Ready</h4><p>Explain concepts clearly, discuss trade-offs. If you can teach it, you understand it.</p></div>
    <div class="vg2-stage vg2-reveal vg2-d2"><div class="vg2-stage-num">3</div><h4>Applied Skills</h4><p>Fine-tuning, RAG, agentic AI, LLMOps, vector DBs, cloud deployment, MCP integrations.</p></div>
    <div class="vg2-stage vg2-reveal vg2-d3"><div class="vg2-stage-num">4</div><h4>The Build Cycle</h4><p>POC → MVP → Full Dev → Deployment → Scalable App. AI coding assistants compress every stage.</p></div>
  </div>
  <div class="vg2-poc-grid">
    <div class="vg2-poc-phase vg2-reveal"><span class="vg2-phase-tag">Phase 1</span><h5>POC</h5><p>Does this idea even work? Quick, dirty validation.</p></div>
    <div class="vg2-poc-phase vg2-reveal vg2-d1"><span class="vg2-phase-tag">Phase 2</span><h5>MVP</h5><p>Smallest version that delivers real value.</p></div>
    <div class="vg2-poc-phase vg2-reveal vg2-d2"><span class="vg2-phase-tag">Phase 3</span><h5>Full Dev</h5><p>Production-quality code, tests, documentation.</p></div>
    <div class="vg2-poc-phase vg2-reveal vg2-d3"><span class="vg2-phase-tag">Phase 4</span><h5>Deployment</h5><p>CI/CD, monitoring, scaling infrastructure.</p></div>
    <div class="vg2-poc-phase vg2-reveal"><span class="vg2-phase-tag">Phase 5</span><h5>Scalable App</h5><p>Real traffic, cost optimization, feedback iteration.</p></div>
  </div>
</div>

<!-- INTERVIEW PREP -->
<div class="vg2-interview-section">
  <p class="vg2-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg2-qa-list">

    <div class="vg2-qa-item vg2-reveal">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Define</span><br>What is tokenization?</div>
      <div class="vg2-qa-a"><strong>Breaking text into units</strong> a model can process. Tokens may be whole words, subwords, or characters. &#8220;unbelievable&#8221; → [&#8220;un&#8221;, &#8220;believ&#8221;, &#8220;able&#8221;]. Methods: BPE, WordPiece, SentencePiece.
        <div class="vg2-pills"><span class="vg2-pill t">BPE</span><span class="vg2-pill t">WordPiece</span><span class="vg2-pill">Subword units</span></div>
      </div>
    </div>

    <div class="vg2-qa-item vg2-reveal vg2-d1">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Define</span><br>Encoding vs Embedding — what&#8217;s the difference?</div>
      <div class="vg2-qa-a"><strong>Encoding</strong> maps tokens to arbitrary integers (lookup table, no meaning). <strong>Embedding</strong> maps tokens to dense learned vectors where similar concepts cluster. Encoding is a student ID; embedding is placing that student on a map by personality and interests.
        <div class="vg2-pills"><span class="vg2-pill a">Encoding = integer</span><span class="vg2-pill t">Embedding = learned vector</span><span class="vg2-pill t">768–4096 dims</span></div>
      </div>
    </div>

    <div class="vg2-qa-item vg2-reveal">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Explain</span><br>Why did Transformers replace RNNs?</div>
      <div class="vg2-qa-a">RNNs are <strong>sequential</strong> — they process one token at a time and forget long-range context. Transformers use <strong>self-attention</strong> to process all tokens simultaneously, letting every word attend directly to every other. This removes the sequential bottleneck and enables parallelization.
        <div class="vg2-pills"><span class="vg2-pill t">Self-attention</span><span class="vg2-pill t">Parallel processing</span><span class="vg2-pill">No vanishing gradient</span></div>
      </div>
    </div>

    <div class="vg2-qa-item vg2-reveal vg2-d1">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Compare</span><br>Keyword search vs semantic search</div>
      <div class="vg2-qa-a">Keyword search matches <strong>exact tokens</strong>. Semantic search matches <strong>meaning using vector similarity</strong>. Query &#8220;I&#8217;m hungry and want something cheesy&#8221; can retrieve pizza results even if &#8220;pizza&#8221; doesn&#8217;t appear. Most modern systems combine both (hybrid search).
        <div class="vg2-pills"><span class="vg2-pill">Keyword = exact match</span><span class="vg2-pill t">Semantic = vector similarity</span><span class="vg2-pill a">Hybrid = best of both</span></div>
      </div>
    </div>

    <div class="vg2-qa-item vg2-reveal">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Explain</span><br>What is RLHF and why does it matter?</div>
      <div class="vg2-qa-a"><strong>Reinforcement Learning from Human Feedback</strong> — humans rate model outputs, those ratings become reward signals, and the model is fine-tuned to maximize human preference. This is how raw language models become aligned, helpful assistants. It&#8217;s the key step between a pretrained LLM and ChatGPT/Claude.
        <div class="vg2-pills"><span class="vg2-pill t">Human ratings → reward</span><span class="vg2-pill t">RL fine-tuning</span><span class="vg2-pill a">Alignment technique</span></div>
      </div>
    </div>

    <div class="vg2-qa-item vg2-reveal vg2-d1">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Define</span><br>What is RAG?</div>
      <div class="vg2-qa-a"><strong>Retrieval-Augmented Generation</strong> — instead of relying only on training data, the model retrieves relevant documents from an external knowledge base at inference time and uses them as context. Powered by embeddings and vector databases. Keeps LLMs accurate on private or recent data without retraining.
        <div class="vg2-pills"><span class="vg2-pill t">Retrieve → Embed → Generate</span><span class="vg2-pill">pgvector / Pinecone</span><span class="vg2-pill a">LlamaIndex</span></div>
      </div>
    </div>

    <div class="vg2-qa-item vg2-reveal">
      <div class="vg2-qa-q"><span class="vg2-q-badge">Name</span><br>The 5-step NLP evolution in order</div>
      <div class="vg2-qa-a"><strong>RNN → LSTM/GRU → Encoder-Decoder → Transformer → LLM.</strong> Each step solved the prior step&#8217;s core limitation: long-range forgetting, vanishing gradients, fixed context vectors, sequential bottleneck, scale.
        <div class="vg2-pills"><span class="vg2-pill">RNN</span><span class="vg2-pill">LSTM/GRU</span><span class="vg2-pill">Enc-Dec</span><span class="vg2-pill t">Transformer</span><span class="vg2-pill a">LLM</span></div>
      </div>
    </div>

  </div>
</div>

<!-- PRE-FLIGHT CHECKLIST -->
<div class="vg2-checklist-section">
  <p class="vg2-checklist-eyebrow">Action Items</p>
  <h2>Pre-flight <em>checklist</em></h2>
  <div class="vg2-checklist">
    <div class="vg2-check-item vg2-reveal"><div class="vg2-check-box"></div><div class="vg2-check-body"><h4>Dashboard access</h4><p>Log into the course platform and verify you can access all session materials.</p></div></div>
    <div class="vg2-check-item vg2-reveal vg2-d1"><div class="vg2-check-box"></div><div class="vg2-check-body"><h4>Shared resources bookmarked</h4><p>Google Sheet, GitHub repo, or Notion workspace from the session.</p></div></div>
    <div class="vg2-check-item vg2-reveal vg2-d2"><div class="vg2-check-box"></div><div class="vg2-check-body"><h4>Python installed and verified</h4><p>Run <code style="font-family:'DM Mono',monospace;font-size:0.8rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">python --version</code> in your terminal. Any 3.10+ is fine.</p></div></div>
    <div class="vg2-check-item vg2-reveal"><div class="vg2-check-box"></div><div class="vg2-check-body"><h4>VS Code + GitHub Copilot configured</h4><p>Install, authenticate, and test with a quick code completion. Or use Claude Code if you prefer.</p></div></div>
    <div class="vg2-check-item vg2-reveal vg2-d1"><div class="vg2-check-box"></div><div class="vg2-check-body"><h4>Baseline ML/DL/NLP familiarity</h4><p>Or a concrete plan to learn alongside. You don&#8217;t need to be an expert — you need a foundation to build on.</p></div></div>
  </div>
</div>

<!-- FOOTER -->
<div class="vg2-footer">
  <p><strong>Next:</strong> Module 1 deep-dive — encoding and embedding with Python. You&#8217;ll write code that turns sentences into vectors and build a basic semantic search system.</p>
  <a href="https://vijay-gokarn.com" class="vg2-next-btn">Back to Blog ↗</a>
</div>

</div><!-- /vg2 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg2-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg2-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>
<p>The post <a href="https://vijay-gokarn.com/the-genai-landscape-from-zero-to-transformer-series-name-genai-mastery-series-chapter-02/">The GenAI Landscape: From Zero to Transformer Series name: GenAI Mastery Series — Chapter 02</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">236</post-id>	</item>
		<item>
		<title>Creating AI Storytelling Agents Using Flowise: A Step-by-Step Guide</title>
		<link>https://vijay-gokarn.com/creating-ai-storytelling-agents-using-flowise-a-step-by-step-guide/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=creating-ai-storytelling-agents-using-flowise-a-step-by-step-guide</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Fri, 24 Jan 2025 16:51:01 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=227</guid>

					<description><![CDATA[<p>GenAI Mastery Series · Agentic AI · Flowise Walkthrough Building an AI Storytelling Agent with Flowise — No Code Required StackFlowise · OpenAI GPT-4 · Supervisor/Worker Nodes DeploymentLocal · Cloud-ready OutputIBM the Robot&#8217;s Marshmallow Party Concepts Covered AI Agents Flowise Workflows Supervisor / Worker Pattern ChatOpenAI Node No-Code Orchestration Prompt Engineering In today&#8217;s AI landscape, [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/creating-ai-storytelling-agents-using-flowise-a-step-by-step-guide/">Creating AI Storytelling Agents Using Flowise: A Step-by-Step Guide</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg4 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg4 *, .vg4 *::before, .vg4 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg4-hero { background: var(--ink); padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg4-hero::before {
  content: '⬡'; font-family: 'Cormorant Garamond', serif; font-size: 24rem;
  color: rgba(255,255,255,0.025); position: absolute;
  right: -2rem; bottom: -5rem; line-height: 1; pointer-events: none;
}
.vg4-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg4-eyebrow {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.vg4-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg4-hero h1 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem);
  font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em;
  margin-bottom: 1.5rem; max-width: 26ch;
}
.vg4-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg4-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg4-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg4-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* PILL BAND */
.vg4-pill-band {
  background: var(--teal); padding: 1.25rem 4rem;
  display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center;
}
.vg4-pill-band-label { font-size: 0.65rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.5); font-weight: 400; margin-right: 0.5rem; }
.vg4-band-pill { font-size: 0.7rem; letter-spacing: 0.06em; padding: 0.3rem 0.9rem; background: rgba(247,244,239,0.12); color: var(--paper); border: 0.5px solid rgba(247,244,239,0.2); }

/* INTRO */
.vg4-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg4-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg4-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg4-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg4-section { margin-bottom: 3.5rem; }
.vg4-section-label {
  font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal); font-weight: 500; margin-bottom: 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.vg4-section-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg4-section h2 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1.25rem;
}
.vg4-section h2 em { font-style: italic; color: var(--teal); }
.vg4-section p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg4-section p strong { color: var(--ink); font-weight: 500; }
.vg4-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg4-callout {
  background: var(--paper-dark); border-left: 3px solid var(--amber);
  padding: 1.25rem 1.5rem; margin: 1.5rem 0;
  font-size: 0.87rem; line-height: 1.8; color: var(--charcoal);
}
.vg4-callout strong { color: var(--amber); font-weight: 500; }
.vg4-callout.teal { border-color: var(--teal); }
.vg4-callout.teal strong { color: var(--teal); }
.vg4-callout code { font-family: 'DM Mono', monospace; font-size: 0.8rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.4rem; }

/* CODE BLOCK */
.vg4-code { background: var(--ink); padding: 1.5rem 2rem; margin: 1.5rem 0; overflow-x: auto; }
.vg4-code-label { font-family: 'DM Sans', sans-serif; font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.6rem; display: block; }
.vg4-code code { font-family: 'DM Mono', monospace; font-size: 0.85rem; color: var(--amber-light); white-space: pre; display: block; line-height: 1.8; }
.vg4-code code .vg4-comment { color: rgba(247,244,239,0.3); }
.vg4-code code .vg4-cmd { color: var(--teal-light); }

/* NODE CARDS — WORKFLOW STEPS */
.vg4-nodes-section { background: var(--paper-dark); padding: 4rem; }
.vg4-nodes-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg4-nodes-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg4-nodes-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg4-nodes-section > h2 em { font-style: italic; color: var(--teal); }
.vg4-node-flow { display: flex; flex-direction: column; gap: 0; }
.vg4-node-item { display: grid; grid-template-columns: 80px 1fr; gap: 2rem; padding: 2rem 0; border-top: 0.5px solid var(--border); align-items: start; }
.vg4-node-item:last-child { border-bottom: 0.5px solid var(--border); }
.vg4-node-left { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
.vg4-node-num {
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Cormorant Garamond', serif; font-size: 1.2rem; font-weight: 300;
  background: var(--ink); color: var(--paper); flex-shrink: 0;
}
.vg4-node-num.teal { background: var(--teal); }
.vg4-node-num.amber { background: var(--amber); color: var(--paper); }
.vg4-node-connector { width: 1px; flex: 1; min-height: 20px; background: var(--border); }
.vg4-node-right {}
.vg4-node-type { font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.35rem; }
.vg4-node-right h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.35rem; font-weight: 400; color: var(--ink); margin-bottom: 0.6rem; }
.vg4-node-right p { font-size: 0.85rem; line-height: 1.8; color: var(--charcoal); font-weight: 300; margin-bottom: 0.75rem; }
.vg4-node-right p strong { color: var(--ink); font-weight: 500; }
.vg4-config-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }
.vg4-config-chip { font-family: 'DM Mono', monospace; font-size: 0.7rem; padding: 0.25rem 0.75rem; background: var(--paper); border: 0.5px solid var(--border-strong); color: var(--charcoal); letter-spacing: 0.04em; }
.vg4-config-chip.teal { border-color: var(--teal); color: var(--teal); background: var(--teal-muted); }
.vg4-prompt-box { background: var(--ink); padding: 1.1rem 1.25rem; margin-top: 0.75rem; font-family: 'DM Mono', monospace; font-size: 0.78rem; color: var(--amber-light); line-height: 1.7; }
.vg4-prompt-box .vg4-prompt-label { font-family: 'DM Sans', sans-serif; font-size: 0.58rem; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.4rem; display: block; }

/* STORY OUTPUT */
.vg4-story-section { background: var(--ink); padding: 4rem; }
.vg4-story-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg4-story-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg4-story-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2rem; }
.vg4-story-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg4-story-card { border: 0.5px solid rgba(247,244,239,0.12); padding: 2.5rem; position: relative; }
.vg4-story-card::before { content: '"'; font-family: 'Cormorant Garamond', serif; font-size: 8rem; font-weight: 300; color: rgba(250,199,117,0.1); position: absolute; top: -1rem; left: 1.5rem; line-height: 1; pointer-events: none; }
.vg4-story-title-row { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg4-story-title-label { font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.4rem; }
.vg4-story-title { font-family: 'Cormorant Garamond', serif; font-size: 1.6rem; font-weight: 300; color: var(--amber-light); line-height: 1.2; }
.vg4-story-body { font-size: 0.9rem; line-height: 1.95; color: rgba(247,244,239,0.7); font-weight: 300; font-style: italic; }
.vg4-story-body p + p { margin-top: 1rem; }
.vg4-story-meta { display: flex; gap: 1.5rem; margin-top: 1.5rem; padding-top: 1.25rem; border-top: 0.5px solid rgba(247,244,239,0.1); flex-wrap: wrap; }
.vg4-story-meta-item { font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.3); }
.vg4-story-meta-item span { color: var(--amber-light); margin-left: 0.35rem; }

/* INTERVIEW */
.vg4-interview-section { background: var(--teal-muted); padding: 4rem; }
.vg4-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg4-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg4-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg4-interview-section > h2 em { font-style: italic; color: var(--teal); }
.vg4-qa-list { display: flex; flex-direction: column; }
.vg4-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(14,14,14,0.1); align-items: start; }
.vg4-qa-item:last-child { border-bottom: 0.5px solid rgba(14,14,14,0.1); }
.vg4-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--ink); line-height: 1.4; }
.vg4-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg4-qa-a { font-size: 0.83rem; line-height: 1.8; color: var(--charcoal); font-weight: 300; }
.vg4-qa-a strong { color: var(--teal); font-weight: 500; }
.vg4-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.35rem; color: var(--ink); }
.vg4-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg4-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid var(--border-strong); color: var(--charcoal); }
.vg4-pill.t { border-color: var(--teal); color: var(--teal); background: var(--teal-muted); }
.vg4-pill.a { border-color: var(--amber); color: var(--amber); background: var(--amber-muted); }

/* FOOTER */
.vg4-footer { background: var(--ink); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; }
.vg4-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg4-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg4-back-btn { display: inline-block; padding: 0.65rem 1.75rem; background: var(--teal); color: var(--paper); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }

/* REVEAL */
.vg4-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg4-reveal.vg4-vis { opacity: 1; transform: translateY(0); }
.vg4-d1 { transition-delay: 0.1s; } .vg4-d2 { transition-delay: 0.2s; } .vg4-d3 { transition-delay: 0.3s; }
</style>

<div class="vg4">

<!-- HERO -->
<div class="vg4-hero">
  <div class="vg4-hero-inner">
    <p class="vg4-eyebrow">GenAI Mastery Series · Agentic AI · Flowise Walkthrough</p>
    <h1>Building an AI Storytelling Agent with Flowise — <em>No Code Required</em></h1>
    <div class="vg4-meta-row">
      <p class="vg4-meta">Stack<span>Flowise · OpenAI GPT-4 · Supervisor/Worker Nodes</span></p>
      <p class="vg4-meta">Deployment<span>Local · Cloud-ready</span></p>
      <p class="vg4-meta">Output<span>IBM the Robot&#8217;s Marshmallow Party</span></p>
    </div>
  </div>
</div>

<!-- PILL BAND -->
<div class="vg4-pill-band">
  <span class="vg4-pill-band-label">Concepts Covered</span>
  <span class="vg4-band-pill">AI Agents</span>
  <span class="vg4-band-pill">Flowise Workflows</span>
  <span class="vg4-band-pill">Supervisor / Worker Pattern</span>
  <span class="vg4-band-pill">ChatOpenAI Node</span>
  <span class="vg4-band-pill">No-Code Orchestration</span>
  <span class="vg4-band-pill">Prompt Engineering</span>
</div>

<!-- INTRO -->
<div class="vg4-intro">
  <p>In today&#8217;s AI landscape, agents are becoming powerful tools to automate complex tasks — from chatbots to interactive storytelling. <strong>Flowise</strong> is a no-code AI workflow builder that makes it easy to design, deploy, and manage AI agents for a wide range of applications. This walkthrough builds a fully functional storytelling agent, locally deployable and cloud-ready.</p>
</div>

<!-- BODY -->
<div class="vg4-body">

  <!-- WHAT ARE AI AGENTS -->
  <div class="vg4-section vg4-reveal">
    <p class="vg4-section-label">Concepts</p>
    <h2>What are AI agents <em>in Flowise?</em></h2>
    <p>AI agents in Flowise are intelligent modules that can handle tasks <strong>autonomously</strong> by combining logic, AI models, and external tools. They process inputs, make decisions, and generate tailored outputs — without manual intervention at each step.</p>
    <p>In this project we use the <strong>Supervisor and Worker node pattern</strong> with OpenAI Chat. The supervisor coordinates the overall workflow; worker nodes each own a specific sub-task — here, storytelling and title assignment.</p>
    <div class="vg4-callout teal">
      <strong>Why multi-agent?</strong> Splitting responsibilities between nodes keeps each prompt focused and small. A dedicated Storyteller node generates better stories than one giant prompt trying to write a story, title it, and format it all at once. This mirrors how real engineering teams work — one job per role.
    </div>
  </div>

  <hr class="vg4-divider">

  <!-- SETUP -->
  <div class="vg4-section vg4-reveal">
    <p class="vg4-section-label">Step 1</p>
    <h2>Setting up <em>Flowise</em></h2>
    <p>Flowise runs as a local Node.js server you access through a browser-based canvas. Two commands are all you need to get started.</p>
    <div class="vg4-code">
      <span class="vg4-code-label">Terminal — Install &#038; Run</span>
      <code><span class="vg4-cmd">npm install</span> flowise
<span class="vg4-cmd">npx flowise</span> run</code>
    </div>
    <p>Once running, open your browser, log in, and click <strong>&#8220;New Workflow&#8221;</strong> to open the interactive canvas. You&#8217;ll drag, drop, and wire nodes together visually — no boilerplate code.</p>
    <div class="vg4-callout">
      <strong>Local vs Cloud:</strong> The setup above runs entirely on your machine. For cloud deployment, Flowise supports Railway, Render, and self-hosted Docker. The workflow JSON is portable — build locally, deploy anywhere.
    </div>
  </div>

</div><!-- /vg4-body -->

<!-- NODE WALKTHROUGH -->
<div class="vg4-nodes-section">
  <p class="vg4-nodes-eyebrow">Step 2 — Workflow Design</p>
  <h2>Building the agent — <em>node by node</em></h2>
  <div class="vg4-node-flow">

    <div class="vg4-node-item vg4-reveal">
      <div class="vg4-node-left">
        <div class="vg4-node-num teal">1</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Chat Model Node</p>
        <h3>ChatOpenAI — The Brain</h3>
        <p>Drag a <strong>ChatOpenAI Node</strong> onto the canvas and connect it as the model backend for all worker nodes. Configure GPT-4 with elevated temperature for imaginative outputs.</p>
        <div class="vg4-config-list">
          <span class="vg4-config-chip teal">Model: GPT-4</span>
          <span class="vg4-config-chip teal">Temperature: 0.9</span>
          <span class="vg4-config-chip">Max Tokens: 400–500</span>
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal vg4-d1">
      <div class="vg4-node-left">
        <div class="vg4-node-num teal">2</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Worker Node · Role: Storyteller</p>
        <h3>Storytelling Agent</h3>
        <p>Add a <strong>Worker Node</strong> and connect it to the ChatOpenAI node. Set its role as the Storyteller. This node owns the core creative generation task — it receives the theme prompt and writes the full story.</p>
        <div class="vg4-prompt-box">
          <span class="vg4-prompt-label">Worker Prompt</span>
          You are a storyteller. Write a fun and engaging story for kids aged 5–8. The main character is a robot named IBM. Make it funny, magical, and include a twist. Limit the story to 400 words.
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal vg4-d2">
      <div class="vg4-node-left">
        <div class="vg4-node-num amber">3</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Worker Node · Role: Title Assigner</p>
        <h3>Title Assigner Agent</h3>
        <p>Add a second <strong>Worker Node</strong> downstream of the Storyteller. This node&#8217;s sole job is to extract a short, engaging title from the generated story — a focused single-responsibility task.</p>
        <div class="vg4-prompt-box">
          <span class="vg4-prompt-label">Worker Prompt</span>
          Extract the title of the story you just created. Keep it short and engaging.
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal">
      <div class="vg4-node-left">
        <div class="vg4-node-num">4</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Format Prompt Values Node</p>
        <h3>Output Formatter</h3>
        <p>Use the <strong>Format Prompt Values Node</strong> to combine the story and title from the two worker nodes into a clean, structured output ready for display.</p>
        <div class="vg4-config-list">
          <span class="vg4-config-chip">Title: {&#8216;{&#8216;}Title Extracted{&#8216;}&#8217;}</span>
          <span class="vg4-config-chip">Story: {&#8216;{&#8216;}Generated Story{&#8216;}&#8217;}</span>
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal vg4-d1">
      <div class="vg4-node-left">
        <div class="vg4-node-num teal">5</div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Chat Output Node</p>
        <h3>Chat Output — Delivery</h3>
        <p>Connect the formatted output to the <strong>Chat Output Node</strong>. This is the interface layer — the final assembled story and title are surfaced here for users to read, copy, or embed.</p>
        <div class="vg4-config-list">
          <span class="vg4-config-chip teal">Displays story + title</span>
          <span class="vg4-config-chip">Embeddable chat widget</span>
        </div>
      </div>
    </div>

  </div>
</div>

<!-- BODY CONTINUED — RUNNING -->
<div class="vg4-body">
  <div class="vg4-section vg4-reveal">
    <p class="vg4-section-label">Step 3</p>
    <h2>Running the <em>agent</em></h2>
    <p>With all nodes configured and wired together, save your workflow — name it something like <strong>&#8220;AI Storytelling Agent&#8221;</strong> — and hit Run. Enter a theme prompt or use the default storytelling instructions, and the agent pipeline fires automatically: ChatOpenAI powers the Storyteller worker, its output flows to the Title Assigner, both outputs merge in the Formatter, and the Chat Output displays the result.</p>
    <div class="vg4-callout teal">
      <strong>Tip:</strong> Experiment with different <code>temperature</code> values. At 0.7 the stories are coherent but predictable. At 0.95 you get genuinely surprising plot twists — which for kids&#8217; stories is exactly what you want.
    </div>
  </div>
</div>

<!-- STORY OUTPUT -->
<div class="vg4-story-section">
  <p class="vg4-story-eyebrow">Example Output</p>
  <h2>IBM&#8217;s <em>Marshmallow Party</em></h2>
  <div class="vg4-story-card vg4-reveal">
    <div class="vg4-story-title-row">
      <p class="vg4-story-title-label">Generated Title</p>
      <p class="vg4-story-title">IBM the Robot and the Marshmallow Party</p>
    </div>
    <div class="vg4-story-body">
      <p>Once upon a time, in a land of giggles and sparkles, there lived a silly little robot named IBM. Now, IBM wasn&#8217;t your everyday robot who danced or painted; oh no! He was known as a &#8220;computer,&#8221; which is a magic box that helps people do all sorts of amazing things!</p>
      <p>One sunny day, IBM decided to throw a party for all his robot friends. He said, &#8220;Let&#8217;s make it the best party ever! I&#8217;ll invite my buddy, Printer Pete, and my bestie, Codey the Coder!&#8221; But IBM accidentally ordered 1,000 bags of rainbow-colored marshmallows instead of snacks — and chaos ensued!</p>
      <p>The party turned into a marshmallow-filled adventure with pillow fights, marshmallow towers, and lots of laughs. In the end, IBM and his friends agreed: whether it&#8217;s chips or marshmallows, any party is fun when friends are around!</p>
    </div>
    <div class="vg4-story-meta">
      <p class="vg4-story-meta-item">Model<span>GPT-4</span></p>
      <p class="vg4-story-meta-item">Temperature<span>0.9</span></p>
      <p class="vg4-story-meta-item">Word Count<span>~150 words</span></p>
      <p class="vg4-story-meta-item">Nodes Used<span>5</span></p>
    </div>
  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg4-interview-section">
  <p class="vg4-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg4-qa-list">

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Define</span><br>What is an AI agent?</div>
      <div class="vg4-qa-a"><strong>An autonomous module</strong> that combines a language model, logic, and optionally external tools to complete a task without step-by-step human instruction. It receives a goal, plans sub-steps, and executes them independently.
        <div class="vg4-pills"><span class="vg4-pill t">Autonomous</span><span class="vg4-pill t">Goal-driven</span><span class="vg4-pill">Tool-using</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal vg4-d1">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Explain</span><br>What is the Supervisor / Worker pattern?</div>
      <div class="vg4-qa-a">A <strong>Supervisor node</strong> coordinates the overall workflow and delegates tasks to <strong>Worker nodes</strong>, each of which handles one focused sub-task. This mirrors microservices architecture — single responsibility per agent, composable into larger pipelines.
        <div class="vg4-pills"><span class="vg4-pill t">Supervisor = orchestrator</span><span class="vg4-pill t">Worker = specialist</span><span class="vg4-pill a">Single responsibility</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Define</span><br>What does temperature control in an LLM?</div>
      <div class="vg4-qa-a"><strong>Randomness in token sampling.</strong> Low temperature (0.1–0.4) = deterministic, factual, conservative outputs. High temperature (0.8–1.0) = creative, surprising, occasionally incoherent. For storytelling, 0.9 hits the sweet spot of imaginative without losing coherence.
        <div class="vg4-pills"><span class="vg4-pill">Low = deterministic</span><span class="vg4-pill a">High = creative</span><span class="vg4-pill t">0.9 for stories</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal vg4-d1">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Compare</span><br>No-code (Flowise) vs code-first (LangChain) — when to use which?</div>
      <div class="vg4-qa-a">Use <strong>Flowise</strong> for rapid prototyping, demos, non-developer stakeholders, or when the workflow is straightforward and visual. Use <strong>LangChain / LangGraph in code</strong> when you need version control, CI/CD, complex branching, custom tool integrations, or production-grade observability.
        <div class="vg4-pills"><span class="vg4-pill t">Flowise = prototype fast</span><span class="vg4-pill a">LangChain = production</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Explain</span><br>Why split story generation and title extraction into separate nodes?</div>
      <div class="vg4-qa-a"><strong>Focused prompts outperform omnibus prompts.</strong> A prompt that must write a story, extract a title, and format output all at once tends to trade off quality across tasks. Separate nodes give each sub-task its own context window, model parameters, and success criteria — and makes each step independently testable and replaceable.
        <div class="vg4-pills"><span class="vg4-pill t">One node, one job</span><span class="vg4-pill">Better quality</span><span class="vg4-pill a">Independently testable</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal vg4-d1">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Use Case</span><br>What other use cases suit a Flowise multi-agent setup?</div>
      <div class="vg4-qa-a"><strong>Any pipeline with distinct sequential sub-tasks:</strong> customer support (intent classification → knowledge retrieval → response drafting), content pipelines (research → outline → write → SEO optimize), data workflows (extract → validate → transform → summarize).
        <div class="vg4-pills"><span class="vg4-pill t">Customer support</span><span class="vg4-pill t">Content pipelines</span><span class="vg4-pill t">Data workflows</span><span class="vg4-pill">Code review agents</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Gotcha</span><br>What are the main limits of no-code agent builders?</div>
      <div class="vg4-qa-a">Three key limitations: <strong>(1) Observability</strong> — debugging visual workflows is harder than reading stack traces. <strong>(2) Version control</strong> — workflow JSON doesn&#8217;t diff cleanly in Git. <strong>(3) Custom logic</strong> — complex conditional branching, stateful memory, and custom tool integrations are much easier in code-first frameworks.
        <div class="vg4-pills"><span class="vg4-pill a">Hard to debug</span><span class="vg4-pill a">No clean Git diff</span><span class="vg4-pill a">Limited branching</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg4-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <a href="https://vijay-gokarn.com" class="vg4-back-btn">Back to Blog ↗</a>
</div>

</div><!-- /vg4 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg4-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg4-reveal').forEach(function(el){ obs.observe(el); });
})();
</script><link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg4 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg4 *, .vg4 *::before, .vg4 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg4-hero { background: var(--ink); padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg4-hero::before {
  content: '⬡'; font-family: 'Cormorant Garamond', serif; font-size: 24rem;
  color: rgba(255,255,255,0.025); position: absolute;
  right: -2rem; bottom: -5rem; line-height: 1; pointer-events: none;
}
.vg4-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg4-eyebrow {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.vg4-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg4-hero h1 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem);
  font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em;
  margin-bottom: 1.5rem; max-width: 26ch;
}
.vg4-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg4-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg4-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg4-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* PILL BAND */
.vg4-pill-band {
  background: var(--teal); padding: 1.25rem 4rem;
  display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center;
}
.vg4-pill-band-label { font-size: 0.65rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.5); font-weight: 400; margin-right: 0.5rem; }
.vg4-band-pill { font-size: 0.7rem; letter-spacing: 0.06em; padding: 0.3rem 0.9rem; background: rgba(247,244,239,0.12); color: var(--paper); border: 0.5px solid rgba(247,244,239,0.2); }

/* INTRO */
.vg4-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg4-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg4-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg4-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg4-section { margin-bottom: 3.5rem; }
.vg4-section-label {
  font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal); font-weight: 500; margin-bottom: 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.vg4-section-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg4-section h2 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1.25rem;
}
.vg4-section h2 em { font-style: italic; color: var(--teal); }
.vg4-section p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg4-section p strong { color: var(--ink); font-weight: 500; }
.vg4-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg4-callout {
  background: var(--paper-dark); border-left: 3px solid var(--amber);
  padding: 1.25rem 1.5rem; margin: 1.5rem 0;
  font-size: 0.87rem; line-height: 1.8; color: var(--charcoal);
}
.vg4-callout strong { color: var(--amber); font-weight: 500; }
.vg4-callout.teal { border-color: var(--teal); }
.vg4-callout.teal strong { color: var(--teal); }
.vg4-callout code { font-family: 'DM Mono', monospace; font-size: 0.8rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.4rem; }

/* CODE BLOCK */
.vg4-code { background: var(--ink); padding: 1.5rem 2rem; margin: 1.5rem 0; overflow-x: auto; }
.vg4-code-label { font-family: 'DM Sans', sans-serif; font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.6rem; display: block; }
.vg4-code code { font-family: 'DM Mono', monospace; font-size: 0.85rem; color: var(--amber-light); white-space: pre; display: block; line-height: 1.8; }
.vg4-code code .vg4-comment { color: rgba(247,244,239,0.3); }
.vg4-code code .vg4-cmd { color: var(--teal-light); }

/* NODE CARDS — WORKFLOW STEPS */
.vg4-nodes-section { background: var(--paper-dark); padding: 4rem; }
.vg4-nodes-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg4-nodes-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg4-nodes-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg4-nodes-section > h2 em { font-style: italic; color: var(--teal); }
.vg4-node-flow { display: flex; flex-direction: column; gap: 0; }
.vg4-node-item { display: grid; grid-template-columns: 80px 1fr; gap: 2rem; padding: 2rem 0; border-top: 0.5px solid var(--border); align-items: start; }
.vg4-node-item:last-child { border-bottom: 0.5px solid var(--border); }
.vg4-node-left { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
.vg4-node-num {
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Cormorant Garamond', serif; font-size: 1.2rem; font-weight: 300;
  background: var(--ink); color: var(--paper); flex-shrink: 0;
}
.vg4-node-num.teal { background: var(--teal); }
.vg4-node-num.amber { background: var(--amber); color: var(--paper); }
.vg4-node-connector { width: 1px; flex: 1; min-height: 20px; background: var(--border); }
.vg4-node-right {}
.vg4-node-type { font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.35rem; }
.vg4-node-right h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.35rem; font-weight: 400; color: var(--ink); margin-bottom: 0.6rem; }
.vg4-node-right p { font-size: 0.85rem; line-height: 1.8; color: var(--charcoal); font-weight: 300; margin-bottom: 0.75rem; }
.vg4-node-right p strong { color: var(--ink); font-weight: 500; }
.vg4-config-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }
.vg4-config-chip { font-family: 'DM Mono', monospace; font-size: 0.7rem; padding: 0.25rem 0.75rem; background: var(--paper); border: 0.5px solid var(--border-strong); color: var(--charcoal); letter-spacing: 0.04em; }
.vg4-config-chip.teal { border-color: var(--teal); color: var(--teal); background: var(--teal-muted); }
.vg4-prompt-box { background: var(--ink); padding: 1.1rem 1.25rem; margin-top: 0.75rem; font-family: 'DM Mono', monospace; font-size: 0.78rem; color: var(--amber-light); line-height: 1.7; }
.vg4-prompt-box .vg4-prompt-label { font-family: 'DM Sans', sans-serif; font-size: 0.58rem; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.4rem; display: block; }

/* STORY OUTPUT */
.vg4-story-section { background: var(--ink); padding: 4rem; }
.vg4-story-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg4-story-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg4-story-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2rem; }
.vg4-story-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg4-story-card { border: 0.5px solid rgba(247,244,239,0.12); padding: 2.5rem; position: relative; }
.vg4-story-card::before { content: '"'; font-family: 'Cormorant Garamond', serif; font-size: 8rem; font-weight: 300; color: rgba(250,199,117,0.1); position: absolute; top: -1rem; left: 1.5rem; line-height: 1; pointer-events: none; }
.vg4-story-title-row { margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg4-story-title-label { font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.3); margin-bottom: 0.4rem; }
.vg4-story-title { font-family: 'Cormorant Garamond', serif; font-size: 1.6rem; font-weight: 300; color: var(--amber-light); line-height: 1.2; }
.vg4-story-body { font-size: 0.9rem; line-height: 1.95; color: rgba(247,244,239,0.7); font-weight: 300; font-style: italic; }
.vg4-story-body p + p { margin-top: 1rem; }
.vg4-story-meta { display: flex; gap: 1.5rem; margin-top: 1.5rem; padding-top: 1.25rem; border-top: 0.5px solid rgba(247,244,239,0.1); flex-wrap: wrap; }
.vg4-story-meta-item { font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.3); }
.vg4-story-meta-item span { color: var(--amber-light); margin-left: 0.35rem; }

/* INTERVIEW */
.vg4-interview-section { background: var(--teal-muted); padding: 4rem; }
.vg4-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg4-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg4-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg4-interview-section > h2 em { font-style: italic; color: var(--teal); }
.vg4-qa-list { display: flex; flex-direction: column; }
.vg4-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(14,14,14,0.1); align-items: start; }
.vg4-qa-item:last-child { border-bottom: 0.5px solid rgba(14,14,14,0.1); }
.vg4-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--ink); line-height: 1.4; }
.vg4-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg4-qa-a { font-size: 0.83rem; line-height: 1.8; color: var(--charcoal); font-weight: 300; }
.vg4-qa-a strong { color: var(--teal); font-weight: 500; }
.vg4-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.35rem; color: var(--ink); }
.vg4-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg4-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid var(--border-strong); color: var(--charcoal); }
.vg4-pill.t { border-color: var(--teal); color: var(--teal); background: var(--teal-muted); }
.vg4-pill.a { border-color: var(--amber); color: var(--amber); background: var(--amber-muted); }

/* FOOTER */
.vg4-footer { background: var(--ink); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; }
.vg4-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg4-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg4-back-btn { display: inline-block; padding: 0.65rem 1.75rem; background: var(--teal); color: var(--paper); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }

/* REVEAL */
.vg4-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg4-reveal.vg4-vis { opacity: 1; transform: translateY(0); }
.vg4-d1 { transition-delay: 0.1s; } .vg4-d2 { transition-delay: 0.2s; } .vg4-d3 { transition-delay: 0.3s; }
</style>

<div class="vg4">

<!-- HERO -->
<div class="vg4-hero">
  <div class="vg4-hero-inner">
    <p class="vg4-eyebrow">GenAI Mastery Series · Agentic AI · Flowise Walkthrough</p>
    <h1>Building an AI Storytelling Agent with Flowise — <em>No Code Required</em></h1>
    <div class="vg4-meta-row">
      <p class="vg4-meta">Stack<span>Flowise · OpenAI GPT-4 · Supervisor/Worker Nodes</span></p>
      <p class="vg4-meta">Deployment<span>Local · Cloud-ready</span></p>
      <p class="vg4-meta">Output<span>IBM the Robot&#8217;s Marshmallow Party</span></p>
    </div>
  </div>
</div>

<!-- PILL BAND -->
<div class="vg4-pill-band">
  <span class="vg4-pill-band-label">Concepts Covered</span>
  <span class="vg4-band-pill">AI Agents</span>
  <span class="vg4-band-pill">Flowise Workflows</span>
  <span class="vg4-band-pill">Supervisor / Worker Pattern</span>
  <span class="vg4-band-pill">ChatOpenAI Node</span>
  <span class="vg4-band-pill">No-Code Orchestration</span>
  <span class="vg4-band-pill">Prompt Engineering</span>
</div>

<!-- INTRO -->
<div class="vg4-intro">
  <p>In today&#8217;s AI landscape, agents are becoming powerful tools to automate complex tasks — from chatbots to interactive storytelling. <strong>Flowise</strong> is a no-code AI workflow builder that makes it easy to design, deploy, and manage AI agents for a wide range of applications. This walkthrough builds a fully functional storytelling agent, locally deployable and cloud-ready.</p>
</div>

<!-- BODY -->
<div class="vg4-body">

  <!-- WHAT ARE AI AGENTS -->
  <div class="vg4-section vg4-reveal">
    <p class="vg4-section-label">Concepts</p>
    <h2>What are AI agents <em>in Flowise?</em></h2>
    <p>AI agents in Flowise are intelligent modules that can handle tasks <strong>autonomously</strong> by combining logic, AI models, and external tools. They process inputs, make decisions, and generate tailored outputs — without manual intervention at each step.</p>
    <p>In this project we use the <strong>Supervisor and Worker node pattern</strong> with OpenAI Chat. The supervisor coordinates the overall workflow; worker nodes each own a specific sub-task — here, storytelling and title assignment.</p>
    <div class="vg4-callout teal">
      <strong>Why multi-agent?</strong> Splitting responsibilities between nodes keeps each prompt focused and small. A dedicated Storyteller node generates better stories than one giant prompt trying to write a story, title it, and format it all at once. This mirrors how real engineering teams work — one job per role.
    </div>
  </div>

  <hr class="vg4-divider">

  <!-- SETUP -->
  <div class="vg4-section vg4-reveal">
    <p class="vg4-section-label">Step 1</p>
    <h2>Setting up <em>Flowise</em></h2>
    <p>Flowise runs as a local Node.js server you access through a browser-based canvas. Two commands are all you need to get started.</p>
    <div class="vg4-code">
      <span class="vg4-code-label">Terminal — Install &#038; Run</span>
      <code><span class="vg4-cmd">npm install</span> flowise
<span class="vg4-cmd">npx flowise</span> run</code>
    </div>
    <p>Once running, open your browser, log in, and click <strong>&#8220;New Workflow&#8221;</strong> to open the interactive canvas. You&#8217;ll drag, drop, and wire nodes together visually — no boilerplate code.</p>
    <div class="vg4-callout">
      <strong>Local vs Cloud:</strong> The setup above runs entirely on your machine. For cloud deployment, Flowise supports Railway, Render, and self-hosted Docker. The workflow JSON is portable — build locally, deploy anywhere.
    </div>
  </div>

</div><!-- /vg4-body -->

<!-- NODE WALKTHROUGH -->
<div class="vg4-nodes-section">
  <p class="vg4-nodes-eyebrow">Step 2 — Workflow Design</p>
  <h2>Building the agent — <em>node by node</em></h2>
  <div class="vg4-node-flow">

    <div class="vg4-node-item vg4-reveal">
      <div class="vg4-node-left">
        <div class="vg4-node-num teal">1</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Chat Model Node</p>
        <h3>ChatOpenAI — The Brain</h3>
        <p>Drag a <strong>ChatOpenAI Node</strong> onto the canvas and connect it as the model backend for all worker nodes. Configure GPT-4 with elevated temperature for imaginative outputs.</p>
        <div class="vg4-config-list">
          <span class="vg4-config-chip teal">Model: GPT-4</span>
          <span class="vg4-config-chip teal">Temperature: 0.9</span>
          <span class="vg4-config-chip">Max Tokens: 400–500</span>
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal vg4-d1">
      <div class="vg4-node-left">
        <div class="vg4-node-num teal">2</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Worker Node · Role: Storyteller</p>
        <h3>Storytelling Agent</h3>
        <p>Add a <strong>Worker Node</strong> and connect it to the ChatOpenAI node. Set its role as the Storyteller. This node owns the core creative generation task — it receives the theme prompt and writes the full story.</p>
        <div class="vg4-prompt-box">
          <span class="vg4-prompt-label">Worker Prompt</span>
          You are a storyteller. Write a fun and engaging story for kids aged 5–8. The main character is a robot named IBM. Make it funny, magical, and include a twist. Limit the story to 400 words.
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal vg4-d2">
      <div class="vg4-node-left">
        <div class="vg4-node-num amber">3</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Worker Node · Role: Title Assigner</p>
        <h3>Title Assigner Agent</h3>
        <p>Add a second <strong>Worker Node</strong> downstream of the Storyteller. This node&#8217;s sole job is to extract a short, engaging title from the generated story — a focused single-responsibility task.</p>
        <div class="vg4-prompt-box">
          <span class="vg4-prompt-label">Worker Prompt</span>
          Extract the title of the story you just created. Keep it short and engaging.
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal">
      <div class="vg4-node-left">
        <div class="vg4-node-num">4</div>
        <div class="vg4-node-connector"></div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Format Prompt Values Node</p>
        <h3>Output Formatter</h3>
        <p>Use the <strong>Format Prompt Values Node</strong> to combine the story and title from the two worker nodes into a clean, structured output ready for display.</p>
        <div class="vg4-config-list">
          <span class="vg4-config-chip">Title: {&#8216;{&#8216;}Title Extracted{&#8216;}&#8217;}</span>
          <span class="vg4-config-chip">Story: {&#8216;{&#8216;}Generated Story{&#8216;}&#8217;}</span>
        </div>
      </div>
    </div>

    <div class="vg4-node-item vg4-reveal vg4-d1">
      <div class="vg4-node-left">
        <div class="vg4-node-num teal">5</div>
      </div>
      <div class="vg4-node-right">
        <p class="vg4-node-type">Chat Output Node</p>
        <h3>Chat Output — Delivery</h3>
        <p>Connect the formatted output to the <strong>Chat Output Node</strong>. This is the interface layer — the final assembled story and title are surfaced here for users to read, copy, or embed.</p>
        <div class="vg4-config-list">
          <span class="vg4-config-chip teal">Displays story + title</span>
          <span class="vg4-config-chip">Embeddable chat widget</span>
        </div>
      </div>
    </div>

  </div>
</div>

<!-- BODY CONTINUED — RUNNING -->
<div class="vg4-body">
  <div class="vg4-section vg4-reveal">
    <p class="vg4-section-label">Step 3</p>
    <h2>Running the <em>agent</em></h2>
    <p>With all nodes configured and wired together, save your workflow — name it something like <strong>&#8220;AI Storytelling Agent&#8221;</strong> — and hit Run. Enter a theme prompt or use the default storytelling instructions, and the agent pipeline fires automatically: ChatOpenAI powers the Storyteller worker, its output flows to the Title Assigner, both outputs merge in the Formatter, and the Chat Output displays the result.</p>
    <div class="vg4-callout teal">
      <strong>Tip:</strong> Experiment with different <code>temperature</code> values. At 0.7 the stories are coherent but predictable. At 0.95 you get genuinely surprising plot twists — which for kids&#8217; stories is exactly what you want.
    </div>
  </div>
</div>

<!-- STORY OUTPUT -->
<div class="vg4-story-section">
  <p class="vg4-story-eyebrow">Example Output</p>
  <h2>IBM&#8217;s <em>Marshmallow Party</em></h2>
  <div class="vg4-story-card vg4-reveal">
    <div class="vg4-story-title-row">
      <p class="vg4-story-title-label">Generated Title</p>
      <p class="vg4-story-title">IBM the Robot and the Marshmallow Party</p>
    </div>
    <div class="vg4-story-body">
      <p>Once upon a time, in a land of giggles and sparkles, there lived a silly little robot named IBM. Now, IBM wasn&#8217;t your everyday robot who danced or painted; oh no! He was known as a &#8220;computer,&#8221; which is a magic box that helps people do all sorts of amazing things!</p>
      <p>One sunny day, IBM decided to throw a party for all his robot friends. He said, &#8220;Let&#8217;s make it the best party ever! I&#8217;ll invite my buddy, Printer Pete, and my bestie, Codey the Coder!&#8221; But IBM accidentally ordered 1,000 bags of rainbow-colored marshmallows instead of snacks — and chaos ensued!</p>
      <p>The party turned into a marshmallow-filled adventure with pillow fights, marshmallow towers, and lots of laughs. In the end, IBM and his friends agreed: whether it&#8217;s chips or marshmallows, any party is fun when friends are around!</p>
    </div>
    <div class="vg4-story-meta">
      <p class="vg4-story-meta-item">Model<span>GPT-4</span></p>
      <p class="vg4-story-meta-item">Temperature<span>0.9</span></p>
      <p class="vg4-story-meta-item">Word Count<span>~150 words</span></p>
      <p class="vg4-story-meta-item">Nodes Used<span>5</span></p>
    </div>
  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg4-interview-section">
  <p class="vg4-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg4-qa-list">

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Define</span><br>What is an AI agent?</div>
      <div class="vg4-qa-a"><strong>An autonomous module</strong> that combines a language model, logic, and optionally external tools to complete a task without step-by-step human instruction. It receives a goal, plans sub-steps, and executes them independently.
        <div class="vg4-pills"><span class="vg4-pill t">Autonomous</span><span class="vg4-pill t">Goal-driven</span><span class="vg4-pill">Tool-using</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal vg4-d1">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Explain</span><br>What is the Supervisor / Worker pattern?</div>
      <div class="vg4-qa-a">A <strong>Supervisor node</strong> coordinates the overall workflow and delegates tasks to <strong>Worker nodes</strong>, each of which handles one focused sub-task. This mirrors microservices architecture — single responsibility per agent, composable into larger pipelines.
        <div class="vg4-pills"><span class="vg4-pill t">Supervisor = orchestrator</span><span class="vg4-pill t">Worker = specialist</span><span class="vg4-pill a">Single responsibility</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Define</span><br>What does temperature control in an LLM?</div>
      <div class="vg4-qa-a"><strong>Randomness in token sampling.</strong> Low temperature (0.1–0.4) = deterministic, factual, conservative outputs. High temperature (0.8–1.0) = creative, surprising, occasionally incoherent. For storytelling, 0.9 hits the sweet spot of imaginative without losing coherence.
        <div class="vg4-pills"><span class="vg4-pill">Low = deterministic</span><span class="vg4-pill a">High = creative</span><span class="vg4-pill t">0.9 for stories</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal vg4-d1">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Compare</span><br>No-code (Flowise) vs code-first (LangChain) — when to use which?</div>
      <div class="vg4-qa-a">Use <strong>Flowise</strong> for rapid prototyping, demos, non-developer stakeholders, or when the workflow is straightforward and visual. Use <strong>LangChain / LangGraph in code</strong> when you need version control, CI/CD, complex branching, custom tool integrations, or production-grade observability.
        <div class="vg4-pills"><span class="vg4-pill t">Flowise = prototype fast</span><span class="vg4-pill a">LangChain = production</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Explain</span><br>Why split story generation and title extraction into separate nodes?</div>
      <div class="vg4-qa-a"><strong>Focused prompts outperform omnibus prompts.</strong> A prompt that must write a story, extract a title, and format output all at once tends to trade off quality across tasks. Separate nodes give each sub-task its own context window, model parameters, and success criteria — and makes each step independently testable and replaceable.
        <div class="vg4-pills"><span class="vg4-pill t">One node, one job</span><span class="vg4-pill">Better quality</span><span class="vg4-pill a">Independently testable</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal vg4-d1">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Use Case</span><br>What other use cases suit a Flowise multi-agent setup?</div>
      <div class="vg4-qa-a"><strong>Any pipeline with distinct sequential sub-tasks:</strong> customer support (intent classification → knowledge retrieval → response drafting), content pipelines (research → outline → write → SEO optimize), data workflows (extract → validate → transform → summarize).
        <div class="vg4-pills"><span class="vg4-pill t">Customer support</span><span class="vg4-pill t">Content pipelines</span><span class="vg4-pill t">Data workflows</span><span class="vg4-pill">Code review agents</span></div>
      </div>
    </div>

    <div class="vg4-qa-item vg4-reveal">
      <div class="vg4-qa-q"><span class="vg4-q-badge">Gotcha</span><br>What are the main limits of no-code agent builders?</div>
      <div class="vg4-qa-a">Three key limitations: <strong>(1) Observability</strong> — debugging visual workflows is harder than reading stack traces. <strong>(2) Version control</strong> — workflow JSON doesn&#8217;t diff cleanly in Git. <strong>(3) Custom logic</strong> — complex conditional branching, stateful memory, and custom tool integrations are much easier in code-first frameworks.
        <div class="vg4-pills"><span class="vg4-pill a">Hard to debug</span><span class="vg4-pill a">No clean Git diff</span><span class="vg4-pill a">Limited branching</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg4-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <a href="https://vijay-gokarn.com" class="vg4-back-btn">Back to Blog ↗</a>
</div>

</div><!-- /vg4 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg4-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg4-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>
<p>The post <a href="https://vijay-gokarn.com/creating-ai-storytelling-agents-using-flowise-a-step-by-step-guide/">Creating AI Storytelling Agents Using Flowise: A Step-by-Step Guide</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">227</post-id>	</item>
		<item>
		<title>Long Context LLM Comparison</title>
		<link>https://vijay-gokarn.com/long-context-llm-comparison/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=long-context-llm-comparison</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Mon, 19 Aug 2024 21:31:01 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=192</guid>

					<description><![CDATA[<p>GenAI Mastery Series · Long Context LLMs · Deep Dive Long Context LLMs — How They Work, How They Compare, and When to Use Which Models CoveredGPT-4 · Claude 2 · Mistral · PaLM 2 · LLaMA 2 FocusContext Length · Architecture · Use Cases 128k GPT-4 max tokens 100k Claude 2 max tokens 32k [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/long-context-llm-comparison/">Long Context LLM Comparison</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg3 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg3 *, .vg3 *::before, .vg3 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg3-hero { background: var(--ink); padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg3-hero::before {
  content: '∞'; font-family: 'Cormorant Garamond', serif; font-size: 22rem;
  font-weight: 300; color: rgba(255,255,255,0.025); position: absolute;
  right: 2rem; top: 50%; transform: translateY(-50%); line-height: 1; pointer-events: none;
}
.vg3-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg3-eyebrow {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.vg3-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg3-hero h1 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem);
  font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em;
  margin-bottom: 1.5rem; max-width: 26ch;
}
.vg3-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg3-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg3-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg3-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* STAT BAND */
.vg3-stat-band {
  background: var(--teal); display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px; background-color: var(--teal);
}
.vg3-stat-item { background: var(--teal); padding: 1.75rem 2rem; }
.vg3-stat-n {
  font-family: 'Cormorant Garamond', serif; font-size: 2.4rem; font-weight: 300;
  line-height: 1; color: var(--paper); letter-spacing: -0.03em; margin-bottom: 0.3rem;
}
.vg3-stat-l { font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(247,244,239,0.55); }

/* INTRO */
.vg3-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg3-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg3-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg3-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg3-section { margin-bottom: 3.5rem; }
.vg3-section-label {
  font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal); font-weight: 500; margin-bottom: 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.vg3-section-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg3-section h2 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1.25rem;
}
.vg3-section h2 em { font-style: italic; color: var(--teal); }
.vg3-section p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg3-section p strong { color: var(--ink); font-weight: 500; }
.vg3-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg3-callout {
  background: var(--paper-dark); border-left: 3px solid var(--amber);
  padding: 1.25rem 1.5rem; margin: 1.5rem 0;
  font-size: 0.87rem; line-height: 1.8; color: var(--charcoal);
}
.vg3-callout strong { color: var(--amber); font-weight: 500; }
.vg3-callout.teal { border-color: var(--teal); }
.vg3-callout.teal strong { color: var(--teal); }

/* HOW IT WORKS - 4 PILLARS */
.vg3-how-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem; margin: 1.5rem 0; }
.vg3-how-card { background: var(--paper); border: 0.5px solid var(--border-strong); padding: 1.75rem; position: relative; }
.vg3-how-card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: var(--teal); }
.vg3-how-card .vg3-how-num { font-family: 'Cormorant Garamond', serif; font-size: 2.2rem; font-weight: 300; color: var(--border-strong); line-height: 1; margin-bottom: 0.5rem; letter-spacing: -0.03em; }
.vg3-how-card h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.2rem; font-weight: 400; color: var(--ink); margin-bottom: 0.5rem; }
.vg3-how-card p { font-size: 0.83rem; line-height: 1.75; color: var(--charcoal); font-weight: 300; }

/* MODEL CARDS */
.vg3-models-section { background: var(--paper-dark); padding: 4rem; }
.vg3-models-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg3-models-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg3-models-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg3-models-section > h2 em { font-style: italic; color: var(--teal); }
.vg3-model-list { display: flex; flex-direction: column; gap: 1.25rem; }
.vg3-model-card { background: var(--paper); border: 0.5px solid var(--border); display: grid; grid-template-columns: 220px 1fr; }
.vg3-model-left { padding: 1.75rem; border-right: 0.5px solid var(--border); position: relative; overflow: hidden; }
.vg3-model-left::before { content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%; }
.vg3-model-card:nth-child(1) .vg3-model-left::before { background: #10a37f; }
.vg3-model-card:nth-child(2) .vg3-model-left::before { background: #7c3aed; }
.vg3-model-card:nth-child(3) .vg3-model-left::before { background: #d97706; }
.vg3-model-card:nth-child(4) .vg3-model-left::before { background: #1a73e8; }
.vg3-model-card:nth-child(5) .vg3-model-left::before { background: #0668e1; }
.vg3-model-provider { font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.4rem; font-weight: 400; }
.vg3-model-name { font-family: 'Cormorant Garamond', serif; font-size: 1.5rem; font-weight: 400; color: var(--ink); line-height: 1.1; margin-bottom: 1rem; }
.vg3-ctx-badge {
  display: inline-block; font-family: 'DM Mono', monospace; font-size: 0.75rem;
  font-weight: 400; color: var(--teal); background: var(--teal-muted);
  padding: 0.3rem 0.75rem; letter-spacing: 0.04em; margin-bottom: 0.5rem;
}
.vg3-arch-label { font-size: 0.68rem; color: var(--muted); font-weight: 300; letter-spacing: 0.04em; }
.vg3-model-right { padding: 1.75rem; }
.vg3-model-right-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.vg3-model-col-head { font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); font-weight: 500; margin-bottom: 0.6rem; }
.vg3-model-col-head.strength { color: var(--teal); }
.vg3-model-col-head.challenge { color: var(--amber); }
.vg3-model-list-inner { list-style: none; display: flex; flex-direction: column; gap: 0.45rem; }
.vg3-model-list-inner li { font-size: 0.8rem; line-height: 1.6; color: var(--charcoal); font-weight: 300; padding-left: 1rem; position: relative; }
.vg3-model-list-inner li.s::before { content: '+'; position: absolute; left: 0; color: var(--teal); font-weight: 500; }
.vg3-model-list-inner li.c::before { content: '⚠'; position: absolute; left: 0; color: var(--amber); font-size: 0.65rem; top: 0.15rem; }
.vg3-use-cases { margin-top: 1.25rem; border-top: 0.5px solid var(--border); padding-top: 1rem; }
.vg3-use-case-label { font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.5rem; }
.vg3-use-case-pills { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.vg3-use-pill { font-size: 0.68rem; padding: 0.2rem 0.65rem; background: var(--paper-dark); border: 0.5px solid var(--border); color: var(--charcoal); letter-spacing: 0.04em; }

/* COMPARISON TABLE */
.vg3-table-wrap { overflow-x: auto; margin: 1.5rem 0; }
.vg3-table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
.vg3-table th { background: var(--ink); color: var(--paper); font-family: 'DM Sans', sans-serif; font-weight: 400; font-size: 0.65rem; letter-spacing: 0.14em; text-transform: uppercase; padding: 0.75rem 1rem; text-align: left; }
.vg3-table td { padding: 0.75rem 1rem; border-bottom: 0.5px solid var(--border); color: var(--charcoal); vertical-align: top; line-height: 1.55; }
.vg3-table tr:nth-child(even) td { background: var(--paper-dark); }
.vg3-table td strong { color: var(--ink); font-weight: 500; }
.vg3-chip { display: inline-block; font-size: 0.65rem; letter-spacing: 0.06em; padding: 0.2rem 0.55rem; border-radius: 2px; font-weight: 400; }
.vg3-chip-green { background: var(--teal-muted); color: var(--teal); }
.vg3-chip-amber { background: var(--amber-muted); color: var(--amber); }
.vg3-chip-gray  { background: var(--paper-dark); color: var(--muted); border: 0.5px solid var(--border); }

/* CONSIDERATIONS */
.vg3-consider-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; margin: 1.5rem 0; }
.vg3-consider-card { padding: 1.75rem; border: 0.5px solid var(--border-strong); background: var(--paper); position: relative; }
.vg3-consider-card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 3px; }
.vg3-consider-card:nth-child(1)::before { background: var(--teal); }
.vg3-consider-card:nth-child(2)::before { background: var(--amber); }
.vg3-consider-card:nth-child(3)::before { background: var(--muted); }
.vg3-consider-card h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.15rem; font-weight: 400; color: var(--ink); margin-bottom: 0.5rem; }
.vg3-consider-card p { font-size: 0.82rem; line-height: 1.7; color: var(--charcoal); font-weight: 300; }

/* INTERVIEW */
.vg3-interview-section { background: var(--ink); padding: 4rem; }
.vg3-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg3-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg3-interview-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg3-interview-section h2 em { font-style: italic; color: var(--amber-light); }
.vg3-qa-list { display: flex; flex-direction: column; }
.vg3-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(247,244,239,0.1); align-items: start; }
.vg3-qa-item:last-child { border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg3-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--paper); line-height: 1.4; }
.vg3-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg3-qa-a { font-size: 0.83rem; line-height: 1.8; color: rgba(247,244,239,0.65); font-weight: 300; }
.vg3-qa-a strong { color: var(--amber-light); font-weight: 400; }
.vg3-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(247,244,239,0.08); padding: 0.1rem 0.35rem; color: var(--paper); }
.vg3-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg3-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); }
.vg3-pill.t { border-color: var(--teal-light); color: var(--teal-light); }
.vg3-pill.a { border-color: var(--amber-light); color: var(--amber-light); }

/* FOOTER */
.vg3-footer { background: var(--charcoal); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; }
.vg3-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg3-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg3-back-btn { display: inline-block; padding: 0.65rem 1.75rem; background: var(--teal); color: var(--paper); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }

/* REVEAL */
.vg3-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg3-reveal.vg3-vis { opacity: 1; transform: translateY(0); }
.vg3-d1 { transition-delay: 0.1s; } .vg3-d2 { transition-delay: 0.2s; } .vg3-d3 { transition-delay: 0.3s; }
</style>

<div class="vg3">

<!-- HERO -->
<div class="vg3-hero">
  <div class="vg3-hero-inner">
    <p class="vg3-eyebrow">GenAI Mastery Series · Long Context LLMs · Deep Dive</p>
    <h1>Long Context LLMs — How They Work, How They Compare, and <em>When to Use Which</em></h1>
    <div class="vg3-meta-row">
      <p class="vg3-meta">Models Covered<span>GPT-4 · Claude 2 · Mistral · PaLM 2 · LLaMA 2</span></p>
      <p class="vg3-meta">Focus<span>Context Length · Architecture · Use Cases</span></p>
    </div>
  </div>
</div>

<!-- STAT BAND -->
<div class="vg3-stat-band">
  <div class="vg3-stat-item vg3-reveal"><div class="vg3-stat-n">128k</div><div class="vg3-stat-l">GPT-4 max tokens</div></div>
  <div class="vg3-stat-item vg3-reveal vg3-d1"><div class="vg3-stat-n">100k</div><div class="vg3-stat-l">Claude 2 max tokens</div></div>
  <div class="vg3-stat-item vg3-reveal vg3-d2"><div class="vg3-stat-n">32k</div><div class="vg3-stat-l">PaLM 2 max tokens</div></div>
  <div class="vg3-stat-item vg3-reveal vg3-d3"><div class="vg3-stat-n">4k</div><div class="vg3-stat-l">LLaMA 2 base tokens</div></div>
</div>

<!-- INTRO BAND -->
<div class="vg3-intro">
  <p>A <strong>long context LLM</strong> can process and remember extended pieces of text or conversation history — maintaining continuity and coherence over longer interactions. This makes them particularly powerful for tasks that require understanding context across documents, extended dialogues, or complex multi-step reasoning.</p>
</div>

<!-- BODY -->
<div class="vg3-body">

  <!-- HOW IT WORKS -->
  <div class="vg3-section vg3-reveal">
    <p class="vg3-section-label">Fundamentals</p>
    <h2>How long context LLMs <em>actually work</em></h2>
    <p>Four core capabilities define what makes a model &#8220;long context&#8221; — and why it matters for real-world applications.</p>
    <div class="vg3-how-grid">
      <div class="vg3-how-card vg3-reveal vg3-d1">
        <div class="vg3-how-num">01</div>
        <h3>Extended Memory</h3>
        <p>These models hold a larger amount of text in working memory, allowing them to refer back to earlier parts of a conversation or document. Critical for maintaining context in complex, multi-turn discussions.</p>
      </div>
      <div class="vg3-how-card vg3-reveal vg3-d2">
        <div class="vg3-how-num">02</div>
        <h3>Context Awareness</h3>
        <p>The model uses extended context to provide more accurate and relevant responses, understanding nuances and how the conversation shifts over time — not just the last few exchanges.</p>
      </div>
      <div class="vg3-how-card vg3-reveal vg3-d1">
        <div class="vg3-how-num">03</div>
        <h3>Coherence</h3>
        <p>Long context LLMs strive to maintain logical coherence across many interactions, avoiding the contradictions and misunderstandings that arise in shorter-context models when earlier context is lost.</p>
      </div>
      <div class="vg3-how-card vg3-reveal vg3-d2">
        <div class="vg3-how-num">04</div>
        <h3>Broad Applications</h3>
        <p>Customer support, storytelling, technical support, legal document review, code review across large codebases — any scenario where understanding and maintaining context over time is critical.</p>
      </div>
    </div>
  </div>

  <hr class="vg3-divider">

  <!-- KEY CONSIDERATIONS -->
  <div class="vg3-section vg3-reveal">
    <p class="vg3-section-label">What Matters</p>
    <h2>Three factors that <em>define performance</em></h2>
    <div class="vg3-consider-grid">
      <div class="vg3-consider-card vg3-reveal vg3-d1">
        <h3>Context Length</h3>
        <p>Longer context allows models to maintain coherence across larger chunks of text. But more tokens in context means more computational resources — there is always a trade-off between window size and speed.</p>
      </div>
      <div class="vg3-consider-card vg3-reveal vg3-d2">
        <h3>Efficiency</h3>
        <p>Processing long contexts without a significant performance drop is crucial, especially for real-time applications. Architecture innovations like sliding window attention and sparse transformers directly address this.</p>
      </div>
      <div class="vg3-consider-card vg3-reveal vg3-d3">
        <h3>Use Case Fit</h3>
        <p>Each model has specific strengths. Whether you need creative writing, technical documentation, ethical guardrails, multimodal capabilities, or open-source flexibility — the right model depends on the task.</p>
      </div>
    </div>
  </div>

</div>

<!-- MODEL DEEP DIVES -->
<div class="vg3-models-section">
  <p class="vg3-models-eyebrow">Model Comparison</p>
  <h2>Five leading long context <em>LLMs compared</em></h2>
  <div class="vg3-model-list">

    <!-- GPT-4 -->
    <div class="vg3-model-card vg3-reveal">
      <div class="vg3-model-left">
        <p class="vg3-model-provider">OpenAI</p>
        <p class="vg3-model-name">GPT-4</p>
        <span class="vg3-ctx-badge">128k tokens</span>
        <p class="vg3-arch-label">Transformer · Proprietary</p>
      </div>
      <div class="vg3-model-right">
        <div class="vg3-model-right-grid">
          <div>
            <p class="vg3-model-col-head strength">Strengths</p>
            <ul class="vg3-model-list-inner">
              <li class="s">Excellent at complex, coherent long-form text</li>
              <li class="s">Strong context retention across long conversations</li>
              <li class="s">Widely applicable — writing, coding, research</li>
              <li class="s">Largest ecosystem and third-party integrations</li>
            </ul>
          </div>
          <div>
            <p class="vg3-model-col-head challenge">Challenges</p>
            <ul class="vg3-model-list-inner">
              <li class="c">Computationally intensive</li>
              <li class="c">Potential latency on very long inputs</li>
              <li class="c">Proprietary — no fine-tuning access</li>
            </ul>
          </div>
        </div>
        <div class="vg3-use-cases">
          <p class="vg3-use-case-label">Best Use Cases</p>
          <div class="vg3-use-case-pills">
            <span class="vg3-use-pill">Writing Assistants</span>
            <span class="vg3-use-pill">Dialogue Systems</span>
            <span class="vg3-use-pill">Long Doc Summarization</span>
            <span class="vg3-use-pill">Complex Automation</span>
          </div>
        </div>
      </div>
    </div>

    <!-- Claude 2 -->
    <div class="vg3-model-card vg3-reveal vg3-d1">
      <div class="vg3-model-left">
        <p class="vg3-model-provider">Anthropic</p>
        <p class="vg3-model-name">Claude 2</p>
        <span class="vg3-ctx-badge">100k tokens</span>
        <p class="vg3-arch-label">Transformer · Safety-optimized</p>
      </div>
      <div class="vg3-model-right">
        <div class="vg3-model-right-grid">
          <div>
            <p class="vg3-model-col-head strength">Strengths</p>
            <ul class="vg3-model-list-inner">
              <li class="s">Designed for ethical use and AI alignment</li>
              <li class="s">Coherent context over extended discussions</li>
              <li class="s">Strong on sensitive, high-stakes interactions</li>
              <li class="s">Excellent at processing entire documents at once</li>
            </ul>
          </div>
          <div>
            <p class="vg3-model-col-head challenge">Challenges</p>
            <ul class="vg3-model-list-inner">
              <li class="c">Less widely tested than GPT-4 at time of release</li>
              <li class="c">Can be more conservative on edge cases</li>
            </ul>
          </div>
        </div>
        <div class="vg3-use-cases">
          <p class="vg3-use-case-label">Best Use Cases</p>
          <div class="vg3-use-case-pills">
            <span class="vg3-use-pill">Conversational AI</span>
            <span class="vg3-use-pill">Content Moderation</span>
            <span class="vg3-use-pill">Legal / Compliance</span>
            <span class="vg3-use-pill">Summarization</span>
          </div>
        </div>
      </div>
    </div>

    <!-- Mistral -->
    <div class="vg3-model-card vg3-reveal">
      <div class="vg3-model-left">
        <p class="vg3-model-provider">Mistral AI</p>
        <p class="vg3-model-name">Mistral</p>
        <span class="vg3-ctx-badge">Extended (varies)</span>
        <p class="vg3-arch-label">Transformer · Efficient architecture</p>
      </div>
      <div class="vg3-model-right">
        <div class="vg3-model-right-grid">
          <div>
            <p class="vg3-model-col-head strength">Strengths</p>
            <ul class="vg3-model-list-inner">
              <li class="s">Efficient long context with reduced compute overhead</li>
              <li class="s">Strong long-form content generation</li>
              <li class="s">Sliding window attention — better memory use</li>
              <li class="s">Open weights available for self-hosting</li>
            </ul>
          </div>
          <div>
            <p class="vg3-model-col-head challenge">Challenges</p>
            <ul class="vg3-model-list-inner">
              <li class="c">Newer entrant — still gathering real-world benchmarks</li>
              <li class="c">Context length varies by variant</li>
            </ul>
          </div>
        </div>
        <div class="vg3-use-cases">
          <p class="vg3-use-case-label">Best Use Cases</p>
          <div class="vg3-use-case-pills">
            <span class="vg3-use-pill">Narrative Generation</span>
            <span class="vg3-use-pill">Technical Docs</span>
            <span class="vg3-use-pill">Research Synthesis</span>
            <span class="vg3-use-pill">Self-hosted Apps</span>
          </div>
        </div>
      </div>
    </div>

    <!-- PaLM 2 -->
    <div class="vg3-model-card vg3-reveal vg3-d1">
      <div class="vg3-model-left">
        <p class="vg3-model-provider">Google</p>
        <p class="vg3-model-name">PaLM 2</p>
        <span class="vg3-ctx-badge">~32k tokens</span>
        <p class="vg3-arch-label">Pathways Architecture · Multimodal</p>
      </div>
      <div class="vg3-model-right">
        <div class="vg3-model-right-grid">
          <div>
            <p class="vg3-model-col-head strength">Strengths</p>
            <ul class="vg3-model-list-inner">
              <li class="s">Strong multilingual and multimodal performance</li>
              <li class="s">Deep integration with Google Search and Knowledge Graph</li>
              <li class="s">Excellent at translation and cross-lingual tasks</li>
              <li class="s">Contextually rich long-form generation</li>
            </ul>
          </div>
          <div>
            <p class="vg3-model-col-head challenge">Challenges</p>
            <ul class="vg3-model-list-inner">
              <li class="c">Smaller context window than GPT-4 / Claude 2</li>
              <li class="c">Balancing multimodal vs long-context performance</li>
            </ul>
          </div>
        </div>
        <div class="vg3-use-cases">
          <p class="vg3-use-case-label">Best Use Cases</p>
          <div class="vg3-use-case-pills">
            <span class="vg3-use-pill">Multilingual Tasks</span>
            <span class="vg3-use-pill">Translation</span>
            <span class="vg3-use-pill">Multimodal Apps</span>
            <span class="vg3-use-pill">Research Tools</span>
          </div>
        </div>
      </div>
    </div>

    <!-- LLaMA 2 -->
    <div class="vg3-model-card vg3-reveal">
      <div class="vg3-model-left">
        <p class="vg3-model-provider">Meta</p>
        <p class="vg3-model-name">LLaMA 2</p>
        <span class="vg3-ctx-badge">4k tokens (base)</span>
        <p class="vg3-arch-label">Transformer · Open-source</p>
      </div>
      <div class="vg3-model-right">
        <div class="vg3-model-right-grid">
          <div>
            <p class="vg3-model-col-head strength">Strengths</p>
            <ul class="vg3-model-list-inner">
              <li class="s">Fully open-source and customizable</li>
              <li class="s">Efficient, runs on modest hardware</li>
              <li class="s">Strong research and academic community</li>
              <li class="s">Extensible — context length expandable via fine-tuning</li>
            </ul>
          </div>
          <div>
            <p class="vg3-model-col-head challenge">Challenges</p>
            <ul class="vg3-model-list-inner">
              <li class="c">Limited base context vs proprietary models</li>
              <li class="c">Requires significant setup for production use</li>
            </ul>
          </div>
        </div>
        <div class="vg3-use-cases">
          <p class="vg3-use-case-label">Best Use Cases</p>
          <div class="vg3-use-case-pills">
            <span class="vg3-use-pill">Research</span>
            <span class="vg3-use-pill">Open-source Projects</span>
            <span class="vg3-use-pill">Academic Work</span>
            <span class="vg3-use-pill">Custom Fine-tuning</span>
          </div>
        </div>
      </div>
    </div>

  </div>
</div>

<!-- COMPARISON TABLE -->
<div class="vg3-body">
  <div class="vg3-section vg3-reveal">
    <p class="vg3-section-label">At a Glance</p>
    <h2>Side-by-side <em>quick reference</em></h2>
    <div class="vg3-table-wrap">
      <table class="vg3-table">
        <thead><tr><th>Model</th><th>Provider</th><th>Max Context</th><th>Open Source</th><th>Key Edge</th><th>Main Constraint</th></tr></thead>
        <tbody>
          <tr>
            <td><strong>GPT-4</strong></td>
            <td>OpenAI</td>
            <td><span class="vg3-chip vg3-chip-green">128k tokens</span></td>
            <td><span class="vg3-chip vg3-chip-gray">No</span></td>
            <td>Best overall coherence, ecosystem</td>
            <td>Compute cost, latency</td>
          </tr>
          <tr>
            <td><strong>Claude 2</strong></td>
            <td>Anthropic</td>
            <td><span class="vg3-chip vg3-chip-green">100k tokens</span></td>
            <td><span class="vg3-chip vg3-chip-gray">No</span></td>
            <td>Safety, alignment, ethical use</td>
            <td>Less benchmark data vs GPT-4</td>
          </tr>
          <tr>
            <td><strong>Mistral</strong></td>
            <td>Mistral AI</td>
            <td><span class="vg3-chip vg3-chip-amber">Varies</span></td>
            <td><span class="vg3-chip vg3-chip-green">Yes (weights)</span></td>
            <td>Efficient compute, self-hostable</td>
            <td>Newer — fewer benchmarks</td>
          </tr>
          <tr>
            <td><strong>PaLM 2</strong></td>
            <td>Google</td>
            <td><span class="vg3-chip vg3-chip-amber">~32k tokens</span></td>
            <td><span class="vg3-chip vg3-chip-gray">No</span></td>
            <td>Multilingual, multimodal, Search integration</td>
            <td>Smaller context window</td>
          </tr>
          <tr>
            <td><strong>LLaMA 2</strong></td>
            <td>Meta</td>
            <td><span class="vg3-chip vg3-chip-amber">4k base</span></td>
            <td><span class="vg3-chip vg3-chip-green">Yes (fully open)</span></td>
            <td>Customizable, runs on consumer hardware</td>
            <td>Shortest base context</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div class="vg3-callout">
      <strong>Bottom Line:</strong> GPT-4 leads for raw context management. Claude 2 wins where safety and ethical handling matter. Mistral and LLaMA 2 are the open-source options for teams that need full control. PaLM 2 is the pick for multilingual and multimodal workloads.
    </div>
  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg3-interview-section">
  <p class="vg3-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg3-qa-list">

    <div class="vg3-qa-item vg3-reveal">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Define</span><br>What is a long context LLM?</div>
      <div class="vg3-qa-a"><strong>A model with a large token window</strong> — the amount of text it can hold in memory and reason over at once. Longer windows allow maintaining coherence over extended documents or multi-turn conversations without losing earlier context.
        <div class="vg3-pills"><span class="vg3-pill t">Token window = memory</span><span class="vg3-pill">Longer = more coherent</span><span class="vg3-pill a">Tradeoff: compute cost</span></div>
      </div>
    </div>

    <div class="vg3-qa-item vg3-reveal vg3-d1">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Explain</span><br>What is a &#8220;token&#8221; and why does window size matter?</div>
      <div class="vg3-qa-a">A <strong>token</strong> is roughly ¾ of a word (~4 characters). 128k tokens ≈ ~100,000 words ≈ a full novel. Window size determines how much of a document or conversation the model can &#8220;see&#8221; at once. Once context overflows the window, earlier information is lost.
        <div class="vg3-pills"><span class="vg3-pill t">~4 chars per token</span><span class="vg3-pill">128k ≈ 100k words</span><span class="vg3-pill a">Overflow = forgetting</span></div>
      </div>
    </div>

    <div class="vg3-qa-item vg3-reveal">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Compare</span><br>GPT-4 vs Claude 2 — when would you pick each?</div>
      <div class="vg3-qa-a">Pick <strong>GPT-4</strong> for breadth, ecosystem integrations, and the widest context window (128k). Pick <strong>Claude 2</strong> when safety, ethical handling, or processing very large documents in one shot matters (100k tokens, strong alignment focus).
        <div class="vg3-pills"><span class="vg3-pill t">GPT-4 = breadth + ecosystem</span><span class="vg3-pill a">Claude 2 = safety + alignment</span></div>
      </div>
    </div>

    <div class="vg3-qa-item vg3-reveal vg3-d1">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Gotcha</span><br>Why doesn&#8217;t bigger context always mean better results?</div>
      <div class="vg3-qa-a">The <strong>&#8220;lost in the middle&#8221; problem</strong> — models tend to attend best to the beginning and end of a long context, with degraded recall in the middle. More tokens also means <strong>quadratic compute cost</strong> in standard attention, increasing latency significantly.
        <div class="vg3-pills"><span class="vg3-pill a">Lost in the middle</span><span class="vg3-pill a">Quadratic attention cost</span><span class="vg3-pill">Latency tradeoff</span></div>
      </div>
    </div>

    <div class="vg3-qa-item vg3-reveal">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Use Case</span><br>When would you use LLaMA 2 over a proprietary model?</div>
      <div class="vg3-qa-a">When you need <strong>data privacy</strong> (no external API calls), <strong>full customization</strong> (fine-tune on your own data), <strong>cost control</strong> (no per-token pricing), or you&#8217;re in a <strong>regulated industry</strong> that prohibits sending data to third-party vendors.
        <div class="vg3-pills"><span class="vg3-pill t">Data privacy</span><span class="vg3-pill t">Fine-tuning control</span><span class="vg3-pill t">No API cost</span><span class="vg3-pill a">Regulated industries</span></div>
      </div>
    </div>

    <div class="vg3-qa-item vg3-reveal vg3-d1">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Define</span><br>What is RAG and how does it relate to context length?</div>
      <div class="vg3-qa-a"><strong>Retrieval-Augmented Generation</strong> — instead of stuffing an entire knowledge base into the context window, you retrieve only the relevant chunks and inject them. RAG is often a better alternative to brute-force long context: cheaper, faster, and avoids the &#8220;lost in the middle&#8221; problem.
        <div class="vg3-pills"><span class="vg3-pill t">Retrieve → Inject → Generate</span><span class="vg3-pill">Alternative to long context</span><span class="vg3-pill a">Cheaper at scale</span></div>
      </div>
    </div>

    <div class="vg3-qa-item vg3-reveal">
      <div class="vg3-qa-q"><span class="vg3-q-badge">Name</span><br>Three applications where long context LLMs are essential</div>
      <div class="vg3-qa-a"><strong>1. Legal / contract review</strong> — entire agreements must be held in context simultaneously. <strong>2. Codebase analysis</strong> — understanding how functions across many files interact. <strong>3. Medical record summarization</strong> — patient history spanning hundreds of pages must be synthesized in one pass.
        <div class="vg3-pills"><span class="vg3-pill t">Legal review</span><span class="vg3-pill t">Code analysis</span><span class="vg3-pill t">Medical records</span><span class="vg3-pill">Long doc summarization</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg3-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <a href="https://vijay-gokarn.com" class="vg3-back-btn">Back to Blog ↗</a>
</div>

</div><!-- /vg3 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg3-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg3-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>
<p>The post <a href="https://vijay-gokarn.com/long-context-llm-comparison/">Long Context LLM Comparison</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">192</post-id>	</item>
		<item>
		<title>Long Context LLM&#8217;s vs RAG</title>
		<link>https://vijay-gokarn.com/llms-large-language-context-vs-rag/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=llms-large-language-context-vs-rag</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Mon, 19 Aug 2024 11:47:57 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[long-context-llm]]></category>
		<category><![CDATA[RAG]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=168</guid>

					<description><![CDATA[<p>Retrieval-Augmented Generation. It is a method that combines the strengths of retrieval-based models and generative models to improve the performance and accuracy of AI systems, particularly in natural language processing tasks. How RAG Works: Applications: RAG models help in grounding the limitations of generative AI and removing the hallucinations from the responses. Why We Needed [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/llms-large-language-context-vs-rag/">Long Context LLM&#8217;s vs RAG</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img decoding="async" width="1365" height="768" loading="lazy" src="https://i0.wp.com/vijay-gokarn.com/wp-content/uploads/2024/08/image-2.png?fit=1024%2C576&amp;ssl=1" alt="" class="wp-image-270" srcset="https://i0.wp.com/vijay-gokarn.com/wp-content/uploads/2024/08/image-2.png?w=1365&amp;ssl=1 1365w, https://i0.wp.com/vijay-gokarn.com/wp-content/uploads/2024/08/image-2.png?resize=300%2C169&amp;ssl=1 300w, https://i0.wp.com/vijay-gokarn.com/wp-content/uploads/2024/08/image-2.png?resize=1024%2C576&amp;ssl=1 1024w, https://i0.wp.com/vijay-gokarn.com/wp-content/uploads/2024/08/image-2.png?resize=768%2C432&amp;ssl=1 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<p class=""><strong>Retrieval-Augmented Generation</strong>. It is a method that combines the strengths of retrieval-based models and generative models to improve the performance and accuracy of AI systems, particularly in natural language processing tasks.</p>



<h3 class="wp-block-heading">How RAG Works:</h3>



<ol class="wp-block-list">
<li class=""><strong>Retrieval Step</strong>: The system first retrieves relevant documents or pieces of information from a large corpus based on the input query. This retrieval process helps to bring in contextually relevant information that the generative model might need to generate a more accurate response.</li>



<li class=""><strong>Generation Step</strong>: After retrieving the relevant information, the generative model (often a large language model like GPT) uses this information as a basis to generate a coherent and contextually appropriate response.</li>
</ol>



<p class=""></p>



<h3 class="wp-block-heading">Applications:</h3>



<ul class="wp-block-list">
<li class=""><strong>Question Answering</strong>: RAG models can be used to answer questions by retrieving relevant text from a knowledge base and then generating an answer based on that information.</li>



<li class=""><strong>Chatbots</strong>: In conversational AI, RAG models help to provide more accurate and context-aware responses by pulling in relevant information before generating a reply.</li>



<li class=""><strong>Content Creation</strong>: For generating content such as articles, reports, or summaries, RAG models can retrieve relevant data and then generate content that integrates this information effectively.</li>
</ul>



<p class="">RAG models help in grounding the limitations of generative AI and removing the hallucinations from the responses.</p>



<h3 class=" wp-block-heading">Why We Needed RAG</h3>



<p class="">Before the advent of long context LLMs, traditional language models had severe limitations in processing and understanding large amounts of text. This constraint hindered their ability to perform tasks like:</p>



<ul class="wp-block-list">
<li class="">Summarizing lengthy documents</li>



<li class="">Answering complex questions requiring extensive knowledge</li>



<li class="">Generating text based on large datasets</li>
</ul>



<p class=""></p>



<p class="">RAG emerged as a solution to this problem. By retrieving relevant information from external knowledge bases, RAG could effectively expand the model&#8217;s access to information, improving its performance on these tasks.</p>



<h3 class=" wp-block-heading">Long Context LLMs New Kid on the block</h3>



<p class="">With the development of long context LLMs, the landscape has changed significantly. These models can now process and understand much larger amounts of text directly, reducing the reliance on external knowledge sources.</p>



<h3 class="wp-block-heading">Long Context LLMs</h3>



<p class=""></p>



<ul class="wp-block-list">
<li class=""><strong>Core concept:</strong> Directly process and understand a larger amount of text within a single input.</li>



<li class=""><strong>Strengths:</strong>
<ul class="wp-block-list">
<li class="">Can capture complex relationships within the text. &nbsp; </li>



<li class="">Potentially better at understanding nuances and context.</li>
</ul>
</li>



<li class=""><strong>Weaknesses:</strong>
<ul class="wp-block-list">
<li class="">Limited by the maximum context window size.</li>



<li class="">Can be computationally expensive for very long inputs</li>
</ul>
</li>
</ul>



<p class=""></p>



<p class=""><strong>This has led to a debate about whether long context LLMs will render RAG obsolete.</strong> Here is <a href="https://vijay-gokarn.com/long-context-llm-comparison/">comparison of long context LLM by major players</a></p>



<p class=""></p>



<h3 class=" wp-block-heading">The Reality: A Complex Interplay</h3>



<p class="">While long context LLMs are impressive, they are not a panacea. Here&#8217;s why:</p>



<ul class="wp-block-list">
<li class=""><strong>Computational Costs:</strong> Processing extremely long contexts is computationally expensive and time-consuming.</li>



<li class=""><strong>Attention Limitations:</strong> Attention mechanisms, essential for long context models, can still struggle with capturing complex relationships within massive amounts of text.</li>



<li class=""><strong>Information Overload:</strong> Feeding an LLM with an overwhelming amount of information can lead to dilution of focus and potential hallucinations.</li>
</ul>



<p class=""></p>



<p class=""><strong>Therefore, RAG is not entirely obsolete.</strong> It still offers several advantages:</p>



<ul class="wp-block-list">
<li class=""><strong>Efficiency:</strong> RAG can be more efficient in retrieving and processing specific information.</li>



<li class=""><strong>Scalability:</strong> RAG can handle virtually unlimited amounts of data.</li>



<li class=""><strong>Focus:</strong> By providing the LLM with targeted information, RAG can improve accuracy and reduce hallucinations.</li>
</ul>



<p class=""></p>



<p class=""><strong>In conclusion, the relationship between long context LLMs and RAG is complex and evolving.</strong> The optimal approach often involves a hybrid strategy, combining the strengths of both technologies. The specific choice depends on the task, the available resources, and the desired level of performance.</p>
<p>The post <a href="https://vijay-gokarn.com/llms-large-language-context-vs-rag/">Long Context LLM&#8217;s vs RAG</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">168</post-id>	</item>
		<item>
		<title>AWS Sagemaker Jumpstart and AWS Bedrock Choosing the Right AI Tool for Your Needs</title>
		<link>https://vijay-gokarn.com/aws-sagemaker-jumpstart-and-aws-bedrock-choosing-the-right-ai-tool-for-your-needs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=aws-sagemaker-jumpstart-and-aws-bedrock-choosing-the-right-ai-tool-for-your-needs</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Thu, 01 Aug 2024 11:19:23 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=160</guid>

					<description><![CDATA[<p>AWS · Cloud AI · Service Comparison SageMaker JumpStart vs Amazon Bedrock — Choosing the Right AWS AI Tool ServicesSageMaker JumpStart · Amazon Bedrock FocusUse Cases · Architecture · Decision Guide StackAWS Cloud AI SageMaker JumpStart The Swiss Army Knife of Machine Learning vs Amazon Bedrock The Generative AI Powerhouse AWS offers two powerful tools [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/aws-sagemaker-jumpstart-and-aws-bedrock-choosing-the-right-ai-tool-for-your-needs/">AWS Sagemaker Jumpstart and AWS Bedrock Choosing the Right AI Tool for Your Needs</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg5 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  --aws-orange: #ff9900; --aws-blue: #232f3e;
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg5 *, .vg5 *::before, .vg5 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg5-hero { background: var(--aws-blue); padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg5-hero::before {
  content: 'AWS'; font-family: 'Cormorant Garamond', serif; font-size: 16rem;
  font-weight: 300; color: rgba(255,255,255,0.03); position: absolute;
  right: -1rem; bottom: -3rem; line-height: 1; pointer-events: none; letter-spacing: -0.05em;
}
.vg5-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg5-eyebrow {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--amber-light); font-weight: 500; margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.vg5-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--amber-light); }
.vg5-hero h1 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem);
  font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em;
  margin-bottom: 1.5rem; max-width: 26ch;
}
.vg5-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg5-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg5-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg5-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* VS BAND */
.vg5-vs-band {
  background: var(--aws-orange); display: grid; grid-template-columns: 1fr 60px 1fr;
  align-items: center;
}
.vg5-vs-left { padding: 1.5rem 2.5rem; background: rgba(0,0,0,0.1); }
.vg5-vs-right { padding: 1.5rem 2.5rem; background: rgba(0,0,0,0.2); }
.vg5-vs-mid { text-align: center; padding: 1.5rem 0; }
.vg5-vs-mid span { font-family: 'Cormorant Garamond', serif; font-size: 1.6rem; font-weight: 300; color: var(--aws-blue); }
.vg5-vs-name { font-size: 0.65rem; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(35,47,62,0.65); margin-bottom: 0.25rem; }
.vg5-vs-title { font-family: 'Cormorant Garamond', serif; font-size: 1.2rem; font-weight: 400; color: var(--aws-blue); line-height: 1.2; }

/* INTRO */
.vg5-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg5-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg5-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg5-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg5-section { margin-bottom: 3.5rem; }
.vg5-section-label {
  font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal); font-weight: 500; margin-bottom: 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.vg5-section-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg5-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.5rem, 3vw, 2.1rem); font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1.25rem; }
.vg5-section h2 em { font-style: italic; color: var(--teal); }
.vg5-section p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg5-section p strong { color: var(--ink); font-weight: 500; }
.vg5-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg5-callout { background: var(--paper-dark); border-left: 3px solid var(--amber); padding: 1.25rem 1.5rem; margin: 1.5rem 0; font-size: 0.87rem; line-height: 1.8; color: var(--charcoal); }
.vg5-callout strong { color: var(--amber); font-weight: 500; }
.vg5-callout.teal { border-color: var(--teal); }
.vg5-callout.teal strong { color: var(--teal); }

/* SERVICE DEEP DIVE CARDS */
.vg5-service-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin: 2rem 0; }
.vg5-service-card { border: 0.5px solid var(--border-strong); padding: 0; overflow: hidden; }
.vg5-service-header { padding: 1.5rem; }
.vg5-service-card.jumpstart .vg5-service-header { background: var(--aws-blue); }
.vg5-service-card.bedrock .vg5-service-header { background: var(--ink); }
.vg5-service-nickname { font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.4); margin-bottom: 0.3rem; }
.vg5-service-name { font-family: 'Cormorant Garamond', serif; font-size: 1.5rem; font-weight: 300; color: var(--paper); line-height: 1.2; margin-bottom: 0.75rem; }
.vg5-service-card.jumpstart .vg5-service-name em { color: var(--amber-light); font-style: italic; }
.vg5-service-card.bedrock .vg5-service-name em { color: var(--teal-light); font-style: italic; }
.vg5-service-tagline { font-size: 0.78rem; color: rgba(247,244,239,0.6); font-weight: 300; line-height: 1.5; }
.vg5-service-body { padding: 1.5rem; background: var(--paper); }
.vg5-attr-list { display: flex; flex-direction: column; gap: 0; }
.vg5-attr-item { padding: 0.85rem 0; border-bottom: 0.5px solid var(--border); display: grid; grid-template-columns: 90px 1fr; gap: 0.75rem; align-items: start; }
.vg5-attr-item:last-child { border-bottom: none; }
.vg5-attr-key { font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); font-weight: 400; padding-top: 0.1rem; }
.vg5-attr-val { font-size: 0.82rem; line-height: 1.65; color: var(--charcoal); font-weight: 300; }
.vg5-attr-val strong { color: var(--ink); font-weight: 500; }

/* TABLE */
.vg5-table-wrap { overflow-x: auto; margin: 1.5rem 0; }
.vg5-table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
.vg5-table th { background: var(--aws-blue); color: var(--paper); font-family: 'DM Sans', sans-serif; font-weight: 400; font-size: 0.65rem; letter-spacing: 0.14em; text-transform: uppercase; padding: 0.75rem 1rem; text-align: left; }
.vg5-table td { padding: 0.75rem 1rem; border-bottom: 0.5px solid var(--border); color: var(--charcoal); vertical-align: top; line-height: 1.55; }
.vg5-table tr:nth-child(even) td { background: var(--paper-dark); }
.vg5-table td strong { color: var(--ink); font-weight: 500; }
.vg5-chip { display: inline-block; font-size: 0.65rem; letter-spacing: 0.06em; padding: 0.2rem 0.55rem; font-weight: 400; }
.vg5-chip-green { background: var(--teal-muted); color: var(--teal); }
.vg5-chip-amber { background: var(--amber-muted); color: var(--amber); }
.vg5-chip-gray  { background: var(--paper-dark); color: var(--muted); border: 0.5px solid var(--border); }

/* USE CASES SECTION */
.vg5-usecases-section { background: var(--paper-dark); padding: 4rem; }
.vg5-usecases-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg5-usecases-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg5-usecases-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg5-usecases-section > h2 em { font-style: italic; color: var(--teal); }
.vg5-uc-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; }
.vg5-uc-col-header { font-size: 0.65rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; padding: 0.6rem 1rem; margin-bottom: 1rem; }
.vg5-uc-col-header.js { background: var(--aws-blue); color: var(--amber-light); }
.vg5-uc-col-header.br { background: var(--ink); color: var(--teal-light); }
.vg5-uc-list { display: flex; flex-direction: column; gap: 1rem; }
.vg5-uc-card { background: var(--paper); border: 0.5px solid var(--border); padding: 1.25rem 1.5rem; position: relative; }
.vg5-uc-card::before { content: ''; position: absolute; top: 0; left: 0; width: 3px; height: 100%; }
.vg5-uc-card.js::before { background: var(--amber); }
.vg5-uc-card.br::before { background: var(--teal); }
.vg5-uc-industry { font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.35rem; }
.vg5-uc-card h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.1rem; font-weight: 400; color: var(--ink); margin-bottom: 0.5rem; }
.vg5-uc-scenario { font-size: 0.78rem; line-height: 1.65; color: var(--muted); font-style: italic; margin-bottom: 0.6rem; font-weight: 300; }
.vg5-uc-solution { font-size: 0.82rem; line-height: 1.7; color: var(--charcoal); font-weight: 300; }
.vg5-uc-solution strong { color: var(--ink); font-weight: 500; }

/* INTERVIEW */
.vg5-interview-section { background: var(--ink); padding: 4rem; }
.vg5-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg5-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg5-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg5-interview-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg5-qa-list { display: flex; flex-direction: column; }
.vg5-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(247,244,239,0.1); align-items: start; }
.vg5-qa-item:last-child { border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg5-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--paper); line-height: 1.4; }
.vg5-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg5-qa-a { font-size: 0.83rem; line-height: 1.8; color: rgba(247,244,239,0.65); font-weight: 300; }
.vg5-qa-a strong { color: var(--amber-light); font-weight: 400; }
.vg5-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(247,244,239,0.08); padding: 0.1rem 0.35rem; color: var(--paper); }
.vg5-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg5-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); }
.vg5-pill.t { border-color: var(--teal-light); color: var(--teal-light); }
.vg5-pill.a { border-color: var(--amber-light); color: var(--amber-light); }

/* FOOTER */
.vg5-footer { background: var(--aws-blue); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; }
.vg5-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg5-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg5-back-btn { display: inline-block; padding: 0.65rem 1.75rem; background: var(--aws-orange); color: var(--aws-blue); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 500; }

/* REVEAL */
.vg5-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg5-reveal.vg5-vis { opacity: 1; transform: translateY(0); }
.vg5-d1 { transition-delay: 0.1s; } .vg5-d2 { transition-delay: 0.2s; } .vg5-d3 { transition-delay: 0.3s; }
</style>

<div class="vg5">

<!-- HERO -->
<div class="vg5-hero">
  <div class="vg5-hero-inner">
    <p class="vg5-eyebrow">AWS · Cloud AI · Service Comparison</p>
    <h1>SageMaker JumpStart vs Amazon Bedrock — <em>Choosing the Right AWS AI Tool</em></h1>
    <div class="vg5-meta-row">
      <p class="vg5-meta">Services<span>SageMaker JumpStart · Amazon Bedrock</span></p>
      <p class="vg5-meta">Focus<span>Use Cases · Architecture · Decision Guide</span></p>
      <p class="vg5-meta">Stack<span>AWS Cloud AI</span></p>
    </div>
  </div>
</div>

<!-- VS BAND -->
<div class="vg5-vs-band">
  <div class="vg5-vs-left">
    <p class="vg5-vs-name">SageMaker JumpStart</p>
    <p class="vg5-vs-title">The Swiss Army Knife of Machine Learning</p>
  </div>
  <div class="vg5-vs-mid"><span>vs</span></div>
  <div class="vg5-vs-right">
    <p class="vg5-vs-name">Amazon Bedrock</p>
    <p class="vg5-vs-title">The Generative AI Powerhouse</p>
  </div>
</div>

<!-- INTRO -->
<div class="vg5-intro">
  <p>AWS offers two powerful tools for businesses looking to leverage AI capabilities. While both services simplify AI adoption, they cater to fundamentally different needs. <strong>SageMaker JumpStart</strong> gives you control, customization, and the full ML lifecycle. <strong>Amazon Bedrock</strong> gives you immediate access to state-of-the-art foundation models with minimal setup. Knowing which to reach for is a core cloud AI skill.</p>
</div>

<!-- BODY -->
<div class="vg5-body">

  <!-- SERVICE CARDS -->
  <div class="vg5-section vg5-reveal">
    <p class="vg5-section-label">Service Deep Dive</p>
    <h2>What each service <em>actually does</em></h2>
    <div class="vg5-service-grid">

      <div class="vg5-service-card jumpstart vg5-reveal vg5-d1">
        <div class="vg5-service-header">
          <p class="vg5-service-nickname">Amazon SageMaker</p>
          <p class="vg5-service-name"><em>JumpStart</em></p>
          <p class="vg5-service-tagline">Pre-built ML solutions + full customization control within the SageMaker ecosystem</p>
        </div>
        <div class="vg5-service-body">
          <div class="vg5-attr-list">
            <div class="vg5-attr-item"><span class="vg5-attr-key">Scope</span><span class="vg5-attr-val">Part of the broader SageMaker ecosystem — notebooks, training, tuning, and deployment in one platform</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Models</span><span class="vg5-attr-val">Wide range of pre-built ML solutions: image classification, object detection, text analysis, and more</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Customization</span><span class="vg5-attr-val"><strong>Fine-tuning, transfer learning, and model retraining</strong> — you own the model weights</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Deployment</span><span class="vg5-attr-val">Seamless SageMaker integration; supports both batch and real-time inference endpoints</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">User Profile</span><span class="vg5-attr-val">Data scientists and ML engineers who want to customize models and build tailored solutions</span></div>
          </div>
        </div>
      </div>

      <div class="vg5-service-card bedrock vg5-reveal vg5-d2">
        <div class="vg5-service-header">
          <p class="vg5-service-nickname">Amazon</p>
          <p class="vg5-service-name"><em>Bedrock</em></p>
          <p class="vg5-service-tagline">Fully managed foundation model API — access top GenAI models without infrastructure</p>
        </div>
        <div class="vg5-service-body">
          <div class="vg5-attr-list">
            <div class="vg5-attr-item"><span class="vg5-attr-key">Scope</span><span class="vg5-attr-val">Standalone service dedicated to generative AI — no ML infrastructure to manage</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Models</span><span class="vg5-attr-val">Curated foundation models from Amazon, <strong>Anthropic (Claude)</strong>, AI21 Labs, Cohere, Meta, and Stability AI</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Customization</span><span class="vg5-attr-val">Fine-tuning available on select models; RAG via Knowledge Bases; no direct model weight access</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Deployment</span><span class="vg5-attr-val">API-first. Minimal setup to start generating text, images, or embeddings — serverless by default</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">User Profile</span><span class="vg5-attr-val">Developers and product teams integrating GenAI features fast — rapid prototyping and deployment</span></div>
          </div>
        </div>
      </div>

    </div>
  </div>

  <hr class="vg5-divider">

  <!-- COMPARISON TABLE -->
  <div class="vg5-section vg5-reveal">
    <p class="vg5-section-label">At a Glance</p>
    <h2>Side-by-side <em>quick reference</em></h2>
    <div class="vg5-table-wrap">
      <table class="vg5-table">
        <thead><tr><th>Factor</th><th>SageMaker JumpStart</th><th>Amazon Bedrock</th></tr></thead>
        <tbody>
          <tr>
            <td><strong>Primary Focus</strong></td>
            <td>Classical ML + customizable models</td>
            <td>Generative AI via foundation models</td>
          </tr>
          <tr>
            <td><strong>Setup Complexity</strong></td>
            <td><span class="vg5-chip vg5-chip-amber">Medium — SageMaker config needed</span></td>
            <td><span class="vg5-chip vg5-chip-green">Low — API call to start</span></td>
          </tr>
          <tr>
            <td><strong>Model Ownership</strong></td>
            <td><span class="vg5-chip vg5-chip-green">Full — fine-tune and own weights</span></td>
            <td><span class="vg5-chip vg5-chip-gray">No — managed by providers</span></td>
          </tr>
          <tr>
            <td><strong>Customization Depth</strong></td>
            <td><span class="vg5-chip vg5-chip-green">Deep — transfer learning, retraining</span></td>
            <td><span class="vg5-chip vg5-chip-amber">Limited — fine-tuning + RAG</span></td>
          </tr>
          <tr>
            <td><strong>Data Privacy</strong></td>
            <td><span class="vg5-chip vg5-chip-green">Full control in your VPC</span></td>
            <td><span class="vg5-chip vg5-chip-green">Data not used for model training</span></td>
          </tr>
          <tr>
            <td><strong>Inference Mode</strong></td>
            <td>Batch + real-time endpoints</td>
            <td>Serverless API (on-demand)</td>
          </tr>
          <tr>
            <td><strong>Model Variety</strong></td>
            <td>Vision, NLP, tabular, forecasting</td>
            <td>Text, image, embedding, multimodal</td>
          </tr>
          <tr>
            <td><strong>Best For</strong></td>
            <td>Tailored ML, regulated industries, data science teams</td>
            <td>Rapid GenAI features, chatbots, content generation</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div class="vg5-callout teal">
      <strong>Decision rule of thumb:</strong> If you&#8217;re asking &#8220;how do I add AI to my app fast?&#8221; — reach for Bedrock. If you&#8217;re asking &#8220;how do I build a custom model on my proprietary data?&#8221; — reach for SageMaker JumpStart.
    </div>
  </div>

</div><!-- /vg5-body -->

<!-- USE CASES -->
<div class="vg5-usecases-section">
  <p class="vg5-usecases-eyebrow">Real-World Examples</p>
  <h2>Use cases — <em>side by side</em></h2>
  <div class="vg5-uc-columns">

    <div>
      <p class="vg5-uc-col-header js">SageMaker JumpStart Examples</p>
      <div class="vg5-uc-list">
        <div class="vg5-uc-card js vg5-reveal">
          <p class="vg5-uc-industry">E-Commerce · Computer Vision</p>
          <h4>Product Image Classification</h4>
          <p class="vg5-uc-scenario">An e-commerce company needs to automatically categorize product images uploaded by sellers.</p>
          <p class="vg5-uc-solution">Deploy a <strong>pre-trained image classification model</strong> via JumpStart. Products are routed into categories — Electronics, Clothing, Home Appliances — with minimal setup. Model can be fine-tuned on proprietary category taxonomy.</p>
        </div>
        <div class="vg5-uc-card js vg5-reveal vg5-d1">
          <p class="vg5-uc-industry">Retail · NLP</p>
          <h4>Customer Sentiment Analysis</h4>
          <p class="vg5-uc-scenario">A company wants to analyze customer reviews at scale to understand satisfaction trends.</p>
          <p class="vg5-uc-solution">Deploy a <strong>pre-trained sentiment analysis model</strong> that classifies reviews as positive, negative, or neutral. Integrates into customer feedback pipelines — no model training required, fine-tuning available if needed.</p>
        </div>
        <div class="vg5-uc-card js vg5-reveal vg5-d2">
          <p class="vg5-uc-industry">Financial Services · Fraud Detection</p>
          <h4>Real-Time Transaction Fraud Detection</h4>
          <p class="vg5-uc-scenario">A financial institution needs to flag fraudulent transactions in real time.</p>
          <p class="vg5-uc-solution">Use a <strong>fraud detection solution template</strong> from JumpStart. Deploys a ready-to-use model that analyzes transaction patterns and flags suspicious activities for investigation — with a real-time inference endpoint.</p>
        </div>
      </div>
    </div>

    <div>
      <p class="vg5-uc-col-header br">Amazon Bedrock Examples</p>
      <div class="vg5-uc-list">
        <div class="vg5-uc-card br vg5-reveal">
          <p class="vg5-uc-industry">Healthcare · Predictive AI</p>
          <h4>Patient Readmission Prediction</h4>
          <p class="vg5-uc-scenario">A healthcare provider wants to predict patient readmissions based on historical patient data.</p>
          <p class="vg5-uc-solution">Use Bedrock to access a <strong>foundation model</strong>, fine-tune on proprietary patient records, and deploy a readmission prediction API. Bedrock&#8217;s managed infrastructure handles scale without the provider managing ML infrastructure.</p>
        </div>
        <div class="vg5-uc-card br vg5-reveal vg5-d1">
          <p class="vg5-uc-industry">Retail · Forecasting</p>
          <h4>Demand Forecasting Across Stores</h4>
          <p class="vg5-uc-scenario">A retail chain needs to forecast product demand across hundreds of locations.</p>
          <p class="vg5-uc-solution">Build a <strong>custom demand forecasting model</strong> via Bedrock, incorporating historical sales, seasonal trends, and promotions. Train, validate, and deploy at scale — Bedrock handles the infrastructure entirely.</p>
        </div>
        <div class="vg5-uc-card br vg5-reveal vg5-d2">
          <p class="vg5-uc-industry">Manufacturing · Computer Vision</p>
          <h4>Production Line Quality Control</h4>
          <p class="vg5-uc-scenario">A manufacturer wants to identify product defects using images from production lines in real time.</p>
          <p class="vg5-uc-solution">Develop a <strong>custom computer vision model</strong> in Bedrock trained on defective vs. non-defective product images. Deploy for real-time inspection — reducing defect rates without managing GPU infrastructure.</p>
        </div>
      </div>
    </div>

  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg5-interview-section">
  <p class="vg5-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg5-qa-list">

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Define</span><br>What is Amazon SageMaker JumpStart?</div>
      <div class="vg5-qa-a"><strong>A curated library of pre-built ML solutions and models</strong> within the SageMaker ecosystem. Lets you deploy, fine-tune, and retrain models for tasks like image classification, NLP, and fraud detection — with full control over the ML lifecycle.
        <div class="vg5-pills"><span class="vg5-pill t">Pre-built models</span><span class="vg5-pill t">Fine-tunable</span><span class="vg5-pill">SageMaker ecosystem</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal vg5-d1">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Define</span><br>What is Amazon Bedrock?</div>
      <div class="vg5-qa-a"><strong>A fully managed API service</strong> that provides access to foundation models from multiple providers (Anthropic, AI21 Labs, Cohere, Stability AI, Amazon). No ML infrastructure to manage — you call an API and get generative AI capabilities immediately.
        <div class="vg5-pills"><span class="vg5-pill t">Managed FM API</span><span class="vg5-pill t">Multi-provider</span><span class="vg5-pill a">Serverless</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Compare</span><br>JumpStart vs Bedrock — when do you pick each?</div>
      <div class="vg5-qa-a">Pick <strong>JumpStart</strong> when you need to customize a model on your own data, require full model weight ownership, or are building classical ML pipelines (vision, tabular, NLP). Pick <strong>Bedrock</strong> when you need GenAI features fast, want managed infrastructure, or are integrating LLMs into an application.
        <div class="vg5-pills"><span class="vg5-pill t">JumpStart = custom ML</span><span class="vg5-pill a">Bedrock = GenAI fast</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal vg5-d1">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Explain</span><br>What is a Foundation Model (FM)?</div>
      <div class="vg5-qa-a">A <strong>large model pre-trained on broad data</strong> that can be adapted for many downstream tasks. Foundation models (GPT-4, Claude, Llama) are trained once at massive scale and then fine-tuned or prompted for specific use cases. Bedrock provides access to these FMs as managed APIs.
        <div class="vg5-pills"><span class="vg5-pill t">Pre-trained at scale</span><span class="vg5-pill">Prompt or fine-tune</span><span class="vg5-pill a">Claude, Llama, Titan</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Gotcha</span><br>Can you use RAG with Bedrock? How?</div>
      <div class="vg5-qa-a">Yes — <strong>Bedrock Knowledge Bases</strong> lets you connect S3 data sources to an FM. Documents are chunked, embedded, and stored in a vector store (OpenSearch or Aurora). At inference, relevant chunks are retrieved and injected as context. This is Bedrock&#8217;s native managed RAG pipeline.
        <div class="vg5-pills"><span class="vg5-pill t">Bedrock Knowledge Bases</span><span class="vg5-pill t">S3 → Embed → Retrieve</span><span class="vg5-pill">Native RAG</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal vg5-d1">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Use Case</span><br>Which service suits a regulated industry (healthcare, finance)?</div>
      <div class="vg5-qa-a"><strong>SageMaker JumpStart</strong> for full data control inside your own VPC — no data leaves your environment. <strong>Bedrock</strong> is also enterprise-safe (data not used for model training, VPC endpoints available), but JumpStart gives deeper control for compliance-heavy workloads requiring model auditability.
        <div class="vg5-pills"><span class="vg5-pill t">JumpStart = full VPC control</span><span class="vg5-pill a">Bedrock = enterprise-safe API</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Name</span><br>Three Bedrock model providers and what they&#8217;re known for</div>
      <div class="vg5-qa-a"><strong>Anthropic (Claude)</strong> — safety-focused, long context, strong reasoning. <strong>AI21 Labs (Jurassic)</strong> — instruction-following, enterprise text generation. <strong>Stability AI</strong> — image generation (Stable Diffusion). Amazon&#8217;s own <strong>Titan</strong> models cover embeddings and text generation natively.
        <div class="vg5-pills"><span class="vg5-pill t">Anthropic = safety + reasoning</span><span class="vg5-pill t">Stability = images</span><span class="vg5-pill a">Titan = embeddings</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg5-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <a href="https://vijay-gokarn.com" class="vg5-back-btn">Back to Blog ↗</a>
</div>

</div><!-- /vg5 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg5-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg5-reveal').forEach(function(el){ obs.observe(el); });
})();
</script><link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg5 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  --aws-orange: #ff9900; --aws-blue: #232f3e;
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg5 *, .vg5 *::before, .vg5 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg5-hero { background: var(--aws-blue); padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg5-hero::before {
  content: 'AWS'; font-family: 'Cormorant Garamond', serif; font-size: 16rem;
  font-weight: 300; color: rgba(255,255,255,0.03); position: absolute;
  right: -1rem; bottom: -3rem; line-height: 1; pointer-events: none; letter-spacing: -0.05em;
}
.vg5-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg5-eyebrow {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--amber-light); font-weight: 500; margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.vg5-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--amber-light); }
.vg5-hero h1 {
  font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem);
  font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em;
  margin-bottom: 1.5rem; max-width: 26ch;
}
.vg5-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg5-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg5-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg5-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* VS BAND */
.vg5-vs-band {
  background: var(--aws-orange); display: grid; grid-template-columns: 1fr 60px 1fr;
  align-items: center;
}
.vg5-vs-left { padding: 1.5rem 2.5rem; background: rgba(0,0,0,0.1); }
.vg5-vs-right { padding: 1.5rem 2.5rem; background: rgba(0,0,0,0.2); }
.vg5-vs-mid { text-align: center; padding: 1.5rem 0; }
.vg5-vs-mid span { font-family: 'Cormorant Garamond', serif; font-size: 1.6rem; font-weight: 300; color: var(--aws-blue); }
.vg5-vs-name { font-size: 0.65rem; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(35,47,62,0.65); margin-bottom: 0.25rem; }
.vg5-vs-title { font-family: 'Cormorant Garamond', serif; font-size: 1.2rem; font-weight: 400; color: var(--aws-blue); line-height: 1.2; }

/* INTRO */
.vg5-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg5-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg5-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg5-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg5-section { margin-bottom: 3.5rem; }
.vg5-section-label {
  font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal); font-weight: 500; margin-bottom: 0.5rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.vg5-section-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg5-section h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.5rem, 3vw, 2.1rem); font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1.25rem; }
.vg5-section h2 em { font-style: italic; color: var(--teal); }
.vg5-section p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg5-section p strong { color: var(--ink); font-weight: 500; }
.vg5-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg5-callout { background: var(--paper-dark); border-left: 3px solid var(--amber); padding: 1.25rem 1.5rem; margin: 1.5rem 0; font-size: 0.87rem; line-height: 1.8; color: var(--charcoal); }
.vg5-callout strong { color: var(--amber); font-weight: 500; }
.vg5-callout.teal { border-color: var(--teal); }
.vg5-callout.teal strong { color: var(--teal); }

/* SERVICE DEEP DIVE CARDS */
.vg5-service-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin: 2rem 0; }
.vg5-service-card { border: 0.5px solid var(--border-strong); padding: 0; overflow: hidden; }
.vg5-service-header { padding: 1.5rem; }
.vg5-service-card.jumpstart .vg5-service-header { background: var(--aws-blue); }
.vg5-service-card.bedrock .vg5-service-header { background: var(--ink); }
.vg5-service-nickname { font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(247,244,239,0.4); margin-bottom: 0.3rem; }
.vg5-service-name { font-family: 'Cormorant Garamond', serif; font-size: 1.5rem; font-weight: 300; color: var(--paper); line-height: 1.2; margin-bottom: 0.75rem; }
.vg5-service-card.jumpstart .vg5-service-name em { color: var(--amber-light); font-style: italic; }
.vg5-service-card.bedrock .vg5-service-name em { color: var(--teal-light); font-style: italic; }
.vg5-service-tagline { font-size: 0.78rem; color: rgba(247,244,239,0.6); font-weight: 300; line-height: 1.5; }
.vg5-service-body { padding: 1.5rem; background: var(--paper); }
.vg5-attr-list { display: flex; flex-direction: column; gap: 0; }
.vg5-attr-item { padding: 0.85rem 0; border-bottom: 0.5px solid var(--border); display: grid; grid-template-columns: 90px 1fr; gap: 0.75rem; align-items: start; }
.vg5-attr-item:last-child { border-bottom: none; }
.vg5-attr-key { font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); font-weight: 400; padding-top: 0.1rem; }
.vg5-attr-val { font-size: 0.82rem; line-height: 1.65; color: var(--charcoal); font-weight: 300; }
.vg5-attr-val strong { color: var(--ink); font-weight: 500; }

/* TABLE */
.vg5-table-wrap { overflow-x: auto; margin: 1.5rem 0; }
.vg5-table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
.vg5-table th { background: var(--aws-blue); color: var(--paper); font-family: 'DM Sans', sans-serif; font-weight: 400; font-size: 0.65rem; letter-spacing: 0.14em; text-transform: uppercase; padding: 0.75rem 1rem; text-align: left; }
.vg5-table td { padding: 0.75rem 1rem; border-bottom: 0.5px solid var(--border); color: var(--charcoal); vertical-align: top; line-height: 1.55; }
.vg5-table tr:nth-child(even) td { background: var(--paper-dark); }
.vg5-table td strong { color: var(--ink); font-weight: 500; }
.vg5-chip { display: inline-block; font-size: 0.65rem; letter-spacing: 0.06em; padding: 0.2rem 0.55rem; font-weight: 400; }
.vg5-chip-green { background: var(--teal-muted); color: var(--teal); }
.vg5-chip-amber { background: var(--amber-muted); color: var(--amber); }
.vg5-chip-gray  { background: var(--paper-dark); color: var(--muted); border: 0.5px solid var(--border); }

/* USE CASES SECTION */
.vg5-usecases-section { background: var(--paper-dark); padding: 4rem; }
.vg5-usecases-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg5-usecases-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg5-usecases-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg5-usecases-section > h2 em { font-style: italic; color: var(--teal); }
.vg5-uc-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; }
.vg5-uc-col-header { font-size: 0.65rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; padding: 0.6rem 1rem; margin-bottom: 1rem; }
.vg5-uc-col-header.js { background: var(--aws-blue); color: var(--amber-light); }
.vg5-uc-col-header.br { background: var(--ink); color: var(--teal-light); }
.vg5-uc-list { display: flex; flex-direction: column; gap: 1rem; }
.vg5-uc-card { background: var(--paper); border: 0.5px solid var(--border); padding: 1.25rem 1.5rem; position: relative; }
.vg5-uc-card::before { content: ''; position: absolute; top: 0; left: 0; width: 3px; height: 100%; }
.vg5-uc-card.js::before { background: var(--amber); }
.vg5-uc-card.br::before { background: var(--teal); }
.vg5-uc-industry { font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.35rem; }
.vg5-uc-card h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.1rem; font-weight: 400; color: var(--ink); margin-bottom: 0.5rem; }
.vg5-uc-scenario { font-size: 0.78rem; line-height: 1.65; color: var(--muted); font-style: italic; margin-bottom: 0.6rem; font-weight: 300; }
.vg5-uc-solution { font-size: 0.82rem; line-height: 1.7; color: var(--charcoal); font-weight: 300; }
.vg5-uc-solution strong { color: var(--ink); font-weight: 500; }

/* INTERVIEW */
.vg5-interview-section { background: var(--ink); padding: 4rem; }
.vg5-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg5-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg5-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg5-interview-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg5-qa-list { display: flex; flex-direction: column; }
.vg5-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(247,244,239,0.1); align-items: start; }
.vg5-qa-item:last-child { border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg5-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--paper); line-height: 1.4; }
.vg5-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg5-qa-a { font-size: 0.83rem; line-height: 1.8; color: rgba(247,244,239,0.65); font-weight: 300; }
.vg5-qa-a strong { color: var(--amber-light); font-weight: 400; }
.vg5-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(247,244,239,0.08); padding: 0.1rem 0.35rem; color: var(--paper); }
.vg5-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg5-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); }
.vg5-pill.t { border-color: var(--teal-light); color: var(--teal-light); }
.vg5-pill.a { border-color: var(--amber-light); color: var(--amber-light); }

/* FOOTER */
.vg5-footer { background: var(--aws-blue); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; }
.vg5-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg5-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg5-back-btn { display: inline-block; padding: 0.65rem 1.75rem; background: var(--aws-orange); color: var(--aws-blue); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 500; }

/* REVEAL */
.vg5-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg5-reveal.vg5-vis { opacity: 1; transform: translateY(0); }
.vg5-d1 { transition-delay: 0.1s; } .vg5-d2 { transition-delay: 0.2s; } .vg5-d3 { transition-delay: 0.3s; }
</style>

<div class="vg5">

<!-- HERO -->
<div class="vg5-hero">
  <div class="vg5-hero-inner">
    <p class="vg5-eyebrow">AWS · Cloud AI · Service Comparison</p>
    <h1>SageMaker JumpStart vs Amazon Bedrock — <em>Choosing the Right AWS AI Tool</em></h1>
    <div class="vg5-meta-row">
      <p class="vg5-meta">Services<span>SageMaker JumpStart · Amazon Bedrock</span></p>
      <p class="vg5-meta">Focus<span>Use Cases · Architecture · Decision Guide</span></p>
      <p class="vg5-meta">Stack<span>AWS Cloud AI</span></p>
    </div>
  </div>
</div>

<!-- VS BAND -->
<div class="vg5-vs-band">
  <div class="vg5-vs-left">
    <p class="vg5-vs-name">SageMaker JumpStart</p>
    <p class="vg5-vs-title">The Swiss Army Knife of Machine Learning</p>
  </div>
  <div class="vg5-vs-mid"><span>vs</span></div>
  <div class="vg5-vs-right">
    <p class="vg5-vs-name">Amazon Bedrock</p>
    <p class="vg5-vs-title">The Generative AI Powerhouse</p>
  </div>
</div>

<!-- INTRO -->
<div class="vg5-intro">
  <p>AWS offers two powerful tools for businesses looking to leverage AI capabilities. While both services simplify AI adoption, they cater to fundamentally different needs. <strong>SageMaker JumpStart</strong> gives you control, customization, and the full ML lifecycle. <strong>Amazon Bedrock</strong> gives you immediate access to state-of-the-art foundation models with minimal setup. Knowing which to reach for is a core cloud AI skill.</p>
</div>

<!-- BODY -->
<div class="vg5-body">

  <!-- SERVICE CARDS -->
  <div class="vg5-section vg5-reveal">
    <p class="vg5-section-label">Service Deep Dive</p>
    <h2>What each service <em>actually does</em></h2>
    <div class="vg5-service-grid">

      <div class="vg5-service-card jumpstart vg5-reveal vg5-d1">
        <div class="vg5-service-header">
          <p class="vg5-service-nickname">Amazon SageMaker</p>
          <p class="vg5-service-name"><em>JumpStart</em></p>
          <p class="vg5-service-tagline">Pre-built ML solutions + full customization control within the SageMaker ecosystem</p>
        </div>
        <div class="vg5-service-body">
          <div class="vg5-attr-list">
            <div class="vg5-attr-item"><span class="vg5-attr-key">Scope</span><span class="vg5-attr-val">Part of the broader SageMaker ecosystem — notebooks, training, tuning, and deployment in one platform</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Models</span><span class="vg5-attr-val">Wide range of pre-built ML solutions: image classification, object detection, text analysis, and more</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Customization</span><span class="vg5-attr-val"><strong>Fine-tuning, transfer learning, and model retraining</strong> — you own the model weights</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Deployment</span><span class="vg5-attr-val">Seamless SageMaker integration; supports both batch and real-time inference endpoints</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">User Profile</span><span class="vg5-attr-val">Data scientists and ML engineers who want to customize models and build tailored solutions</span></div>
          </div>
        </div>
      </div>

      <div class="vg5-service-card bedrock vg5-reveal vg5-d2">
        <div class="vg5-service-header">
          <p class="vg5-service-nickname">Amazon</p>
          <p class="vg5-service-name"><em>Bedrock</em></p>
          <p class="vg5-service-tagline">Fully managed foundation model API — access top GenAI models without infrastructure</p>
        </div>
        <div class="vg5-service-body">
          <div class="vg5-attr-list">
            <div class="vg5-attr-item"><span class="vg5-attr-key">Scope</span><span class="vg5-attr-val">Standalone service dedicated to generative AI — no ML infrastructure to manage</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Models</span><span class="vg5-attr-val">Curated foundation models from Amazon, <strong>Anthropic (Claude)</strong>, AI21 Labs, Cohere, Meta, and Stability AI</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Customization</span><span class="vg5-attr-val">Fine-tuning available on select models; RAG via Knowledge Bases; no direct model weight access</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">Deployment</span><span class="vg5-attr-val">API-first. Minimal setup to start generating text, images, or embeddings — serverless by default</span></div>
            <div class="vg5-attr-item"><span class="vg5-attr-key">User Profile</span><span class="vg5-attr-val">Developers and product teams integrating GenAI features fast — rapid prototyping and deployment</span></div>
          </div>
        </div>
      </div>

    </div>
  </div>

  <hr class="vg5-divider">

  <!-- COMPARISON TABLE -->
  <div class="vg5-section vg5-reveal">
    <p class="vg5-section-label">At a Glance</p>
    <h2>Side-by-side <em>quick reference</em></h2>
    <div class="vg5-table-wrap">
      <table class="vg5-table">
        <thead><tr><th>Factor</th><th>SageMaker JumpStart</th><th>Amazon Bedrock</th></tr></thead>
        <tbody>
          <tr>
            <td><strong>Primary Focus</strong></td>
            <td>Classical ML + customizable models</td>
            <td>Generative AI via foundation models</td>
          </tr>
          <tr>
            <td><strong>Setup Complexity</strong></td>
            <td><span class="vg5-chip vg5-chip-amber">Medium — SageMaker config needed</span></td>
            <td><span class="vg5-chip vg5-chip-green">Low — API call to start</span></td>
          </tr>
          <tr>
            <td><strong>Model Ownership</strong></td>
            <td><span class="vg5-chip vg5-chip-green">Full — fine-tune and own weights</span></td>
            <td><span class="vg5-chip vg5-chip-gray">No — managed by providers</span></td>
          </tr>
          <tr>
            <td><strong>Customization Depth</strong></td>
            <td><span class="vg5-chip vg5-chip-green">Deep — transfer learning, retraining</span></td>
            <td><span class="vg5-chip vg5-chip-amber">Limited — fine-tuning + RAG</span></td>
          </tr>
          <tr>
            <td><strong>Data Privacy</strong></td>
            <td><span class="vg5-chip vg5-chip-green">Full control in your VPC</span></td>
            <td><span class="vg5-chip vg5-chip-green">Data not used for model training</span></td>
          </tr>
          <tr>
            <td><strong>Inference Mode</strong></td>
            <td>Batch + real-time endpoints</td>
            <td>Serverless API (on-demand)</td>
          </tr>
          <tr>
            <td><strong>Model Variety</strong></td>
            <td>Vision, NLP, tabular, forecasting</td>
            <td>Text, image, embedding, multimodal</td>
          </tr>
          <tr>
            <td><strong>Best For</strong></td>
            <td>Tailored ML, regulated industries, data science teams</td>
            <td>Rapid GenAI features, chatbots, content generation</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div class="vg5-callout teal">
      <strong>Decision rule of thumb:</strong> If you&#8217;re asking &#8220;how do I add AI to my app fast?&#8221; — reach for Bedrock. If you&#8217;re asking &#8220;how do I build a custom model on my proprietary data?&#8221; — reach for SageMaker JumpStart.
    </div>
  </div>

</div><!-- /vg5-body -->

<!-- USE CASES -->
<div class="vg5-usecases-section">
  <p class="vg5-usecases-eyebrow">Real-World Examples</p>
  <h2>Use cases — <em>side by side</em></h2>
  <div class="vg5-uc-columns">

    <div>
      <p class="vg5-uc-col-header js">SageMaker JumpStart Examples</p>
      <div class="vg5-uc-list">
        <div class="vg5-uc-card js vg5-reveal">
          <p class="vg5-uc-industry">E-Commerce · Computer Vision</p>
          <h4>Product Image Classification</h4>
          <p class="vg5-uc-scenario">An e-commerce company needs to automatically categorize product images uploaded by sellers.</p>
          <p class="vg5-uc-solution">Deploy a <strong>pre-trained image classification model</strong> via JumpStart. Products are routed into categories — Electronics, Clothing, Home Appliances — with minimal setup. Model can be fine-tuned on proprietary category taxonomy.</p>
        </div>
        <div class="vg5-uc-card js vg5-reveal vg5-d1">
          <p class="vg5-uc-industry">Retail · NLP</p>
          <h4>Customer Sentiment Analysis</h4>
          <p class="vg5-uc-scenario">A company wants to analyze customer reviews at scale to understand satisfaction trends.</p>
          <p class="vg5-uc-solution">Deploy a <strong>pre-trained sentiment analysis model</strong> that classifies reviews as positive, negative, or neutral. Integrates into customer feedback pipelines — no model training required, fine-tuning available if needed.</p>
        </div>
        <div class="vg5-uc-card js vg5-reveal vg5-d2">
          <p class="vg5-uc-industry">Financial Services · Fraud Detection</p>
          <h4>Real-Time Transaction Fraud Detection</h4>
          <p class="vg5-uc-scenario">A financial institution needs to flag fraudulent transactions in real time.</p>
          <p class="vg5-uc-solution">Use a <strong>fraud detection solution template</strong> from JumpStart. Deploys a ready-to-use model that analyzes transaction patterns and flags suspicious activities for investigation — with a real-time inference endpoint.</p>
        </div>
      </div>
    </div>

    <div>
      <p class="vg5-uc-col-header br">Amazon Bedrock Examples</p>
      <div class="vg5-uc-list">
        <div class="vg5-uc-card br vg5-reveal">
          <p class="vg5-uc-industry">Healthcare · Predictive AI</p>
          <h4>Patient Readmission Prediction</h4>
          <p class="vg5-uc-scenario">A healthcare provider wants to predict patient readmissions based on historical patient data.</p>
          <p class="vg5-uc-solution">Use Bedrock to access a <strong>foundation model</strong>, fine-tune on proprietary patient records, and deploy a readmission prediction API. Bedrock&#8217;s managed infrastructure handles scale without the provider managing ML infrastructure.</p>
        </div>
        <div class="vg5-uc-card br vg5-reveal vg5-d1">
          <p class="vg5-uc-industry">Retail · Forecasting</p>
          <h4>Demand Forecasting Across Stores</h4>
          <p class="vg5-uc-scenario">A retail chain needs to forecast product demand across hundreds of locations.</p>
          <p class="vg5-uc-solution">Build a <strong>custom demand forecasting model</strong> via Bedrock, incorporating historical sales, seasonal trends, and promotions. Train, validate, and deploy at scale — Bedrock handles the infrastructure entirely.</p>
        </div>
        <div class="vg5-uc-card br vg5-reveal vg5-d2">
          <p class="vg5-uc-industry">Manufacturing · Computer Vision</p>
          <h4>Production Line Quality Control</h4>
          <p class="vg5-uc-scenario">A manufacturer wants to identify product defects using images from production lines in real time.</p>
          <p class="vg5-uc-solution">Develop a <strong>custom computer vision model</strong> in Bedrock trained on defective vs. non-defective product images. Deploy for real-time inspection — reducing defect rates without managing GPU infrastructure.</p>
        </div>
      </div>
    </div>

  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg5-interview-section">
  <p class="vg5-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg5-qa-list">

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Define</span><br>What is Amazon SageMaker JumpStart?</div>
      <div class="vg5-qa-a"><strong>A curated library of pre-built ML solutions and models</strong> within the SageMaker ecosystem. Lets you deploy, fine-tune, and retrain models for tasks like image classification, NLP, and fraud detection — with full control over the ML lifecycle.
        <div class="vg5-pills"><span class="vg5-pill t">Pre-built models</span><span class="vg5-pill t">Fine-tunable</span><span class="vg5-pill">SageMaker ecosystem</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal vg5-d1">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Define</span><br>What is Amazon Bedrock?</div>
      <div class="vg5-qa-a"><strong>A fully managed API service</strong> that provides access to foundation models from multiple providers (Anthropic, AI21 Labs, Cohere, Stability AI, Amazon). No ML infrastructure to manage — you call an API and get generative AI capabilities immediately.
        <div class="vg5-pills"><span class="vg5-pill t">Managed FM API</span><span class="vg5-pill t">Multi-provider</span><span class="vg5-pill a">Serverless</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Compare</span><br>JumpStart vs Bedrock — when do you pick each?</div>
      <div class="vg5-qa-a">Pick <strong>JumpStart</strong> when you need to customize a model on your own data, require full model weight ownership, or are building classical ML pipelines (vision, tabular, NLP). Pick <strong>Bedrock</strong> when you need GenAI features fast, want managed infrastructure, or are integrating LLMs into an application.
        <div class="vg5-pills"><span class="vg5-pill t">JumpStart = custom ML</span><span class="vg5-pill a">Bedrock = GenAI fast</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal vg5-d1">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Explain</span><br>What is a Foundation Model (FM)?</div>
      <div class="vg5-qa-a">A <strong>large model pre-trained on broad data</strong> that can be adapted for many downstream tasks. Foundation models (GPT-4, Claude, Llama) are trained once at massive scale and then fine-tuned or prompted for specific use cases. Bedrock provides access to these FMs as managed APIs.
        <div class="vg5-pills"><span class="vg5-pill t">Pre-trained at scale</span><span class="vg5-pill">Prompt or fine-tune</span><span class="vg5-pill a">Claude, Llama, Titan</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Gotcha</span><br>Can you use RAG with Bedrock? How?</div>
      <div class="vg5-qa-a">Yes — <strong>Bedrock Knowledge Bases</strong> lets you connect S3 data sources to an FM. Documents are chunked, embedded, and stored in a vector store (OpenSearch or Aurora). At inference, relevant chunks are retrieved and injected as context. This is Bedrock&#8217;s native managed RAG pipeline.
        <div class="vg5-pills"><span class="vg5-pill t">Bedrock Knowledge Bases</span><span class="vg5-pill t">S3 → Embed → Retrieve</span><span class="vg5-pill">Native RAG</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal vg5-d1">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Use Case</span><br>Which service suits a regulated industry (healthcare, finance)?</div>
      <div class="vg5-qa-a"><strong>SageMaker JumpStart</strong> for full data control inside your own VPC — no data leaves your environment. <strong>Bedrock</strong> is also enterprise-safe (data not used for model training, VPC endpoints available), but JumpStart gives deeper control for compliance-heavy workloads requiring model auditability.
        <div class="vg5-pills"><span class="vg5-pill t">JumpStart = full VPC control</span><span class="vg5-pill a">Bedrock = enterprise-safe API</span></div>
      </div>
    </div>

    <div class="vg5-qa-item vg5-reveal">
      <div class="vg5-qa-q"><span class="vg5-q-badge">Name</span><br>Three Bedrock model providers and what they&#8217;re known for</div>
      <div class="vg5-qa-a"><strong>Anthropic (Claude)</strong> — safety-focused, long context, strong reasoning. <strong>AI21 Labs (Jurassic)</strong> — instruction-following, enterprise text generation. <strong>Stability AI</strong> — image generation (Stable Diffusion). Amazon&#8217;s own <strong>Titan</strong> models cover embeddings and text generation natively.
        <div class="vg5-pills"><span class="vg5-pill t">Anthropic = safety + reasoning</span><span class="vg5-pill t">Stability = images</span><span class="vg5-pill a">Titan = embeddings</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg5-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <a href="https://vijay-gokarn.com" class="vg5-back-btn">Back to Blog ↗</a>
</div>

</div><!-- /vg5 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg5-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg5-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>



<p class=""></p>
<p>The post <a href="https://vijay-gokarn.com/aws-sagemaker-jumpstart-and-aws-bedrock-choosing-the-right-ai-tool-for-your-needs/">AWS Sagemaker Jumpstart and AWS Bedrock Choosing the Right AI Tool for Your Needs</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">160</post-id>	</item>
		<item>
		<title>FAST API</title>
		<link>https://vijay-gokarn.com/fast-api/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fast-api</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Wed, 17 Jul 2024 08:47:26 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=143</guid>

					<description><![CDATA[<p>FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. Here are several reasons why FastAPI is an excellent choice for building APIs: 1. Speed FastAPI is one of the fastest web frameworks available, thanks to its use of Starlette for the web parts and [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/fast-api/">FAST API</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="">FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. Here are several reasons why FastAPI is an excellent choice for building APIs:</p>



<h3 class="wp-block-heading">1. <strong>Speed</strong></h3>



<p class="">FastAPI is one of the fastest web frameworks available, thanks to its use of Starlette for the web parts and Pydantic for the data parts. It&#8217;s designed to be as fast as possible, ensuring that your API has minimal latency and high throughput.</p>



<h3 class="wp-block-heading">2. <strong>Ease of Use</strong></h3>



<p class="">FastAPI leverages Python&#8217;s type hints, making the code easier to write and understand. It automatically generates interactive API documentation (using Swagger UI and ReDoc), which simplifies testing and understanding of the API endpoints.</p>



<h3 class="wp-block-heading">3. <strong>Data Validation</strong></h3>



<p class="">FastAPI uses Pydantic for data validation and parsing. This ensures that the data sent to the API is correctly formatted and validated before any further processing.</p>



<h3 class="wp-block-heading">4. <strong>Automatic Documentation</strong></h3>



<p class="">FastAPI generates interactive API documentation from your code using OpenAPI. This is extremely helpful for developers, as they can see and interact with the API directly from the browser.</p>



<h3 class="wp-block-heading">5. <strong>Asynchronous Support</strong></h3>



<p class="">FastAPI has first-class support for asynchronous programming, making it easy to write asynchronous endpoints that can handle large numbers of concurrent requests efficiently.</p>



<h3 class="wp-block-heading">6. <strong>Dependency Injection</strong></h3>



<p class="">FastAPI provides a powerful dependency injection system that makes it easy to manage and inject dependencies into your endpoints, which can simplify the design of your application and improve its testability.</p>



<h3 class="wp-block-heading">7. <strong>Security</strong></h3>



<p class="">FastAPI includes tools to handle security and authentication, like OAuth2 and JWT tokens, right out of the box.</p>



<h3 class="wp-block-heading">8. <strong>Community and Ecosystem</strong></h3>



<p class="">FastAPI has a growing community and a rich ecosystem of plugins and extensions. It integrates well with other popular Python libraries and tools, such as SQLAlchemy for ORM, Celery for background tasks, and others.</p>



<h3 class="wp-block-heading">Example: Building a tasklist FastAPI</h3>



<p class=""></p>



<h3 class="wp-block-heading">1. Imports</h3>



<pre class="wp-block-preformatted"><code>from fastapi import FastAPI, HTTPException<br>from pydantic import BaseModel<br>from typing import List, Optional<br>from uuid import UUID, uuid4<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>FastAPI</strong>: The web framework for building APIs.</li>



<li class=""><strong>HTTPException</strong>: Used to raise HTTP errors.</li>



<li class=""><strong>BaseModel</strong>: A base class from Pydantic for creating data models.</li>



<li class=""><strong>List, Optional</strong>: Type hints for better code readability and type checking.</li>



<li class=""><strong>UUID, uuid4</strong>: For generating unique identifiers for each task or blog post.</li>
</ul>



<h3 class="wp-block-heading">2. Initialize FastAPI</h3>



<pre class="wp-block-preformatted"><code>app = FastAPI()<br></code></pre>



<ul class="wp-block-list">
<li class="">Creates an instance of the FastAPI application.</li>
</ul>



<h3 class="wp-block-heading">3. Define the Task Model</h3>



<pre class="wp-block-preformatted"><code>class Task(BaseModel):<br>    id: Optional[UUID] = None<br>    title: str<br>    description: Optional[str] = None<br>    completed: bool = False<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>Task</strong>: This is a data model for tasks with optional <code>id</code>, <code>title</code>, optional <code>description</code>, and <code>completed</code> status.</li>
</ul>



<h3 class="wp-block-heading">4. In-Memory Storage</h3>



<pre class="wp-block-preformatted"><code>tasks = []<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>tasks</strong>: A list to store the tasks. In a real application, this would typically be a database.</li>
</ul>



<h3 class="wp-block-heading">5. Create Task Endpoint</h3>



<pre class="wp-block-preformatted"><code>@app.post("/tasks/", response_model=Task)<br>def create_task(task: Task):<br>    task.id = uuid4()<br>    tasks.append(task)<br>    return task<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>@app.post(&#8220;/tasks/&#8221;)</strong>: This is a POST endpoint to create a new task.</li>



<li class=""><strong>create_task</strong>: A function that accepts a <code>Task</code>, assigns it a unique <code>id</code>, and adds it to the <code>tasks</code> list.</li>
</ul>



<h3 class="wp-block-heading">6. Read All Tasks Endpoint</h3>



<pre class="wp-block-preformatted"><code>@app.get("/tasks/", response_model=List[Task])<br>def read_tasks():<br>    return tasks<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>@app.get(&#8220;/tasks/&#8221;)</strong>: This is a GET endpoint to read all tasks.</li>



<li class=""><strong>read_tasks</strong>: A function that returns the list of all tasks.</li>
</ul>



<h3 class="wp-block-heading">7. Read Task by ID Endpoint</h3>



<pre class="wp-block-preformatted"><code>@app.get("/tasks/{task_id}", response_model=Task)<br>def read_task(task_id: UUID):<br>    for task in tasks:<br>        if task.id == task_id:<br>            return task<br>        <br>    raise HTTPException(status_code=404, detail="Task not found")<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>@app.get(&#8220;/tasks/{task_id}&#8221;)</strong>: This is a GET endpoint to read a specific task by its ID.</li>



<li class=""><strong>read_task</strong>: A function that searches for a task by its ID. If found, it returns the task; otherwise, it raises a 404 error.</li>
</ul>



<h3 class="wp-block-heading">8. Update Task Endpoint</h3>



<pre class="wp-block-preformatted"><code>@app.put("/tasks/{task_id}", response_model=Task)<br>def update_task(task_id: UUID, task_update: Task):<br>    for idx, task in enumerate(tasks):<br>        if task.id == task_id:<br>            updated_task = task.copy(update=task_update.dict(exclude_unset=True))<br>            tasks[idx] = updated_task<br>            return updated_task<br>        <br>    raise HTTPException(status_code=404, detail="Task not found")<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>@app.put(&#8220;/tasks/{task_id}&#8221;)</strong>: This is a PUT endpoint to update an existing task.</li>



<li class=""><strong>update_task</strong>: A function that updates a task&#8217;s information by copying the updated fields and replacing the old task. If the task is not found, it raises a 404 error.</li>
</ul>



<h3 class="wp-block-heading">9. Delete Task Endpoint</h3>



<pre class="wp-block-preformatted"><code>@app.delete("/tasks/{task_id}", response_model=Task)<br>def delete_task(task_id: UUID):<br>    for idx, task in enumerate(tasks):<br>        if task.id == task_id:<br>            return tasks.pop(idx)<br>    <br>    raise HTTPException(status_code=404, detail="Task not found")<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>@app.delete(&#8220;/tasks/{task_id}&#8221;)</strong>: This is a DELETE endpoint to delete a task by its ID.</li>



<li class=""><strong>delete_task</strong>: A function that removes a task from the list if found; otherwise, it raises a 404 error.</li>
</ul>



<h3 class="wp-block-heading">10. Run the Application</h3>



<pre class="wp-block-preformatted"><code>if __name__ == "__main__":<br>    import uvicorn<br>    uvicorn.run(app, host="0.0.0.0", port=8000)<br></code></pre>



<ul class="wp-block-list">
<li class=""><strong>if name == &#8220;main&#8221;</strong>: This ensures that the app runs only if the script is executed directly.</li>



<li class=""><strong>uvicorn.run</strong>: Runs the FastAPI app using Uvicorn, a lightning-fast ASGI server.</li>
</ul>



<h3 class="wp-block-heading"><a href="https://github.com/vijaygokarn130/fast-api-example">Git</a></h3>
<p>The post <a href="https://vijay-gokarn.com/fast-api/">FAST API</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">143</post-id>	</item>
		<item>
		<title>Analyzing Wikipedia Articles with Langchain and OpenAI in Databricks</title>
		<link>https://vijay-gokarn.com/analyzing-wikipedia-articles-with-langchain-and-openai-in-databricks/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=analyzing-wikipedia-articles-with-langchain-and-openai-in-databricks</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Tue, 16 Jul 2024 10:59:28 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[pandas]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=140</guid>

					<description><![CDATA[<p>GenAI Mastery Series · NLP · Databricks · LangChain Categorizing Wikipedia at Scale with OpenAI, LangChain &#038; Databricks Datasetwikimedia/wikipedia · 10,000 articles ModelChatOpenAI (GPT-4) Output50-category JSON classifier Stack Databricks Notebook LangChain Core langchain_openai HuggingFace Datasets ChatPromptTemplate Batch Inference JSON Parsing A complete walkthrough of a large-scale text classification pipeline built inside a Databricks notebook — [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/analyzing-wikipedia-articles-with-langchain-and-openai-in-databricks/">Analyzing Wikipedia Articles with Langchain and OpenAI in Databricks</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg6 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  --db-red: #e8353a; --db-dark: #1b1f23;
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg6 *, .vg6 *::before, .vg6 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg6-hero { background: var(--db-dark); padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg6-hero::before {
  content: '{ }'; font-family: 'Cormorant Garamond', serif; font-size: 18rem;
  font-weight: 300; color: rgba(255,255,255,0.025); position: absolute;
  right: 0rem; bottom: -4rem; line-height: 1; pointer-events: none; letter-spacing: -0.05em;
}
.vg6-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg6-eyebrow { font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem; display: flex; align-items: center; gap: 0.75rem; }
.vg6-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg6-hero h1 { font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem); font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em; margin-bottom: 1.5rem; max-width: 28ch; }
.vg6-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg6-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg6-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg6-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* STACK BAND */
.vg6-stack-band { background: var(--db-red); padding: 1.1rem 4rem; display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
.vg6-stack-label { font-size: 0.63rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(255,255,255,0.6); font-weight: 400; margin-right: 0.4rem; }
.vg6-stack-pill { font-size: 0.7rem; letter-spacing: 0.05em; padding: 0.28rem 0.85rem; background: rgba(255,255,255,0.12); color: #fff; border: 0.5px solid rgba(255,255,255,0.2); }

/* INTRO */
.vg6-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg6-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg6-intro strong { color: var(--teal); font-weight: 500; }

/* PREREQS */
.vg6-prereqs { background: var(--paper-dark); padding: 2rem 4rem; display: flex; gap: 2rem; flex-wrap: wrap; align-items: center; border-bottom: 0.5px solid var(--border); }
.vg6-prereq-label { font-size: 0.63rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); font-weight: 500; flex-shrink: 0; }
.vg6-prereq-chips { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.vg6-prereq-chip { font-size: 0.72rem; padding: 0.3rem 0.9rem; border: 0.5px solid var(--border-strong); color: var(--charcoal); background: var(--paper); display: flex; align-items: center; gap: 0.4rem; }
.vg6-prereq-chip::before { content: '✓'; color: var(--teal); font-size: 0.65rem; font-weight: 600; }

/* BODY */
.vg6-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg6-step { margin-bottom: 3.5rem; }
.vg6-step-label { font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg6-step-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg6-step h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1rem; }
.vg6-step h2 em { font-style: italic; color: var(--teal); }
.vg6-step p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg6-step p strong { color: var(--ink); font-weight: 500; }
.vg6-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }

/* CALLOUT */
.vg6-callout { background: var(--paper-dark); border-left: 3px solid var(--amber); padding: 1.25rem 1.5rem; margin: 1.25rem 0; font-size: 0.87rem; line-height: 1.8; color: var(--charcoal); }
.vg6-callout strong { color: var(--amber); font-weight: 500; }
.vg6-callout.teal { border-color: var(--teal); }
.vg6-callout.teal strong { color: var(--teal); }

/* ── CODE BLOCKS ── */
.vg6-code-wrap { margin: 1.25rem 0; border: 0.5px solid rgba(255,255,255,0.06); overflow: hidden; }
.vg6-code-header { background: #2d333b; padding: 0.6rem 1.25rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 0.5px solid rgba(255,255,255,0.06); }
.vg6-code-filename { font-family: 'DM Mono', monospace; font-size: 0.68rem; color: rgba(247,244,239,0.45); letter-spacing: 0.04em; }
.vg6-code-lang { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--teal-light); font-weight: 500; }
.vg6-code-body { background: var(--db-dark); padding: 1.5rem; overflow-x: auto; }
.vg6-code-body pre { margin: 0; }
.vg6-code-body code { font-family: 'DM Mono', monospace; font-size: 0.82rem; line-height: 1.85; color: #e6edf3; white-space: pre; display: block; }

/* Syntax token colours */
.vg6-k  { color: #ff7b72; }   /* keyword: import, def, for, if */
.vg6-s  { color: #a5d6ff; }   /* string */
.vg6-c  { color: #8b949e; font-style: italic; } /* comment */
.vg6-f  { color: #d2a8ff; }   /* function / class call */
.vg6-n  { color: var(--amber-light); } /* number / constant */
.vg6-v  { color: #79c0ff; }   /* variable name */
.vg6-p  { color: #e6edf3; }   /* punctuation */
.vg6-m  { color: var(--teal-light); } /* magic / decorator */

/* ARCHITECTURE DIAGRAM */
.vg6-arch { display: flex; align-items: center; gap: 0; margin: 1.5rem 0; flex-wrap: wrap; }
.vg6-arch-box { background: var(--paper); border: 0.5px solid var(--border-strong); padding: 0.75rem 1.1rem; text-align: center; flex: 1; min-width: 100px; }
.vg6-arch-box .vg6-arch-icon { font-size: 1.25rem; margin-bottom: 0.25rem; }
.vg6-arch-box h5 { font-family: 'Cormorant Garamond', serif; font-size: 0.95rem; font-weight: 400; color: var(--ink); margin-bottom: 0.15rem; }
.vg6-arch-box p { font-size: 0.68rem; color: var(--muted); line-height: 1.4; font-weight: 300; }
.vg6-arch-box.highlight { background: var(--teal); border-color: var(--teal); }
.vg6-arch-box.highlight h5 { color: var(--paper); }
.vg6-arch-box.highlight p { color: rgba(247,244,239,0.6); }
.vg6-arch-arrow { font-size: 1rem; color: var(--muted); padding: 0 0.3rem; flex-shrink: 0; }

/* OUTPUT CARD */
.vg6-output-section { background: var(--db-dark); padding: 4rem; }
.vg6-output-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg6-output-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg6-output-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.2rem); font-weight: 300; color: var(--paper); margin-bottom: 2rem; }
.vg6-output-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg6-output-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: rgba(247,244,239,0.06); border: 0.5px solid rgba(247,244,239,0.06); margin-bottom: 2rem; }
.vg6-output-stat { background: var(--db-dark); padding: 1.5rem; }
.vg6-output-stat-n { font-family: 'Cormorant Garamond', serif; font-size: 2.2rem; font-weight: 300; color: var(--teal-light); line-height: 1; margin-bottom: 0.3rem; letter-spacing: -0.02em; }
.vg6-output-stat-l { font-size: 0.65rem; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg6-json-card { background: #161b22; border: 0.5px solid rgba(247,244,239,0.08); overflow: hidden; }
.vg6-json-header { background: #2d333b; padding: 0.55rem 1.25rem; display: flex; justify-content: space-between; }
.vg6-json-header span { font-family: 'DM Mono', monospace; font-size: 0.65rem; color: rgba(247,244,239,0.4); }
.vg6-json-header .vg6-json-tag { color: var(--teal-light); }
.vg6-json-body { padding: 1.5rem; font-family: 'DM Mono', monospace; font-size: 0.83rem; line-height: 1.9; color: #e6edf3; }
.vg6-json-key { color: var(--amber-light); }
.vg6-json-val-str { color: #a5d6ff; }
.vg6-json-val-num { color: #79c0ff; }
.vg6-json-punct { color: rgba(247,244,239,0.4); }

/* CATEGORIES CLOUD */
.vg6-categories { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.5rem 0; }
.vg6-cat-pill { font-size: 0.7rem; letter-spacing: 0.05em; padding: 0.3rem 0.85rem; border: 0.5px solid rgba(247,244,239,0.12); color: rgba(247,244,239,0.55); }
.vg6-cat-pill.active { border-color: var(--teal-light); color: var(--teal-light); background: rgba(29,158,117,0.1); }

/* INTERVIEW */
.vg6-interview-section { background: var(--teal-muted); padding: 4rem; }
.vg6-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg6-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg6-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 2.5rem; }
.vg6-interview-section > h2 em { font-style: italic; color: var(--teal); }
.vg6-qa-list { display: flex; flex-direction: column; }
.vg6-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(14,14,14,0.1); align-items: start; }
.vg6-qa-item:last-child { border-bottom: 0.5px solid rgba(14,14,14,0.1); }
.vg6-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--ink); line-height: 1.4; }
.vg6-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg6-qa-a { font-size: 0.83rem; line-height: 1.8; color: var(--charcoal); font-weight: 300; }
.vg6-qa-a strong { color: var(--teal); font-weight: 500; }
.vg6-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.35rem; color: var(--ink); }
.vg6-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg6-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid var(--border-strong); color: var(--charcoal); }
.vg6-pill.t { border-color: var(--teal); color: var(--teal); background: var(--teal-muted); }
.vg6-pill.a { border-color: var(--amber); color: var(--amber); background: var(--amber-muted); }

/* FOOTER */
.vg6-footer { background: var(--db-dark); padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; border-top: 0.5px solid rgba(247,244,239,0.06); }
.vg6-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg6-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg6-footer-links { display: flex; gap: 1rem; }
.vg6-footer-btn { display: inline-block; padding: 0.65rem 1.75rem; font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }
.vg6-footer-btn.primary { background: var(--teal); color: var(--paper); }
.vg6-footer-btn.ghost { background: transparent; color: rgba(247,244,239,0.55); border: 0.5px solid rgba(247,244,239,0.2); }

/* REVEAL */
.vg6-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg6-reveal.vg6-vis { opacity: 1; transform: translateY(0); }
.vg6-d1 { transition-delay: 0.1s; } .vg6-d2 { transition-delay: 0.2s; }
</style>

<div class="vg6">

<!-- HERO -->
<div class="vg6-hero">
  <div class="vg6-hero-inner">
    <p class="vg6-eyebrow">GenAI Mastery Series · NLP · Databricks · LangChain</p>
    <h1>Categorizing Wikipedia at Scale with <em>OpenAI, LangChain &#038; Databricks</em></h1>
    <div class="vg6-meta-row">
      <p class="vg6-meta">Dataset<span>wikimedia/wikipedia · 10,000 articles</span></p>
      <p class="vg6-meta">Model<span>ChatOpenAI (GPT-4)</span></p>
      <p class="vg6-meta">Output<span>50-category JSON classifier</span></p>
    </div>
  </div>
</div>

<!-- STACK BAND -->
<div class="vg6-stack-band">
  <span class="vg6-stack-label">Stack</span>
  <span class="vg6-stack-pill">Databricks Notebook</span>
  <span class="vg6-stack-pill">LangChain Core</span>
  <span class="vg6-stack-pill">langchain_openai</span>
  <span class="vg6-stack-pill">HuggingFace Datasets</span>
  <span class="vg6-stack-pill">ChatPromptTemplate</span>
  <span class="vg6-stack-pill">Batch Inference</span>
  <span class="vg6-stack-pill">JSON Parsing</span>
</div>

<!-- INTRO -->
<div class="vg6-intro">
  <p>A complete walkthrough of a <strong>large-scale text classification pipeline</strong> built inside a Databricks notebook — from loading 10,000 Wikipedia articles to batch-classifying them into 50 categories using OpenAI&#8217;s language model via LangChain. Every step includes the real working code.</p>
</div>

<!-- PREREQS -->
<div class="vg6-prereqs">
  <span class="vg6-prereq-label">Prerequisites</span>
  <div class="vg6-prereq-chips">
    <span class="vg6-prereq-chip">Databricks Account</span>
    <span class="vg6-prereq-chip">Python (basic)</span>
    <span class="vg6-prereq-chip">OpenAI API Key</span>
    <span class="vg6-prereq-chip">HuggingFace Access</span>
  </div>
</div>

<!-- BODY -->
<div class="vg6-body">

  <!-- ARCHITECTURE -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Overview</p>
    <h2>Pipeline <em>architecture</em></h2>
    <p>The full pipeline runs end-to-end inside a single Databricks notebook. Wikipedia articles are loaded from HuggingFace, cleaned to first-line summaries, batched, and sent to GPT-4 via LangChain&#8217;s chain interface. Responses are parsed from JSON into a DataFrame.</p>
    <div class="vg6-arch">
      <div class="vg6-arch-box"><div class="vg6-arch-icon">📦</div><h5>HuggingFace</h5><p>wikimedia/wikipedia dataset</p></div>
      <div class="vg6-arch-arrow">→</div>
      <div class="vg6-arch-box"><div class="vg6-arch-icon">✂️</div><h5>Clean</h5><p>First-line extraction</p></div>
      <div class="vg6-arch-arrow">→</div>
      <div class="vg6-arch-box highlight"><div class="vg6-arch-icon" style="color:var(--paper)">⛓</div><h5>LangChain</h5><p>Prompt + ChatOpenAI</p></div>
      <div class="vg6-arch-arrow">→</div>
      <div class="vg6-arch-box"><div class="vg6-arch-icon">🔄</div><h5>Batch (8)</h5><p>Rate-limit safe</p></div>
      <div class="vg6-arch-arrow">→</div>
      <div class="vg6-arch-box"><div class="vg6-arch-icon">📊</div><h5>DataFrame</h5><p>id + category</p></div>
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 1 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 1</p>
    <h2>Install <em>required packages</em></h2>
    <p>In a Databricks notebook, use <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">%pip</code> magic commands to install packages into the cluster. The <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">%restart_python</code> command refreshes the interpreter to pick up the new packages without restarting the whole cluster.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 1</span><span class="vg6-code-lang">Python / Magic</span></div>
      <div class="vg6-code-body"><code><span class="vg6-m">%pip install</span> langchain_openai
<span class="vg6-m">%pip install</span> <span class="vg6-v">--upgrade</span> langchain_core langchain_openai

<span class="vg6-m">%restart_python</span></code></div>
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 2 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 2</p>
    <h2>Import <em>libraries</em></h2>
    <p>Standard Python utilities (<code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">json</code>, <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">time</code>, <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">os</code>) combined with <strong>LangChain</strong> for the LLM interface, <strong>HuggingFace Datasets</strong> for Wikipedia data loading, and <strong>tqdm</strong> for progress visibility during batch processing.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 2</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code><span class="vg6-k">import</span> json
<span class="vg6-k">import</span> time
<span class="vg6-k">import</span> os
<span class="vg6-k">import</span> getpass
<span class="vg6-k">import</span> pandas <span class="vg6-k">as</span> pd

<span class="vg6-k">from</span> datasets <span class="vg6-k">import</span> Dataset, load_dataset
<span class="vg6-k">from</span> tqdm <span class="vg6-k">import</span> tqdm
<span class="vg6-k">from</span> langchain_core.prompts <span class="vg6-k">import</span> ChatPromptTemplate
<span class="vg6-k">from</span> langchain_openai <span class="vg6-k">import</span> ChatOpenAI</code></div>
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 3 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 3</p>
    <h2>Load &#038; clean <em>the dataset</em></h2>
    <p>The HuggingFace <strong>wikimedia/wikipedia</strong> dataset is massive — we take a 10,000 article slice from the English November 2023 snapshot. The cleaning step extracts only the first line of each article (the summary sentence), which is sufficient for category classification and drastically reduces token usage.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 3</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code><span class="vg6-c"># Load the Wikipedia English dataset (Nov 2023 snapshot)</span>
dataset = <span class="vg6-f">load_dataset</span>(<span class="vg6-s">"wikimedia/wikipedia"</span>, <span class="vg6-s">"20231101.en"</span>)

<span class="vg6-c"># Take a 10k article sample</span>
<span class="vg6-v">NUM_SAMPLES</span> = <span class="vg6-n">10000</span>
articles = dataset[<span class="vg6-s">"train"</span>][:<span class="vg6-v">NUM_SAMPLES</span>][<span class="vg6-s">"text"</span>]
ids      = dataset[<span class="vg6-s">"train"</span>][:<span class="vg6-v">NUM_SAMPLES</span>][<span class="vg6-s">"id"</span>]

<span class="vg6-c"># Clean: keep only the first line (article summary) to reduce tokens</span>
articles = [x.<span class="vg6-f">split</span>(<span class="vg6-s">"\n"</span>)[<span class="vg6-n">0</span>] <span class="vg6-k">for</span> x <span class="vg6-k">in</span> articles]

<span class="vg6-c"># Sanity check</span>
<span class="vg6-f">print</span>(<span class="vg6-f">len</span>(articles))   <span class="vg6-c"># → 10000</span>
<span class="vg6-f">print</span>(articles[<span class="vg6-n">99</span>])    <span class="vg6-c"># inspect a sample article</span></code></div>
    </div>
    <div class="vg6-callout teal">
      <strong>Why first line only?</strong> Wikipedia article summaries are dense and self-contained. Using the full article would cost ~10–50x more tokens per classification with minimal accuracy gain. At 10k articles × avg 150 tokens = ~1.5M input tokens — already significant. First-line only brings that to ~200k tokens.
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 4 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 4</p>
    <h2>Configure <em>OpenAI + LangChain</em></h2>
    <p>Use <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">getpass</code> to securely prompt for the API key without echoing it to the notebook output. Then initialize <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">ChatOpenAI</code> — LangChain&#8217;s wrapper around the OpenAI Chat Completions API.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 4 &#038; 5</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code><span class="vg6-c"># Securely enter API key (won't echo to notebook output)</span>
os.environ[<span class="vg6-s">"OPENAI_API_KEY"</span>] = getpass.<span class="vg6-f">getpass</span>(<span class="vg6-s">"Enter your OpenAI API key: "</span>)

<span class="vg6-c"># Initialize the LangChain ChatOpenAI wrapper</span>
llm = <span class="vg6-f">ChatOpenAI</span>()
<span class="vg6-f">print</span>(llm.model_name)  <span class="vg6-c"># → "gpt-3.5-turbo" (default) or your configured model</span></code></div>
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 5 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 5 — Core Logic</p>
    <h2>Define the <em>prompt template</em></h2>
    <p>The <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">ChatPromptTemplate</code> structures the conversation: a system message sets the classification task with all 50 categories, and the human message carries the article payload. The <strong>double curly braces</strong> <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">&#123;&#123; &#125;&#125;</code> in the JSON schema escape the literal braces so LangChain doesn&#8217;t treat them as template variables.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 6</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code>prompt = ChatPromptTemplate.<span class="vg6-f">from_messages</span>([
    (<span class="vg6-s">"system"</span>, <span class="vg6-s">"""Your task is to assess the article and categorize it
into one of the following predefined categories:

'History', 'Geography', 'Science', 'Technology', 'Mathematics',
'Literature', 'Art', 'Music', 'Film', 'Television', 'Sports',
'Politics', 'Philosophy', 'Religion', 'Sociology', 'Psychology',
'Economics', 'Business', 'Medicine', 'Biology', 'Chemistry',
'Physics', 'Astronomy', 'Environmental Science', 'Engineering',
'Computer Science', 'Linguistics', 'Anthropology', 'Archaeology',
'Education', 'Law', 'Military', 'Architecture', 'Fashion',
'Cuisine', 'Travel', 'Mythology', 'Folklore', 'Biography',
'Social Issues', 'Human Rights', 'Technology Ethics',
'Climate Change', 'Conservation', 'Urban Studies', 'Demographics',
'Journalism', 'Cryptocurrency', 'Artificial Intelligence'

Output ONLY a JSON object — no extra text:
{{
    "id": string,
    "category": string
}}"""</span>),
    (<span class="vg6-s">"human"</span>, <span class="vg6-s">"{input}"</span>)
])</code></div>
    </div>
    <div class="vg6-callout">
      <strong>Prompt engineering note:</strong> Listing all valid categories explicitly in the system prompt constrains the model to valid outputs — reducing hallucinated or free-form category names. The strict JSON output instruction combined with downstream <code>json.loads()</code> parsing creates a simple but robust structured output pipeline.
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 6 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 6</p>
    <h2>Build the chain &#038; <em>test it</em></h2>
    <p>LangChain&#8217;s pipe operator <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">|</code> composes the prompt template and the LLM into a reusable chain. One call to <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">.invoke()</code> with a single article validates the whole setup before committing to batch processing.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 7</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code><span class="vg6-c"># Compose prompt → llm into a reusable chain</span>
chain = prompt | llm

<span class="vg6-c"># Test with article[0] before running the full batch</span>
content  = json.<span class="vg6-f">dumps</span>({<span class="vg6-s">"id"</span>: ids[<span class="vg6-n">0</span>], <span class="vg6-s">"article"</span>: articles[<span class="vg6-n">0</span>]})
response = chain.<span class="vg6-f">invoke</span>(content)
<span class="vg6-f">print</span>(response.content)
<span class="vg6-c"># → {"id": "1", "category": "History"}</span></code></div>
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 7 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 7 — Core Loop</p>
    <h2>Batch processing <em>with rate-limit handling</em></h2>
    <p>Processing 1,000 articles one-by-one would quickly hit OpenAI&#8217;s requests-per-minute limit. The solution: accumulate inputs into batches of 8 and call <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">.batch()</code> with a <strong>1.5-second sleep</strong> between each batch. <code style="font-family:'DM Mono',monospace;font-size:0.82rem;background:rgba(14,14,14,0.07);padding:0.1rem 0.35rem">tqdm</code> wraps the loop to give live progress in the notebook.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 8</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code>results    = []
<span class="vg6-v">BATCH_SIZE</span> = <span class="vg6-n">8</span>
inputs     = []

<span class="vg6-k">for</span> index, article <span class="vg6-k">in</span> <span class="vg6-f">tqdm</span>(<span class="vg6-f">enumerate</span>(articles[:<span class="vg6-n">1000</span>])):

    inputs.<span class="vg6-f">append</span>(
        json.<span class="vg6-f">dumps</span>({<span class="vg6-s">"id"</span>: ids[index], <span class="vg6-s">"article"</span>: articles[index]})
    )

    <span class="vg6-k">if</span> <span class="vg6-f">len</span>(inputs) == <span class="vg6-v">BATCH_SIZE</span>:
        time.<span class="vg6-f">sleep</span>(<span class="vg6-n">1.5</span>)            <span class="vg6-c"># respect rate limits</span>
        response = chain.<span class="vg6-f">batch</span>(inputs)
        results += response
        inputs   = []               <span class="vg6-c"># reset buffer</span>

<span class="vg6-c"># Flush any remaining articles in the last partial batch</span>
<span class="vg6-k">if</span> inputs:
    response = chain.<span class="vg6-f">batch</span>(inputs)
    results += response</code></div>
    </div>
    <div class="vg6-callout">
      <strong>Rate limit strategy:</strong> Batch size 8 + 1.5s sleep = ~5 batches/sec = ~40 requests/sec. For the free OpenAI tier (3 RPM), reduce batch size to 1 and increase sleep to 20s. For production use, implement exponential backoff with <code>tenacity</code>.
    </div>
  </div>

  <hr class="vg6-divider">

  <!-- STEP 8 -->
  <div class="vg6-step vg6-reveal">
    <p class="vg6-step-label">Step 8</p>
    <h2>Parse results into <em>a DataFrame</em></h2>
    <p>Not every LLM response will be valid JSON — network hiccups, model refusals, and malformed outputs all happen at scale. The pattern below separates successful parses from failures so you can inspect and retry the failures without losing the successful results.</p>
    <div class="vg6-code-wrap">
      <div class="vg6-code-header"><span class="vg6-code-filename">Databricks Notebook — Cell 9</span><span class="vg6-code-lang">Python</span></div>
      <div class="vg6-code-body"><code>success = []
failure = []

<span class="vg6-k">for</span> output <span class="vg6-k">in</span> results:
    content = output.content
    <span class="vg6-k">try</span>:
        content = json.<span class="vg6-f">loads</span>(content)
        success.<span class="vg6-f">append</span>(content)
    <span class="vg6-k">except</span> ValueError <span class="vg6-k">as</span> e:
        failure.<span class="vg6-f">append</span>(content)  <span class="vg6-c"># keep for retry / inspection</span>

<span class="vg6-f">print</span>(<span class="vg6-f">f</span><span class="vg6-s">"Success: {len(success)} | Failure: {len(failure)}"</span>)

<span class="vg6-c"># Convert to DataFrame for analysis / export</span>
df = pd.<span class="vg6-f">DataFrame</span>(success)
df.<span class="vg6-f">head</span>(<span class="vg6-n">10</span>)</code></div>
    </div>
  </div>

</div><!-- /vg6-body -->

<!-- OUTPUT SECTION -->
<div class="vg6-output-section">
  <p class="vg6-output-eyebrow">Sample Output</p>
  <h2>What the <em>pipeline produces</em></h2>
  <div class="vg6-output-grid vg6-reveal">
    <div class="vg6-output-stat"><div class="vg6-output-stat-n">10k</div><div class="vg6-output-stat-l">Articles Loaded</div></div>
    <div class="vg6-output-stat"><div class="vg6-output-stat-n">1k</div><div class="vg6-output-stat-l">Articles Classified</div></div>
    <div class="vg6-output-stat"><div class="vg6-output-stat-n">50</div><div class="vg6-output-stat-l">Categories</div></div>
    <div class="vg6-output-stat"><div class="vg6-output-stat-n">8</div><div class="vg6-output-stat-l">Batch Size</div></div>
  </div>
  <div class="vg6-json-card vg6-reveal vg6-d1">
    <div class="vg6-json-header">
      <span>LLM Response — Single Article</span>
      <span class="vg6-json-tag">JSON output</span>
    </div>
    <div class="vg6-json-body">
<span class="vg6-json-punct">[</span>
  <span class="vg6-json-punct">{</span>
    <span class="vg6-json-key">&#8220;id&#8221;</span><span class="vg6-json-punct">:</span> <span class="vg6-json-val-str">&#8220;1&#8221;</span><span class="vg6-json-punct">,</span>
    <span class="vg6-json-key">&#8220;category&#8221;</span><span class="vg6-json-punct">:</span> <span class="vg6-json-val-str">&#8220;History&#8221;</span>
  <span class="vg6-json-punct">},</span>
  <span class="vg6-json-punct">{</span>
    <span class="vg6-json-key">&#8220;id&#8221;</span><span class="vg6-json-punct">:</span> <span class="vg6-json-val-str">&#8220;4&#8221;</span><span class="vg6-json-punct">,</span>
    <span class="vg6-json-key">&#8220;category&#8221;</span><span class="vg6-json-punct">:</span> <span class="vg6-json-val-str">&#8220;Computer Science&#8221;</span>
  <span class="vg6-json-punct">},</span>
  <span class="vg6-json-punct">{</span>
    <span class="vg6-json-key">&#8220;id&#8221;</span><span class="vg6-json-punct">:</span> <span class="vg6-json-val-str">&#8220;7&#8221;</span><span class="vg6-json-punct">,</span>
    <span class="vg6-json-key">&#8220;category&#8221;</span><span class="vg6-json-punct">:</span> <span class="vg6-json-val-str">&#8220;Biology&#8221;</span>
  <span class="vg6-json-punct">}</span>
<span class="vg6-json-punct">]</span>
    </div>
  </div>
  <p style="font-size:0.82rem;color:rgba(247,244,239,0.45);margin-top:1.5rem;font-weight:300;">All 50 available classification categories:</p>
  <div class="vg6-categories vg6-reveal vg6-d2">
    <span class="vg6-cat-pill active">History</span><span class="vg6-cat-pill">Geography</span><span class="vg6-cat-pill active">Science</span><span class="vg6-cat-pill">Technology</span><span class="vg6-cat-pill">Mathematics</span><span class="vg6-cat-pill">Literature</span><span class="vg6-cat-pill">Art</span><span class="vg6-cat-pill">Music</span><span class="vg6-cat-pill">Film</span><span class="vg6-cat-pill">Television</span><span class="vg6-cat-pill">Sports</span><span class="vg6-cat-pill active">Politics</span><span class="vg6-cat-pill">Philosophy</span><span class="vg6-cat-pill">Religion</span><span class="vg6-cat-pill">Sociology</span><span class="vg6-cat-pill">Psychology</span><span class="vg6-cat-pill">Economics</span><span class="vg6-cat-pill">Business</span><span class="vg6-cat-pill">Medicine</span><span class="vg6-cat-pill active">Biology</span><span class="vg6-cat-pill">Chemistry</span><span class="vg6-cat-pill">Physics</span><span class="vg6-cat-pill">Astronomy</span><span class="vg6-cat-pill">Environmental Science</span><span class="vg6-cat-pill">Engineering</span><span class="vg6-cat-pill active">Computer Science</span><span class="vg6-cat-pill">Linguistics</span><span class="vg6-cat-pill">Anthropology</span><span class="vg6-cat-pill">Archaeology</span><span class="vg6-cat-pill">Education</span><span class="vg6-cat-pill">Law</span><span class="vg6-cat-pill">Military</span><span class="vg6-cat-pill">Architecture</span><span class="vg6-cat-pill">Fashion</span><span class="vg6-cat-pill">Cuisine</span><span class="vg6-cat-pill">Travel</span><span class="vg6-cat-pill">Mythology</span><span class="vg6-cat-pill">Folklore</span><span class="vg6-cat-pill">Biography</span><span class="vg6-cat-pill">Social Issues</span><span class="vg6-cat-pill">Human Rights</span><span class="vg6-cat-pill active">Artificial Intelligence</span><span class="vg6-cat-pill">Cryptocurrency</span><span class="vg6-cat-pill">Climate Change</span><span class="vg6-cat-pill">Conservation</span><span class="vg6-cat-pill">Urban Studies</span><span class="vg6-cat-pill">Journalism</span><span class="vg6-cat-pill">Technology Ethics</span><span class="vg6-cat-pill">Demographics</span>
  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg6-interview-section">
  <p class="vg6-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg6-qa-list">

    <div class="vg6-qa-item vg6-reveal">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Define</span><br>What is LangChain and what problem does it solve?</div>
      <div class="vg6-qa-a"><strong>A framework for composing LLM-powered applications</strong> from modular building blocks — prompts, models, chains, memory, tools, and agents. It solves the orchestration problem: how do you connect a prompt template to an LLM, parse the output, and chain multiple steps together cleanly?
        <div class="vg6-pills"><span class="vg6-pill t">Prompt + LLM + Output</span><span class="vg6-pill t">Composable chains</span><span class="vg6-pill">Pipe operator |</span></div>
      </div>
    </div>

    <div class="vg6-qa-item vg6-reveal vg6-d1">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Explain</span><br>What is a ChatPromptTemplate?</div>
      <div class="vg6-qa-a">A <strong>reusable message template</strong> that structures the conversation for a chat model. Defines the system role (task instructions) and the human turn (variable input). The <code>{input}</code> placeholder gets filled at runtime. Separating instructions from data is a core prompt engineering best practice.
        <div class="vg6-pills"><span class="vg6-pill t">System = instructions</span><span class="vg6-pill t">Human = data</span><span class="vg6-pill">{input} placeholder</span></div>
      </div>
    </div>

    <div class="vg6-qa-item vg6-reveal">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Explain</span><br>Why use <code>.batch()</code> instead of looping <code>.invoke()</code>?</div>
      <div class="vg6-qa-a"><code>.batch()</code> sends multiple requests <strong>concurrently</strong> using asyncio under the hood, while <code>.invoke()</code> is sequential. For 8 articles, batch is roughly 8x faster. The sleep between batches manages rate limits — you get concurrency within a batch, pacing across batches.
        <div class="vg6-pills"><span class="vg6-pill t">Concurrent within batch</span><span class="vg6-pill a">Sleep between batches</span><span class="vg6-pill">8x throughput gain</span></div>
      </div>
    </div>

    <div class="vg6-qa-item vg6-reveal vg6-d1">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Gotcha</span><br>Why separate success and failure lists instead of crashing on parse error?</div>
      <div class="vg6-qa-a">At 1,000+ LLM calls, <strong>some will fail</strong> — network timeouts, content policy refusals, or models that occasionally output extra text before the JSON. A try/except pattern collects failures without losing the successful results. Failures can be inspected and retried separately.
        <div class="vg6-pills"><span class="vg6-pill a">Never crash on parse error</span><span class="vg6-pill">Inspect failures separately</span><span class="vg6-pill t">Retry pattern</span></div>
      </div>
    </div>

    <div class="vg6-qa-item vg6-reveal">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Best Practice</span><br>How do you get reliable structured JSON from an LLM?</div>
      <div class="vg6-qa-a">Three layers: <strong>(1) Constrain in the prompt</strong> — list valid values, specify exact schema, say &#8220;output ONLY JSON&#8221;. <strong>(2) Use LangChain&#8217;s output parsers</strong> (<code>JsonOutputParser</code>) for automatic parsing and retry. <strong>(3) Validate with Pydantic</strong> — define a model and parse the JSON through it to catch type errors.
        <div class="vg6-pills"><span class="vg6-pill t">Constrain schema in prompt</span><span class="vg6-pill t">JsonOutputParser</span><span class="vg6-pill a">Pydantic validation</span></div>
      </div>
    </div>

    <div class="vg6-qa-item vg6-reveal vg6-d1">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Explain</span><br>Why use Databricks for this pipeline?</div>
      <div class="vg6-qa-a">Databricks provides a <strong>managed Spark + Python environment</strong> that scales horizontally. For 10k–10M articles, you can parallelize across a cluster using Spark UDFs or <code>pandas_udf</code>. It also integrates with Delta Lake for storing results, MLflow for experiment tracking, and Unity Catalog for data governance.
        <div class="vg6-pills"><span class="vg6-pill t">Horizontal scale</span><span class="vg6-pill t">Delta Lake storage</span><span class="vg6-pill">MLflow tracking</span></div>
      </div>
    </div>

    <div class="vg6-qa-item vg6-reveal">
      <div class="vg6-qa-q"><span class="vg6-q-badge">Improve</span><br>How would you scale this to 10 million articles?</div>
      <div class="vg6-qa-a"><strong>Three upgrades:</strong> (1) Wrap the chain call in a <strong>Spark pandas_udf</strong> so it runs in parallel across the cluster. (2) Replace <code>time.sleep()</code> with <strong>exponential backoff</strong> via <code>tenacity</code>. (3) Use <strong>LangChain&#8217;s async batch</strong> with <code>chain.abatch()</code> and asyncio for maximum concurrency per node.
        <div class="vg6-pills"><span class="vg6-pill t">Spark pandas_udf</span><span class="vg6-pill t">chain.abatch()</span><span class="vg6-pill a">tenacity backoff</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg6-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <div class="vg6-footer-links">
    <a href="https://github.com/vijaygokarn130" class="vg6-footer-btn ghost">GitHub ↗</a>
    <a href="https://vijay-gokarn.com" class="vg6-footer-btn primary">Back to Blog ↗</a>
  </div>
</div>

</div><!-- /vg6 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg6-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg6-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>
<p>The post <a href="https://vijay-gokarn.com/analyzing-wikipedia-articles-with-langchain-and-openai-in-databricks/">Analyzing Wikipedia Articles with Langchain and OpenAI in Databricks</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">140</post-id>	</item>
		<item>
		<title>RAG: Retrieval-Augmented Generation.</title>
		<link>https://vijay-gokarn.com/rag-retrieval-augmented-generation/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rag-retrieval-augmented-generation</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Mon, 15 Jul 2024 02:13:23 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=122</guid>

					<description><![CDATA[<p>GenAI Mastery Series · RAG · NLP · HuggingFace · FAISS Retrieval-Augmented Generation — Build a RAG Pipeline from Scratch RetrieverDPR + FAISS GeneratorBART (facebook/bart-large-cnn) StackHuggingFace Transformers · PyTorch Stack transformers faiss-cpu torch DPR Question Encoder DPR Context Encoder BART Generator datasets RAG (Retrieval-Augmented Generation) combines the factual accuracy of information retrieval with the fluent [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/rag-retrieval-augmented-generation/">RAG: Retrieval-Augmented Generation.</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg7 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  --code-bg: #161b22; --code-header: #2d333b; --code-border: rgba(255,255,255,0.06);
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg7 *, .vg7 *::before, .vg7 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg7-hero { background: #0d1117; padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg7-hero::before {
  content: 'RAG'; font-family: 'Cormorant Garamond', serif; font-size: 18rem;
  font-weight: 300; color: rgba(255,255,255,0.025); position: absolute;
  right: -1rem; bottom: -4rem; line-height: 1; pointer-events: none; letter-spacing: -0.05em;
}
.vg7-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg7-eyebrow { font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem; display: flex; align-items: center; gap: 0.75rem; }
.vg7-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg7-hero h1 { font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem); font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em; margin-bottom: 1.5rem; max-width: 26ch; }
.vg7-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg7-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg7-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg7-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* STACK BAND */
.vg7-stack-band { background: var(--teal); padding: 1.1rem 4rem; display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
.vg7-stack-label { font-size: 0.63rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(255,255,255,0.6); font-weight: 400; margin-right: 0.4rem; }
.vg7-stack-pill { font-size: 0.7rem; letter-spacing: 0.05em; padding: 0.28rem 0.85rem; background: rgba(255,255,255,0.12); color: #fff; border: 0.5px solid rgba(255,255,255,0.2); }

/* INTRO */
.vg7-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg7-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg7-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg7-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg7-step { margin-bottom: 3.5rem; }
.vg7-step-label { font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg7-step-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg7-step h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1rem; }
.vg7-step h2 em { font-style: italic; color: var(--teal); }
.vg7-step p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg7-step p strong { color: var(--ink); font-weight: 500; }
.vg7-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }
.vg7-ic { font-family: 'DM Mono', monospace; font-size: 0.82rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.4rem; color: var(--ink); }

/* CALLOUT */
.vg7-callout { background: var(--paper-dark); border-left: 3px solid var(--amber); padding: 1.25rem 1.5rem; margin: 1.25rem 0; font-size: 0.87rem; line-height: 1.8; color: var(--charcoal); }
.vg7-callout strong { color: var(--amber); font-weight: 500; }
.vg7-callout.teal { border-color: var(--teal); }
.vg7-callout.teal strong { color: var(--teal); }

/* RAG PILLARS */
.vg7-pillars { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--border); border: 0.5px solid var(--border); margin: 1.5rem 0; }
.vg7-pillar { background: var(--paper); padding: 1.75rem 1.5rem; position: relative; }
.vg7-pillar::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; }
.vg7-pillar:nth-child(1)::before { background: var(--muted); }
.vg7-pillar:nth-child(2)::before { background: var(--amber); }
.vg7-pillar:nth-child(3)::before { background: var(--teal); }
.vg7-pillar-letter { font-family: 'Cormorant Garamond', serif; font-size: 3rem; font-weight: 300; line-height: 1; margin-bottom: 0.5rem; letter-spacing: -0.02em; }
.vg7-pillar:nth-child(1) .vg7-pillar-letter { color: var(--muted); }
.vg7-pillar:nth-child(2) .vg7-pillar-letter { color: var(--amber); }
.vg7-pillar:nth-child(3) .vg7-pillar-letter { color: var(--teal); }
.vg7-pillar h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.15rem; font-weight: 400; color: var(--ink); margin-bottom: 0.4rem; }
.vg7-pillar p { font-size: 0.82rem; line-height: 1.7; color: var(--charcoal); font-weight: 300; }

/* WHY RAG */
.vg7-why-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin: 1.5rem 0; }
.vg7-why-card { background: var(--paper); border: 0.5px solid var(--border-strong); padding: 1.25rem 1.5rem; display: flex; gap: 1rem; align-items: flex-start; }
.vg7-why-num { font-family: 'DM Mono', monospace; font-size: 0.68rem; color: var(--teal); min-width: 1.5rem; margin-top: 0.15rem; flex-shrink: 0; }
.vg7-why-body h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--ink); margin-bottom: 0.3rem; }
.vg7-why-body p { font-size: 0.8rem; line-height: 1.65; color: var(--charcoal); font-weight: 300; }

/* ARCH DIAGRAM */
.vg7-arch { display: flex; align-items: center; gap: 0; margin: 1.5rem 0; flex-wrap: wrap; }
.vg7-arch-box { background: var(--paper); border: 0.5px solid var(--border-strong); padding: 0.9rem 1rem; text-align: center; flex: 1; min-width: 90px; }
.vg7-arch-box.hl { background: var(--teal); border-color: var(--teal); }
.vg7-arch-box.hl2 { background: var(--ink); border-color: var(--ink); }
.vg7-arch-box h5 { font-family: 'Cormorant Garamond', serif; font-size: 0.95rem; font-weight: 400; color: var(--ink); }
.vg7-arch-box.hl h5 { color: var(--paper); }
.vg7-arch-box.hl2 h5 { color: var(--paper); }
.vg7-arch-box p { font-size: 0.63rem; color: var(--muted); line-height: 1.3; font-weight: 300; margin-top: 0.2rem; }
.vg7-arch-box.hl p { color: rgba(247,244,239,0.6); }
.vg7-arch-box.hl2 p { color: rgba(247,244,239,0.5); }
.vg7-arch-arrow { font-size: 0.9rem; color: var(--muted); padding: 0 0.25rem; flex-shrink: 0; }

/* ── CODE BLOCKS ── */
.vg7-code-wrap { margin: 1.25rem 0; border: 0.5px solid var(--code-border); overflow: hidden; }
.vg7-code-header { background: var(--code-header); padding: 0.6rem 1.25rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 0.5px solid var(--code-border); }
.vg7-code-filename { font-family: 'DM Mono', monospace; font-size: 0.68rem; color: rgba(247,244,239,0.45); letter-spacing: 0.04em; }
.vg7-code-lang { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--teal-light); font-weight: 500; }
.vg7-code-body { background: var(--code-bg); padding: 1.5rem; overflow-x: auto; }
.vg7-code-body pre { margin: 0; }
.vg7-code-body code { font-family: 'DM Mono', monospace; font-size: 0.82rem; line-height: 1.85; color: #e6edf3; white-space: pre; display: block; }
/* syntax tokens */
.t-k  { color: #ff7b72; }
.t-s  { color: #a5d6ff; }
.t-c  { color: #8b949e; font-style: italic; }
.t-f  { color: #d2a8ff; }
.t-n  { color: #79c0ff; }
.t-v  { color: #ffa657; }
.t-m  { color: var(--teal-light); }
.t-p  { color: rgba(230,237,243,0.5); }
.t-cm { color: var(--amber-light); }

/* TERMINAL / PIP BLOCK */
.vg7-terminal { background: #0d1117; border: 0.5px solid rgba(255,255,255,0.1); padding: 1.25rem 1.5rem; margin: 1.25rem 0; font-family: 'DM Mono', monospace; font-size: 0.83rem; color: var(--teal-light); }
.vg7-terminal .t-prompt { color: rgba(247,244,239,0.25); margin-right: 0.5rem; user-select: none; }

/* INTERVIEW */
.vg7-interview-section { background: var(--ink); padding: 4rem; }
.vg7-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg7-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg7-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg7-interview-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg7-qa-list { display: flex; flex-direction: column; }
.vg7-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(247,244,239,0.1); align-items: start; }
.vg7-qa-item:last-child { border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg7-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--paper); line-height: 1.4; }
.vg7-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg7-qa-a { font-size: 0.83rem; line-height: 1.8; color: rgba(247,244,239,0.65); font-weight: 300; }
.vg7-qa-a strong { color: var(--amber-light); font-weight: 400; }
.vg7-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(247,244,239,0.08); padding: 0.1rem 0.35rem; color: var(--paper); }
.vg7-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg7-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); }
.vg7-pill.t { border-color: var(--teal-light); color: var(--teal-light); }
.vg7-pill.a { border-color: var(--amber-light); color: var(--amber-light); }

/* FOOTER */
.vg7-footer { background: #0d1117; padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; border-top: 0.5px solid rgba(247,244,239,0.06); }
.vg7-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg7-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg7-footer-links { display: flex; gap: 1rem; }
.vg7-btn { display: inline-block; padding: 0.65rem 1.75rem; font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }
.vg7-btn.primary { background: var(--teal); color: var(--paper); }
.vg7-btn.ghost { background: transparent; color: rgba(247,244,239,0.55); border: 0.5px solid rgba(247,244,239,0.2); }

/* REVEAL */
.vg7-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg7-reveal.vg7-vis { opacity: 1; transform: translateY(0); }
.vg7-d1 { transition-delay: 0.1s; } .vg7-d2 { transition-delay: 0.2s; } .vg7-d3 { transition-delay: 0.3s; }
</style>

<div class="vg7">

<!-- HERO -->
<div class="vg7-hero">
  <div class="vg7-hero-inner">
    <p class="vg7-eyebrow">GenAI Mastery Series · RAG · NLP · HuggingFace · FAISS</p>
    <h1>Retrieval-Augmented Generation — <em>Build a RAG Pipeline from Scratch</em></h1>
    <div class="vg7-meta-row">
      <p class="vg7-meta">Retriever<span>DPR + FAISS</span></p>
      <p class="vg7-meta">Generator<span>BART (facebook/bart-large-cnn)</span></p>
      <p class="vg7-meta">Stack<span>HuggingFace Transformers · PyTorch</span></p>
    </div>
  </div>
</div>

<!-- STACK BAND -->
<div class="vg7-stack-band">
  <span class="vg7-stack-label">Stack</span>
  <span class="vg7-stack-pill">transformers</span>
  <span class="vg7-stack-pill">faiss-cpu</span>
  <span class="vg7-stack-pill">torch</span>
  <span class="vg7-stack-pill">DPR Question Encoder</span>
  <span class="vg7-stack-pill">DPR Context Encoder</span>
  <span class="vg7-stack-pill">BART Generator</span>
  <span class="vg7-stack-pill">datasets</span>
</div>

<!-- INTRO -->
<div class="vg7-intro">
  <p><strong>RAG (Retrieval-Augmented Generation)</strong> combines the factual accuracy of information retrieval with the fluent language generation of large models. Instead of encoding all knowledge into model weights, it retrieves relevant documents at inference time and uses them as live context — producing more accurate, up-to-date, and traceable answers.</p>
</div>

<!-- BODY -->
<div class="vg7-body">

  <!-- WHAT IS RAG -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Concept</p>
    <h2>What is <em>RAG?</em></h2>
    <p>RAG stands for <strong>Retrieval-Augmented Generation</strong>. It&#8217;s a three-stage technique that grounds a language model&#8217;s output in retrieved facts — dramatically reducing hallucinations and enabling access to knowledge that wasn&#8217;t in the model&#8217;s training data.</p>
    <div class="vg7-pillars">
      <div class="vg7-pillar vg7-reveal vg7-d1">
        <div class="vg7-pillar-letter">R</div>
        <h3>Retrieval</h3>
        <p>Search a large knowledge base to find documents relevant to the query. Uses dense vector similarity (DPR + FAISS) or sparse BM25.</p>
      </div>
      <div class="vg7-pillar vg7-reveal vg7-d2">
        <div class="vg7-pillar-letter">A</div>
        <h3>Augmentation</h3>
        <p>Inject the retrieved documents into the prompt as context — supplementing the original query with verified external knowledge.</p>
      </div>
      <div class="vg7-pillar vg7-reveal vg7-d3">
        <div class="vg7-pillar-letter">G</div>
        <h3>Generation</h3>
        <p>The language model generates its response conditioned on both the original query and the retrieved context — grounded, not hallucinated.</p>
      </div>
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- WHY RAG -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Motivation</p>
    <h2>Why RAG <em>matters</em></h2>
    <div class="vg7-why-grid">
      <div class="vg7-why-card vg7-reveal vg7-d1">
        <span class="vg7-why-num">01</span>
        <div class="vg7-why-body"><h4>Reduces Hallucinations</h4><p>Retrieved documents anchor the model to factual content, reducing fabricated answers that plague purely parametric models.</p></div>
      </div>
      <div class="vg7-why-card vg7-reveal vg7-d2">
        <span class="vg7-why-num">02</span>
        <div class="vg7-why-body"><h4>Up-to-Date Knowledge</h4><p>The knowledge base can be updated without retraining the entire model — keeping responses current without a costly fine-tune cycle.</p></div>
      </div>
      <div class="vg7-why-card vg7-reveal vg7-d1">
        <span class="vg7-why-num">03</span>
        <div class="vg7-why-body"><h4>Source Transparency</h4><p>Every response is traceable back to specific retrieved documents — critical for compliance, audit, and trust in enterprise deployments.</p></div>
      </div>
      <div class="vg7-why-card vg7-reveal vg7-d2">
        <span class="vg7-why-num">04</span>
        <div class="vg7-why-body"><h4>Domain Customization</h4><p>Swap the knowledge base to instantly specialize the system for healthcare, legal, finance, or any vertical — without model retraining.</p></div>
      </div>
      <div class="vg7-why-card vg7-reveal vg7-d1">
        <span class="vg7-why-num">05</span>
        <div class="vg7-why-body"><h4>Compute Efficiency</h4><p>It&#8217;s far cheaper to retrieve specific knowledge at inference than to encode it all into billions of model parameters during training.</p></div>
      </div>
      <div class="vg7-why-card vg7-reveal vg7-d2">
        <span class="vg7-why-num">06</span>
        <div class="vg7-why-body"><h4>Contextual Relevance</h4><p>Each query pulls its own specific context — the model isn&#8217;t constrained to a fixed knowledge snapshot, it adapts per-query.</p></div>
      </div>
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- ARCHITECTURE -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Architecture</p>
    <h2>Pipeline <em>overview</em></h2>
    <p>This implementation uses <strong>Dense Passage Retrieval (DPR)</strong> for encoding both questions and documents into a shared vector space, <strong>FAISS</strong> for fast nearest-neighbor search, and <strong>BART</strong> as the sequence-to-sequence generator.</p>
    <div class="vg7-arch">
      <div class="vg7-arch-box"><h5>Query</h5><p>User input</p></div>
      <div class="vg7-arch-arrow">→</div>
      <div class="vg7-arch-box hl"><h5>DPR Encoder</h5><p>Question embedding</p></div>
      <div class="vg7-arch-arrow">→</div>
      <div class="vg7-arch-box"><h5>FAISS Search</h5><p>Top-K similar docs</p></div>
      <div class="vg7-arch-arrow">→</div>
      <div class="vg7-arch-box"><h5>Concat</h5><p>Query + context</p></div>
      <div class="vg7-arch-arrow">→</div>
      <div class="vg7-arch-box hl2"><h5>BART</h5><p>Generate response</p></div>
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- STEP 1 -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Step 1</p>
    <h2>Install <em>dependencies</em></h2>
    <p>Four libraries cover everything: <strong>transformers</strong> for DPR and BART models, <strong>datasets</strong> for data loading, <strong>faiss-cpu</strong> for vector indexing, and <strong>torch</strong> as the deep learning backend.</p>
    <div class="vg7-terminal">
      <span class="t-prompt">$</span><span style="color:var(--teal-light)">pip install</span> transformers datasets faiss-cpu torch
    </div>
    <div class="vg7-callout teal">
      <strong>GPU note:</strong> Replace <code>faiss-cpu</code> with <code>faiss-gpu</code> for GPU-accelerated indexing on large corpora. For the retriever and generator models, ensure CUDA is available — BART on CPU is significantly slower for generation.
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- STEP 2 -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Step 2</p>
    <h2>Load models <em>&#038; tokenizers</em></h2>
    <p>RAG uses <strong>two separate encoders</strong> from DPR: a Question Encoder for query embeddings and a Context Encoder for document embeddings. These are trained jointly so their vectors are comparable in the same space. BART is the conditional generation model that produces the final answer.</p>
    <div class="vg7-code-wrap">
      <div class="vg7-code-header"><span class="vg7-code-filename">models.py</span><span class="vg7-code-lang">Python</span></div>
      <div class="vg7-code-body"><pre><code><span class="t-k">from</span> transformers <span class="t-k">import</span> DPRQuestionEncoder, DPRQuestionEncoderTokenizer
<span class="t-k">from</span> transformers <span class="t-k">import</span> DPRContextEncoder, DPRContextEncoderTokenizer
<span class="t-k">from</span> transformers <span class="t-k">import</span> BartTokenizer, BartForConditionalGeneration

<span class="t-c"># ── RETRIEVER: encodes the user's question into a dense vector ──</span>
question_encoder = DPRQuestionEncoder.<span class="t-f">from_pretrained</span>(
    <span class="t-s">'facebook/dpr-question_encoder-single-nq-base'</span>
)
question_tokenizer = DPRQuestionEncoderTokenizer.<span class="t-f">from_pretrained</span>(
    <span class="t-s">'facebook/dpr-question_encoder-single-nq-base'</span>
)

<span class="t-c"># ── RETRIEVER: encodes each document into a dense vector ──</span>
context_encoder = DPRContextEncoder.<span class="t-f">from_pretrained</span>(
    <span class="t-s">'facebook/dpr-ctx_encoder-single-nq-base'</span>
)
context_tokenizer = DPRContextEncoderTokenizer.<span class="t-f">from_pretrained</span>(
    <span class="t-s">'facebook/dpr-ctx_encoder-single-nq-base'</span>
)

<span class="t-c"># ── GENERATOR: seq2seq model that produces the final answer ──</span>
generator_tokenizer = BartTokenizer.<span class="t-f">from_pretrained</span>(<span class="t-s">'facebook/bart-large-cnn'</span>)
generator = BartForConditionalGeneration.<span class="t-f">from_pretrained</span>(<span class="t-s">'facebook/bart-large-cnn'</span>)</code></pre></div>
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- STEP 3 -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Step 3</p>
    <h2>Prepare <em>your documents</em></h2>
    <p>Each document needs a <strong>title</strong> and <strong>text</strong> field. In production this could be chunks from a PDF, database rows, web-scraped articles, or any domain corpus. Keep chunk sizes manageable — 256 to 512 tokens is a common sweet spot for retrieval quality.</p>
    <div class="vg7-code-wrap">
      <div class="vg7-code-header"><span class="vg7-code-filename">data.py</span><span class="vg7-code-lang">Python</span></div>
      <div class="vg7-code-body"><pre><code><span class="t-c"># Each document is a dict with title + text</span>
<span class="t-c"># In production: load from PDF, DB, S3, or a vector store</span>
documents = [
    {<span class="t-s">"title"</span>: <span class="t-s">"Document 1"</span>, <span class="t-s">"text"</span>: <span class="t-s">"This is the text of document 1."</span>},
    {<span class="t-s">"title"</span>: <span class="t-s">"Document 2"</span>, <span class="t-s">"text"</span>: <span class="t-s">"This is the text of document 2."</span>},
    <span class="t-c"># Add your real documents here...</span>
]</code></pre></div>
    </div>
    <div class="vg7-callout">
      <strong>Chunking strategy matters:</strong> For long documents, split into overlapping chunks of ~300 tokens. Too large = diluted retrieval signal. Too small = missing context for the generator. Overlap of ~50 tokens prevents cutting a sentence at a chunk boundary.
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- STEP 4 -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Step 4</p>
    <h2>Build the <em>FAISS index</em></h2>
    <p>Each document&#8217;s text is encoded by the DPR Context Encoder into a <strong>768-dimensional vector</strong>. These embeddings are stacked into a numpy array and added to a FAISS <code class="vg7-ic">IndexFlatL2</code> — a flat L2-distance index that does exact nearest-neighbor search.</p>
    <div class="vg7-code-wrap">
      <div class="vg7-code-header"><span class="vg7-code-filename">indexer.py</span><span class="vg7-code-lang">Python</span></div>
      <div class="vg7-code-body"><pre><code><span class="t-k">import</span> faiss
<span class="t-k">import</span> numpy <span class="t-k">as</span> np

context_embeddings = []

<span class="t-k">for</span> doc <span class="t-k">in</span> documents:
    inputs     = <span class="t-f">context_tokenizer</span>(doc[<span class="t-s">'text'</span>], return_tensors=<span class="t-s">'pt'</span>)
    embeddings = <span class="t-f">context_encoder</span>(**inputs).pooler_output.<span class="t-f">detach</span>().<span class="t-f">numpy</span>()
    context_embeddings.<span class="t-f">append</span>(embeddings[<span class="t-n">0</span>])

<span class="t-c"># Stack into (num_docs, 768) numpy array</span>
context_embeddings = np.<span class="t-f">array</span>(context_embeddings)

<span class="t-c"># Build FAISS flat L2 index — exact search, best for small-medium corpora</span>
index = faiss.<span class="t-f">IndexFlatL2</span>(context_embeddings.shape[<span class="t-n">1</span>])
index.<span class="t-f">add</span>(context_embeddings)

<span class="t-f">print</span>(<span class="t-f">f</span><span class="t-s">"Index built: {index.ntotal} vectors of dim {context_embeddings.shape[1]}"</span>)</code></pre></div>
    </div>
    <div class="vg7-callout teal">
      <strong>Scaling up:</strong> <code class="vg7-ic">IndexFlatL2</code> does exhaustive search — fine for thousands of docs. For millions, switch to <code class="vg7-ic">IndexIVFFlat</code> (inverted file) or <code class="vg7-ic">IndexHNSWFlat</code> (graph-based ANN) for approximate but fast search. Managed options: Pinecone, Weaviate, pgvector.
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- STEP 5 -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Step 5</p>
    <h2>Retrieve <em>relevant documents</em></h2>
    <p>For a given query, the Question Encoder produces a dense vector in the same space as the document embeddings. FAISS finds the <strong>top-K nearest documents</strong> by L2 distance — these are the most semantically similar docs to the query.</p>
    <div class="vg7-code-wrap">
      <div class="vg7-code-header"><span class="vg7-code-filename">retriever.py</span><span class="vg7-code-lang">Python</span></div>
      <div class="vg7-code-body"><pre><code><span class="t-k">def</span> <span class="t-f">retrieve_documents</span>(query, top_k=<span class="t-n">5</span>):
    <span class="t-c"># Encode the query into a dense vector</span>
    inputs            = <span class="t-f">question_tokenizer</span>(query, return_tensors=<span class="t-s">'pt'</span>)
    question_embedding = <span class="t-f">question_encoder</span>(**inputs).pooler_output.<span class="t-f">detach</span>().<span class="t-f">numpy</span>()

    <span class="t-c"># Search FAISS for the top_k nearest document vectors</span>
    _, indices = index.<span class="t-f">search</span>(question_embedding, top_k)

    <span class="t-c"># Return the actual document dicts</span>
    <span class="t-k">return</span> [documents[idx] <span class="t-k">for</span> idx <span class="t-k">in</span> indices[<span class="t-n">0</span>]]


<span class="t-c"># ── Test it ──</span>
query         = <span class="t-s">"What is the text of document 1?"</span>
retrieved_docs = <span class="t-f">retrieve_documents</span>(query)
<span class="t-f">print</span>(retrieved_docs)</code></pre></div>
    </div>
  </div>

  <hr class="vg7-divider">

  <!-- STEP 6 -->
  <div class="vg7-step vg7-reveal">
    <p class="vg7-step-label">Step 6</p>
    <h2>Generate the <em>response</em></h2>
    <p>The retrieved document texts are concatenated and prepended to the query. BART processes this combined input using <strong>beam search</strong> (<code class="vg7-ic">num_beams=4</code>) to generate a fluent, coherent response grounded in the retrieved facts.</p>
    <div class="vg7-code-wrap">
      <div class="vg7-code-header"><span class="vg7-code-filename">generator.py</span><span class="vg7-code-lang">Python</span></div>
      <div class="vg7-code-body"><pre><code><span class="t-k">def</span> <span class="t-f">generate_response</span>(query, retrieved_docs):
    <span class="t-c"># Concat all retrieved doc texts into one context string</span>
    context = <span class="t-s">" "</span>.<span class="t-f">join</span>([doc[<span class="t-s">'text'</span>] <span class="t-k">for</span> doc <span class="t-k">in</span> retrieved_docs])

    <span class="t-c"># Tokenize query + context together (truncate at 1024 tokens)</span>
    inputs = <span class="t-f">generator_tokenizer</span>(
        query + <span class="t-s">" "</span> + context,
        return_tensors = <span class="t-s">'pt'</span>,
        max_length     = <span class="t-n">1024</span>,
        truncation     = <span class="t-k">True</span>
    )

    <span class="t-c"># Generate with beam search for higher quality output</span>
    summary_ids = generator.<span class="t-f">generate</span>(
        inputs[<span class="t-s">'input_ids'</span>],
        num_beams     = <span class="t-n">4</span>,
        max_length    = <span class="t-n">512</span>,
        early_stopping = <span class="t-k">True</span>
    )

    <span class="t-k">return</span> generator_tokenizer.<span class="t-f">decode</span>(summary_ids[<span class="t-n">0</span>], skip_special_tokens=<span class="t-k">True</span>)


<span class="t-c"># ── End-to-end test ──</span>
query         = <span class="t-s">"What is the text of document 1?"</span>
retrieved_docs = <span class="t-f">retrieve_documents</span>(query)
response      = <span class="t-f">generate_response</span>(query, retrieved_docs)
<span class="t-f">print</span>(response)</code></pre></div>
    </div>
    <div class="vg7-callout">
      <strong>Beam search vs greedy:</strong> <code class="vg7-ic">num_beams=1</code> is greedy — fast but lower quality. <code class="vg7-ic">num_beams=4</code> keeps 4 candidate sequences at each step and returns the highest-scoring one. For production, <code class="vg7-ic">num_beams=4</code> with <code class="vg7-ic">early_stopping=True</code> is the standard BART configuration.
    </div>
  </div>

</div><!-- /vg7-body -->

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg7-interview-section">
  <p class="vg7-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg7-qa-list">

    <div class="vg7-qa-item vg7-reveal">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Define</span><br>What is RAG in one sentence?</div>
      <div class="vg7-qa-a"><strong>Retrieve relevant documents, inject them as context, then generate a grounded response</strong> — combining the precision of information retrieval with the fluency of a language model to reduce hallucinations and enable access to external knowledge.
        <div class="vg7-pills"><span class="vg7-pill t">Retrieve → Augment → Generate</span><span class="vg7-pill a">Reduces hallucinations</span></div>
      </div>
    </div>

    <div class="vg7-qa-item vg7-reveal vg7-d1">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Explain</span><br>What is DPR and why two encoders?</div>
      <div class="vg7-qa-a"><strong>Dense Passage Retrieval</strong> — two separate BERT-based encoders trained jointly: a Question Encoder and a Context Encoder. They&#8217;re kept separate because questions and documents have different linguistic structure. Joint training ensures their output vectors are comparable in the same embedding space.
        <div class="vg7-pills"><span class="vg7-pill t">Question Encoder</span><span class="vg7-pill t">Context Encoder</span><span class="vg7-pill">Same vector space</span></div>
      </div>
    </div>

    <div class="vg7-qa-item vg7-reveal">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Explain</span><br>What is FAISS and when would you replace it?</div>
      <div class="vg7-qa-a"><strong>Facebook AI Similarity Search</strong> — a library for fast nearest-neighbor search over dense vectors. <code>IndexFlatL2</code> does exact exhaustive search — fine for thousands of docs but O(n) per query. For millions of docs, switch to <code>IndexIVFFlat</code> (approximate, partitioned) or a managed vector DB like Pinecone, Weaviate, or pgvector.
        <div class="vg7-pills"><span class="vg7-pill t">Exact: IndexFlatL2</span><span class="vg7-pill a">Approx: IVFFlat / HNSW</span><span class="vg7-pill">Scale: Pinecone / pgvector</span></div>
      </div>
    </div>

    <div class="vg7-qa-item vg7-reveal vg7-d1">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Compare</span><br>RAG vs fine-tuning — when to use which?</div>
      <div class="vg7-qa-a">Use <strong>RAG</strong> when knowledge changes frequently, you need source attribution, or you want to avoid the cost of retraining. Use <strong>fine-tuning</strong> when you need the model to learn a new style, format, or reasoning pattern that retrieval can&#8217;t provide. In practice, the best systems combine both.
        <div class="vg7-pills"><span class="vg7-pill t">RAG = dynamic knowledge</span><span class="vg7-pill a">Fine-tune = style / reasoning</span><span class="vg7-pill">Combine for best results</span></div>
      </div>
    </div>

    <div class="vg7-qa-item vg7-reveal">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Gotcha</span><br>What is the &#8220;lost in the middle&#8221; problem in RAG?</div>
      <div class="vg7-qa-a">When multiple documents are concatenated as context, LLMs tend to attend best to the <strong>beginning and end</strong> of the input — information in the middle gets underweighted. Mitigations: rerank retrieved docs by relevance before concatenation, or use a model with a longer, more uniform attention mechanism.
        <div class="vg7-pills"><span class="vg7-pill a">Middle docs underweighted</span><span class="vg7-pill t">Rerank before concat</span><span class="vg7-pill">Limit top_k to 3–5</span></div>
      </div>
    </div>

    <div class="vg7-qa-item vg7-reveal vg7-d1">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Explain</span><br>What does beam search do in generation?</div>
      <div class="vg7-qa-a">Instead of greedily picking the single best next token at each step, <strong>beam search keeps the top N candidate sequences</strong> (beams) in parallel and returns the highest-scoring complete sequence. <code>num_beams=4</code> explores 4 paths simultaneously — better quality than greedy, with manageable compute overhead.
        <div class="vg7-pills"><span class="vg7-pill">num_beams=1 = greedy</span><span class="vg7-pill t">num_beams=4 = quality</span><span class="vg7-pill a">Higher beams = slower</span></div>
      </div>
    </div>

    <div class="vg7-qa-item vg7-reveal">
      <div class="vg7-qa-q"><span class="vg7-q-badge">Improve</span><br>How would you modernize this RAG stack for production?</div>
      <div class="vg7-qa-a"><strong>Three upgrades:</strong> (1) Replace DPR + BART with a <strong>single LLM via Bedrock or OpenAI</strong> — better quality, less infrastructure. (2) Replace FAISS with <strong>pgvector or Pinecone</strong> for managed, scalable retrieval. (3) Add a <strong>reranker</strong> (cross-encoder) between retrieval and generation to reorder results by relevance before injecting as context.
        <div class="vg7-pills"><span class="vg7-pill t">Bedrock / OpenAI LLM</span><span class="vg7-pill t">pgvector / Pinecone</span><span class="vg7-pill a">Cross-encoder reranker</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg7-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <div class="vg7-footer-links">
    <a href="https://github.com/vijaygokarn130" class="vg7-btn ghost">GitHub ↗</a>
    <a href="https://vijay-gokarn.com" class="vg7-btn primary">Back to Blog ↗</a>
  </div>
</div>

</div><!-- /vg7 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg7-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg7-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>v
<p>The post <a href="https://vijay-gokarn.com/rag-retrieval-augmented-generation/">RAG: Retrieval-Augmented Generation.</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">122</post-id>	</item>
		<item>
		<title>Pandas Remove Duplicates</title>
		<link>https://vijay-gokarn.com/pandas-remove-duplicates/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pandas-remove-duplicates</link>
		
		<dc:creator><![CDATA[Vijay Gokarn]]></dc:creator>
		<pubDate>Tue, 09 Jul 2024 11:12:55 +0000</pubDate>
				<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[databricks]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[generative-ai]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[data-analysis]]></category>
		<category><![CDATA[gen-ai]]></category>
		<category><![CDATA[pandas]]></category>
		<guid isPermaLink="false">https://vijay-gokarn.com/?p=119</guid>

					<description><![CDATA[<p>Data Engineering · Python · Pandas · Data Cleaning Handling Duplicate Rows in Pandas — Identify, Remove &#038; Export Clean Data Librarypandas Methodsduplicated() · drop_duplicates() · reset_index() OutputCleaned CSV Stack Python pandas df.duplicated() drop_duplicates() reset_index() to_csv() Duplicate rows are one of the most common data quality issues — and one of the most damaging to [&#8230;]</p>
<p>The post <a href="https://vijay-gokarn.com/pandas-remove-duplicates/">Pandas Remove Duplicates</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&#038;family=DM+Sans:wght@300;400;500&#038;family=DM+Mono:wght@400&#038;display=swap" rel="stylesheet">

<style>
.vg8 {
  --ink: #0e0e0e; --paper: #f7f4ef; --paper-dark: #ede9e1;
  --teal: #0f6e56; --teal-light: #1d9e75; --teal-muted: #e1f5ee;
  --amber: #ba7517; --amber-light: #fac775; --amber-muted: #faeeda;
  --charcoal: #2c2c2a; --muted: #888780;
  --border: rgba(14,14,14,0.12); --border-strong: rgba(14,14,14,0.25);
  --code-bg: #161b22; --code-header: #2d333b; --code-border: rgba(255,255,255,0.06);
  font-family: 'DM Sans', sans-serif; font-weight: 300;
  color: var(--ink); background: var(--paper); line-height: 1.75; font-size: 16px; overflow-x: hidden;
}
.vg8 *, .vg8 *::before, .vg8 *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* HERO */
.vg8-hero { background: #0d1117; padding: 5rem 4rem 4rem; position: relative; overflow: hidden; }
.vg8-hero::before {
  content: '⊕'; font-family: 'Cormorant Garamond', serif; font-size: 22rem;
  font-weight: 300; color: rgba(255,255,255,0.025); position: absolute;
  right: 1rem; bottom: -5rem; line-height: 1; pointer-events: none;
}
.vg8-hero-inner { position: relative; z-index: 1; max-width: 900px; }
.vg8-eyebrow { font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal-light); font-weight: 500; margin-bottom: 1.25rem; display: flex; align-items: center; gap: 0.75rem; }
.vg8-eyebrow::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--teal-light); }
.vg8-hero h1 { font-family: 'Cormorant Garamond', serif; font-size: clamp(2.2rem, 5vw, 3.8rem); font-weight: 300; line-height: 1.1; color: var(--paper); letter-spacing: -0.02em; margin-bottom: 1.5rem; max-width: 28ch; }
.vg8-hero h1 em { font-style: italic; color: var(--amber-light); }
.vg8-meta-row { display: flex; gap: 2rem; flex-wrap: wrap; }
.vg8-meta { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(247,244,239,0.35); }
.vg8-meta span { color: rgba(247,244,239,0.7); margin-left: 0.4rem; }

/* STACK BAND */
.vg8-stack-band { background: var(--teal); padding: 1.1rem 4rem; display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
.vg8-stack-label { font-size: 0.63rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(255,255,255,0.6); font-weight: 400; margin-right: 0.4rem; }
.vg8-stack-pill { font-size: 0.7rem; letter-spacing: 0.05em; padding: 0.28rem 0.85rem; background: rgba(255,255,255,0.12); color: #fff; border: 0.5px solid rgba(255,255,255,0.2); }

/* INTRO */
.vg8-intro { background: var(--teal-muted); padding: 2.5rem 4rem; border-left: 4px solid var(--teal); }
.vg8-intro p { font-size: 1.05rem; line-height: 1.85; color: var(--charcoal); font-weight: 300; max-width: 80ch; }
.vg8-intro strong { color: var(--teal); font-weight: 500; }

/* BODY */
.vg8-body { max-width: 900px; margin: 0 auto; padding: 4rem; }
.vg8-step { margin-bottom: 3.5rem; }
.vg8-step-label { font-size: 0.63rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg8-step-label::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg8-step h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 300; line-height: 1.2; color: var(--ink); margin-bottom: 1rem; }
.vg8-step h2 em { font-style: italic; color: var(--teal); }
.vg8-step p { font-size: 0.93rem; line-height: 1.9; color: var(--charcoal); font-weight: 300; margin-bottom: 1rem; }
.vg8-step p strong { color: var(--ink); font-weight: 500; }
.vg8-divider { border: none; border-top: 0.5px solid var(--border); margin: 3rem 0; }
.vg8-ic { font-family: 'DM Mono', monospace; font-size: 0.82rem; background: rgba(14,14,14,0.07); padding: 0.1rem 0.4rem; color: var(--ink); }

/* CALLOUT */
.vg8-callout { background: var(--paper-dark); border-left: 3px solid var(--amber); padding: 1.25rem 1.5rem; margin: 1.25rem 0; font-size: 0.87rem; line-height: 1.8; color: var(--charcoal); }
.vg8-callout strong { color: var(--amber); font-weight: 500; }
.vg8-callout.teal { border-color: var(--teal); }
.vg8-callout.teal strong { color: var(--teal); }

/* STRATEGY CARDS */
.vg8-strategy-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; margin: 1.5rem 0; }
.vg8-strategy-card { background: var(--paper); border: 0.5px solid var(--border-strong); padding: 1.5rem; position: relative; }
.vg8-strategy-card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 4px; }
.vg8-strategy-card:nth-child(1)::before { background: var(--muted); }
.vg8-strategy-card:nth-child(2)::before { background: var(--amber); }
.vg8-strategy-card:nth-child(3)::before { background: var(--teal); }
.vg8-strategy-card .vg8-strat-tag { font-family: 'DM Mono', monospace; font-size: 0.65rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.5rem; display: block; }
.vg8-strategy-card:nth-child(2) .vg8-strat-tag { color: var(--amber); }
.vg8-strategy-card:nth-child(3) .vg8-strat-tag { color: var(--teal); }
.vg8-strategy-card h3 { font-family: 'Cormorant Garamond', serif; font-size: 1.15rem; font-weight: 400; color: var(--ink); margin-bottom: 0.4rem; }
.vg8-strategy-card p { font-size: 0.82rem; line-height: 1.7; color: var(--charcoal); font-weight: 300; }

/* PIPELINE */
.vg8-pipeline { display: flex; flex-direction: column; gap: 0; margin: 1.5rem 0; }
.vg8-pipeline-step { display: grid; grid-template-columns: 52px 1fr; gap: 1.5rem; padding: 1.25rem 0; border-top: 0.5px solid var(--border); align-items: start; }
.vg8-pipeline-step:last-child { border-bottom: 0.5px solid var(--border); }
.vg8-pipeline-num { width: 36px; height: 36px; background: var(--teal); display: flex; align-items: center; justify-content: center; font-family: 'Cormorant Garamond', serif; font-size: 1.1rem; font-weight: 300; color: var(--paper); flex-shrink: 0; }
.vg8-pipeline-body h4 { font-family: 'Cormorant Garamond', serif; font-size: 1.1rem; font-weight: 400; color: var(--ink); margin-bottom: 0.3rem; }
.vg8-pipeline-body p { font-size: 0.83rem; line-height: 1.7; color: var(--charcoal); font-weight: 300; }

/* CODE BLOCKS */
.vg8-code-wrap { margin: 1.25rem 0; border: 0.5px solid var(--code-border); overflow: hidden; }
.vg8-code-header { background: var(--code-header); padding: 0.6rem 1.25rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 0.5px solid var(--code-border); }
.vg8-code-filename { font-family: 'DM Mono', monospace; font-size: 0.68rem; color: rgba(247,244,239,0.45); letter-spacing: 0.04em; }
.vg8-code-lang { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--teal-light); font-weight: 500; }
.vg8-code-body { background: var(--code-bg); padding: 1.5rem; overflow-x: auto; }
.vg8-code-body pre { margin: 0; }
.vg8-code-body code { font-family: 'DM Mono', monospace; font-size: 0.82rem; line-height: 1.85; color: #e6edf3; white-space: pre; display: block; }
/* tokens */
.t8-k { color: #ff7b72; }
.t8-s { color: #a5d6ff; }
.t8-c { color: #8b949e; font-style: italic; }
.t8-f { color: #d2a8ff; }
.t8-n { color: #79c0ff; }
.t8-v { color: #ffa657; }
.t8-b { color: var(--amber-light); }

/* FULL SCRIPT SECTION */
.vg8-full-section { background: var(--paper-dark); padding: 4rem; }
.vg8-full-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg8-full-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--teal); }
.vg8-full-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--ink); margin-bottom: 0.75rem; }
.vg8-full-section > h2 em { font-style: italic; color: var(--teal); }
.vg8-full-section > p { font-size: 0.9rem; color: var(--charcoal); font-weight: 300; line-height: 1.8; margin-bottom: 2rem; max-width: 70ch; }

/* INTERVIEW */
.vg8-interview-section { background: var(--ink); padding: 4rem; }
.vg8-interview-eyebrow { font-size: 0.65rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--amber-light); font-weight: 500; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; }
.vg8-interview-eyebrow::before { content: ''; display: inline-block; width: 1.25rem; height: 1px; background: var(--amber-light); }
.vg8-interview-section > h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 300; color: var(--paper); margin-bottom: 2.5rem; }
.vg8-interview-section > h2 em { font-style: italic; color: var(--amber-light); }
.vg8-qa-list { display: flex; flex-direction: column; }
.vg8-qa-item { display: grid; grid-template-columns: 1fr 1.4fr; gap: 2rem; padding: 1.5rem 0; border-top: 0.5px solid rgba(247,244,239,0.1); align-items: start; }
.vg8-qa-item:last-child { border-bottom: 0.5px solid rgba(247,244,239,0.1); }
.vg8-qa-q { font-family: 'Cormorant Garamond', serif; font-size: 1.05rem; font-weight: 400; color: var(--paper); line-height: 1.4; }
.vg8-q-badge { font-family: 'DM Mono', monospace; font-size: 0.58rem; letter-spacing: 0.1em; text-transform: uppercase; background: var(--teal); color: var(--paper); padding: 0.15rem 0.5rem; margin-bottom: 0.5rem; display: inline-block; }
.vg8-qa-a { font-size: 0.83rem; line-height: 1.8; color: rgba(247,244,239,0.65); font-weight: 300; }
.vg8-qa-a strong { color: var(--amber-light); font-weight: 400; }
.vg8-qa-a code { font-family: 'DM Mono', monospace; font-size: 0.77rem; background: rgba(247,244,239,0.08); padding: 0.1rem 0.35rem; color: var(--paper); }
.vg8-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.vg8-pill { font-size: 0.67rem; letter-spacing: 0.06em; padding: 0.25rem 0.75rem; border: 0.5px solid rgba(247,244,239,0.15); color: rgba(247,244,239,0.5); }
.vg8-pill.t { border-color: var(--teal-light); color: var(--teal-light); }
.vg8-pill.a { border-color: var(--amber-light); color: var(--amber-light); }

/* FOOTER */
.vg8-footer { background: #0d1117; padding: 3rem 4rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; border-top: 0.5px solid rgba(247,244,239,0.06); }
.vg8-footer p { font-size: 0.82rem; color: rgba(247,244,239,0.35); font-weight: 300; }
.vg8-footer p strong { color: rgba(247,244,239,0.65); font-weight: 400; }
.vg8-footer-links { display: flex; gap: 1rem; }
.vg8-btn { display: inline-block; padding: 0.65rem 1.75rem; font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; font-weight: 400; }
.vg8-btn.primary { background: var(--teal); color: var(--paper); }
.vg8-btn.ghost { background: transparent; color: rgba(247,244,239,0.55); border: 0.5px solid rgba(247,244,239,0.2); }

/* REVEAL */
.vg8-reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.55s ease, transform 0.55s ease; }
.vg8-reveal.vg8-vis { opacity: 1; transform: translateY(0); }
.vg8-d1 { transition-delay: 0.1s; } .vg8-d2 { transition-delay: 0.2s; } .vg8-d3 { transition-delay: 0.3s; }
</style>

<div class="vg8">

<!-- HERO -->
<div class="vg8-hero">
  <div class="vg8-hero-inner">
    <p class="vg8-eyebrow">Data Engineering · Python · Pandas · Data Cleaning</p>
    <h1>Handling Duplicate Rows in Pandas — <em>Identify, Remove &#038; Export Clean Data</em></h1>
    <div class="vg8-meta-row">
      <p class="vg8-meta">Library<span>pandas</span></p>
      <p class="vg8-meta">Methods<span>duplicated() · drop_duplicates() · reset_index()</span></p>
      <p class="vg8-meta">Output<span>Cleaned CSV</span></p>
    </div>
  </div>
</div>

<!-- STACK BAND -->
<div class="vg8-stack-band">
  <span class="vg8-stack-label">Stack</span>
  <span class="vg8-stack-pill">Python</span>
  <span class="vg8-stack-pill">pandas</span>
  <span class="vg8-stack-pill">df.duplicated()</span>
  <span class="vg8-stack-pill">drop_duplicates()</span>
  <span class="vg8-stack-pill">reset_index()</span>
  <span class="vg8-stack-pill">to_csv()</span>
</div>

<!-- INTRO -->
<div class="vg8-intro">
  <p>Duplicate rows are one of the most common data quality issues — and one of the most damaging to model accuracy and analysis reliability. <strong>Pandas</strong> gives you precise tools to detect, inspect, and remove duplicates with a single line of code. This guide walks through the full pipeline: load, detect, choose a strategy, clean, and export.</p>
</div>

<!-- BODY -->
<div class="vg8-body">

  <!-- WHY IT MATTERS -->
  <div class="vg8-step vg8-reveal">
    <p class="vg8-step-label">Context</p>
    <h2>Why duplicates <em>matter</em></h2>
    <p>Duplicate rows skew aggregations, inflate record counts, bias ML model training, and produce misleading visualizations. A sales total that counts the same transaction twice, a classifier trained on repeated samples — both produce results that look correct but aren&#8217;t. <strong>Clean data is the foundation everything else is built on.</strong></p>
    <div class="vg8-strategy-grid">
      <div class="vg8-strategy-card vg8-reveal vg8-d1">
        <span class="vg8-strat-tag">keep=&#8217;first&#8217;</span>
        <h3>Keep First</h3>
        <p>Drop all duplicates <em>except</em> the first occurrence. The original record is preserved. Most common default choice.</p>
      </div>
      <div class="vg8-strategy-card vg8-reveal vg8-d2">
        <span class="vg8-strat-tag">keep=&#8217;last&#8217;</span>
        <h3>Keep Last</h3>
        <p>Drop all duplicates <em>except</em> the last occurrence. Useful when later records represent updated values.</p>
      </div>
      <div class="vg8-strategy-card vg8-reveal vg8-d3">
        <span class="vg8-strat-tag">keep=False</span>
        <h3>Drop All</h3>
        <p>Remove every instance of a duplicated row — including the first. Use when any duplicated record is invalid.</p>
      </div>
    </div>
  </div>

  <hr class="vg8-divider">

  <!-- PIPELINE OVERVIEW -->
  <div class="vg8-step vg8-reveal">
    <p class="vg8-step-label">Pipeline</p>
    <h2>The four-step <em>deduplication pipeline</em></h2>
    <div class="vg8-pipeline">
      <div class="vg8-pipeline-step vg8-reveal">
        <div class="vg8-pipeline-num">1</div>
        <div class="vg8-pipeline-body"><h4>Load</h4><p>Read the raw CSV into a DataFrame with <code class="vg8-ic">pd.read_csv()</code>.</p></div>
      </div>
      <div class="vg8-pipeline-step vg8-reveal vg8-d1">
        <div class="vg8-pipeline-num">2</div>
        <div class="vg8-pipeline-body"><h4>Detect</h4><p>Use <code class="vg8-ic">df.duplicated()</code> to identify and inspect all duplicate rows before touching the data.</p></div>
      </div>
      <div class="vg8-pipeline-step vg8-reveal vg8-d2">
        <div class="vg8-pipeline-num">3</div>
        <div class="vg8-pipeline-body"><h4>Remove</h4><p>Call <code class="vg8-ic">drop_duplicates(keep=...)</code> with your chosen strategy. Reset the index for a clean sequential result.</p></div>
      </div>
      <div class="vg8-pipeline-step vg8-reveal vg8-d3">
        <div class="vg8-pipeline-num">4</div>
        <div class="vg8-pipeline-body"><h4>Export</h4><p>Write the cleaned DataFrame back to CSV with <code class="vg8-ic">to_csv()</code> for downstream use.</p></div>
      </div>
    </div>
  </div>

  <hr class="vg8-divider">

  <!-- STEP 1 — LOAD -->
  <div class="vg8-step vg8-reveal">
    <p class="vg8-step-label">Step 1</p>
    <h2>Load <em>your dataset</em></h2>
    <p>Start by reading your data into a pandas DataFrame. <code class="vg8-ic">pd.read_csv()</code> is the standard entry point for flat files. From here, all deduplication operations work on the in-memory DataFrame — your source file is never modified.</p>
    <div class="vg8-code-wrap">
      <div class="vg8-code-header"><span class="vg8-code-filename">load_data.py</span><span class="vg8-code-lang">Python</span></div>
      <div class="vg8-code-body"><pre><code><span class="t8-k">import</span> pandas <span class="t8-k">as</span> pd

<span class="t8-c"># Read the raw dataset into a DataFrame</span>
df = pd.<span class="t8-f">read_csv</span>(<span class="t8-s">'your_data_file.csv'</span>)

<span class="t8-c"># Quick shape check before cleaning</span>
<span class="t8-f">print</span>(<span class="t8-f">f</span><span class="t8-s">"Rows: {df.shape[0]:,}  |  Columns: {df.shape[1]}"</span>)</code></pre></div>
    </div>
    <div class="vg8-callout teal">
      <strong>Other sources:</strong> The same deduplication logic applies regardless of how you load your data. Use <code class="vg8-ic">pd.read_excel()</code> for XLSX, <code class="vg8-ic">pd.read_parquet()</code> for Parquet, or query a database with <code class="vg8-ic">pd.read_sql()</code> — all return a DataFrame you can clean the same way.
    </div>
  </div>

  <hr class="vg8-divider">

  <!-- STEP 2 — DETECT -->
  <div class="vg8-step vg8-reveal">
    <p class="vg8-step-label">Step 2</p>
    <h2>Detect <em>&#038; inspect duplicates</em></h2>
    <p><code class="vg8-ic">df.duplicated()</code> returns a boolean Series — <code class="vg8-ic">True</code> for every row that is a duplicate of an earlier row. Always <strong>inspect before you remove</strong> — understanding what the duplicates look like helps you choose the right strategy.</p>
    <div class="vg8-code-wrap">
      <div class="vg8-code-header"><span class="vg8-code-filename">detect_duplicates.py</span><span class="vg8-code-lang">Python</span></div>
      <div class="vg8-code-body"><pre><code><span class="t8-c"># Boolean mask: True for every row that is a duplicate</span>
duplicate_mask = df.<span class="t8-f">duplicated</span>()

<span class="t8-c"># How many duplicates exist?</span>
<span class="t8-f">print</span>(<span class="t8-f">f</span><span class="t8-s">"Duplicate rows found: {duplicate_mask.sum():,}"</span>)

<span class="t8-c"># Inspect the duplicate rows themselves</span>
duplicates = df[df.<span class="t8-f">duplicated</span>()]
<span class="t8-f">print</span>(duplicates)

<span class="t8-c"># See ALL occurrences of duplicated rows (including originals)</span>
all_dupes = df[df.<span class="t8-f">duplicated</span>(keep=<span class="t8-b">False</span>)]
<span class="t8-f">print</span>(all_dupes.<span class="t8-f">sort_values</span>(by=df.columns.<span class="t8-f">tolist</span>()))</code></pre></div>
    </div>
    <div class="vg8-callout">
      <strong>Subset duplicates:</strong> By default <code class="vg8-ic">duplicated()</code> checks all columns. To flag rows that are duplicates only on specific columns (e.g. same customer_id): <code class="vg8-ic">df.duplicated(subset=['customer_id'])</code>. This is useful for finding logical duplicates even when other columns differ.
    </div>
  </div>

  <hr class="vg8-divider">

  <!-- STEP 3 — REMOVE -->
  <div class="vg8-step vg8-reveal">
    <p class="vg8-step-label">Step 3</p>
    <h2>Remove duplicates — <em>three strategies</em></h2>
    <p><code class="vg8-ic">drop_duplicates()</code> returns a new DataFrame by default — the original is untouched. The <code class="vg8-ic">keep</code> parameter controls which occurrence survives. After removing, <code class="vg8-ic">reset_index(drop=True)</code> gives you a clean sequential index starting from 0.</p>
    <div class="vg8-code-wrap">
      <div class="vg8-code-header"><span class="vg8-code-filename">remove_duplicates.py</span><span class="vg8-code-lang">Python</span></div>
      <div class="vg8-code-body"><pre><code><span class="t8-c"># ── Strategy 1: keep the FIRST occurrence (default) ──</span>
df_keep_first = df.<span class="t8-f">drop_duplicates</span>(keep=<span class="t8-s">'first'</span>)

<span class="t8-c"># ── Strategy 2: keep the LAST occurrence ──</span>
<span class="t8-c">#    useful when later rows represent updated/corrected records</span>
df_keep_last = df.<span class="t8-f">drop_duplicates</span>(keep=<span class="t8-s">'last'</span>)

<span class="t8-c"># ── Strategy 3: drop ALL occurrences of any duplicated row ──</span>
<span class="t8-c">#    use when any repeated row is invalid data</span>
df_drop_all = df.<span class="t8-f">drop_duplicates</span>(keep=<span class="t8-b">False</span>)

<span class="t8-c"># ── Subset: deduplicate only on specific columns ──</span>
df_subset = df.<span class="t8-f">drop_duplicates</span>(subset=[<span class="t8-s">'customer_id'</span>, <span class="t8-s">'order_date'</span>], keep=<span class="t8-s">'first'</span>)

<span class="t8-c"># ── Reset the index after removal (clean 0-based index) ──</span>
df_cleaned = df_keep_first.<span class="t8-f">reset_index</span>(drop=<span class="t8-b">True</span>, inplace=<span class="t8-b">False</span>)

<span class="t8-c"># Confirm rows removed</span>
<span class="t8-f">print</span>(<span class="t8-f">f</span><span class="t8-s">"Before: {len(df):,}  |  After: {len(df_cleaned):,}  |  Removed: {len(df) - len(df_cleaned):,}"</span>)</code></pre></div>
    </div>
    <div class="vg8-callout teal">
      <strong>inplace vs assignment:</strong> <code class="vg8-ic">drop_duplicates(inplace=True)</code> modifies the DataFrame in place and returns <code class="vg8-ic">None</code>. Prefer the assignment pattern (<code class="vg8-ic">df_cleaned = df.drop_duplicates()</code>) — it preserves the original for comparison and makes your code easier to debug.
    </div>
  </div>

  <hr class="vg8-divider">

  <!-- STEP 4 — EXPORT -->
  <div class="vg8-step vg8-reveal">
    <p class="vg8-step-label">Step 4</p>
    <h2>Export <em>the clean data</em></h2>
    <p>Write the deduplicated DataFrame back to a CSV. Setting <code class="vg8-ic">index=False</code> prevents pandas from writing the row index as an extra column — your downstream consumers will thank you.</p>
    <div class="vg8-code-wrap">
      <div class="vg8-code-header"><span class="vg8-code-filename">export.py</span><span class="vg8-code-lang">Python</span></div>
      <div class="vg8-code-body"><pre><code><span class="t8-c"># Export to CSV — index=False keeps the file clean</span>
df_cleaned.<span class="t8-f">to_csv</span>(<span class="t8-s">'cleaned_data.csv'</span>, index=<span class="t8-b">False</span>)

<span class="t8-f">print</span>(<span class="t8-s">"Cleaned data exported to cleaned_data.csv"</span>)

<span class="t8-c"># Optional: also export to Parquet for better performance at scale</span>
df_cleaned.<span class="t8-f">to_parquet</span>(<span class="t8-s">'cleaned_data.parquet'</span>, index=<span class="t8-b">False</span>)</code></pre></div>
    </div>
  </div>

</div><!-- /vg8-body -->

<!-- FULL SCRIPT -->
<div class="vg8-full-section">
  <p class="vg8-full-eyebrow">Complete Reference</p>
  <h2>Full deduplication <em>script</em></h2>
  <p>Everything in one place — load, detect, remove (keep first), reset index, and export.</p>
  <div class="vg8-code-wrap vg8-reveal">
    <div class="vg8-code-header"><span class="vg8-code-filename">deduplicate.py — full script</span><span class="vg8-code-lang">Python</span></div>
    <div class="vg8-code-body"><pre><code><span class="t8-k">import</span> pandas <span class="t8-k">as</span> pd

<span class="t8-c"># ── 1. Load ─────────────────────────────────────────────</span>
df = pd.<span class="t8-f">read_csv</span>(<span class="t8-s">'your_data_file.csv'</span>)
<span class="t8-f">print</span>(<span class="t8-f">f</span><span class="t8-s">"Loaded {len(df):,} rows"</span>)

<span class="t8-c"># ── 2. Detect ────────────────────────────────────────────</span>
duplicates = df[df.<span class="t8-f">duplicated</span>()]
<span class="t8-f">print</span>(<span class="t8-f">f</span><span class="t8-s">"Duplicate rows found: {len(duplicates):,}"</span>)
<span class="t8-f">print</span>(duplicates)

<span class="t8-c"># ── 3a. Keep last occurrence of each duplicate row ───────</span>
df_cleaned = df.<span class="t8-f">drop_duplicates</span>(keep=<span class="t8-s">'last'</span>)

<span class="t8-c"># ── 3b. Keep first occurrence (swap in if preferred) ─────</span>
<span class="t8-c"># df_cleaned = df.drop_duplicates(keep='first')</span>

<span class="t8-c"># ── 3c. Reset the index to a clean 0-based sequence ──────</span>
df_cleaned.<span class="t8-f">reset_index</span>(drop=<span class="t8-b">True</span>, inplace=<span class="t8-b">True</span>)

<span class="t8-f">print</span>(<span class="t8-f">f</span><span class="t8-s">"Rows after cleaning: {len(df_cleaned):,}"</span>)

<span class="t8-c"># ── 4. Export ─────────────────────────────────────────────</span>
df_cleaned.<span class="t8-f">to_csv</span>(<span class="t8-s">'cleaned_data.csv'</span>, index=<span class="t8-b">False</span>)
<span class="t8-f">print</span>(<span class="t8-s">"Exported to cleaned_data.csv"</span>)</code></pre></div>
  </div>
</div>

<!-- INTERVIEW CHEAT SHEET -->
<div class="vg8-interview-section">
  <p class="vg8-interview-eyebrow">Interview Prep</p>
  <h2>Cheat sheet — <em>quick definitions to remember</em></h2>
  <div class="vg8-qa-list">

    <div class="vg8-qa-item vg8-reveal">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Define</span><br>What does <code>df.duplicated()</code> return?</div>
      <div class="vg8-qa-a">A <strong>boolean Series</strong> the same length as the DataFrame — <code>True</code> for every row that is a duplicate of a previously seen row, <code>False</code> otherwise. The first occurrence is marked <code>False</code> by default.
        <div class="vg8-pills"><span class="vg8-pill t">Boolean Series</span><span class="vg8-pill">True = duplicate</span><span class="vg8-pill a">First = False by default</span></div>
      </div>
    </div>

    <div class="vg8-qa-item vg8-reveal vg8-d1">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Compare</span><br>keep=&#8217;first&#8217; vs keep=&#8217;last&#8217; vs keep=False</div>
      <div class="vg8-qa-a"><strong>first</strong> — keeps the first occurrence, drops all subsequent duplicates. <strong>last</strong> — keeps the final occurrence, useful for updated records. <strong>False</strong> — drops every occurrence of any duplicated row, leaving only rows that were unique to begin with.
        <div class="vg8-pills"><span class="vg8-pill t">first = keep original</span><span class="vg8-pill a">last = keep latest</span><span class="vg8-pill">False = drop all copies</span></div>
      </div>
    </div>

    <div class="vg8-qa-item vg8-reveal">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Explain</span><br>What does the <code>subset</code> parameter do?</div>
      <div class="vg8-qa-a">By default, <code>duplicated()</code> and <code>drop_duplicates()</code> compare <strong>all columns</strong>. The <code>subset</code> parameter restricts the comparison to specific columns — for example <code>subset=['customer_id']</code> finds rows with the same customer ID even if other columns differ.
        <div class="vg8-pills"><span class="vg8-pill t">Default = all columns</span><span class="vg8-pill">subset = logical dedup</span></div>
      </div>
    </div>

    <div class="vg8-qa-item vg8-reveal vg8-d1">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Gotcha</span><br>Why call <code>reset_index(drop=True)</code> after deduplication?</div>
      <div class="vg8-qa-a">After dropping rows, the DataFrame retains the <strong>original row indices</strong> — you&#8217;d have gaps like 0, 1, 4, 7 instead of 0, 1, 2, 3. <code>reset_index(drop=True)</code> renumbers from 0 continuously. <code>drop=True</code> prevents the old index from being added as a column.
        <div class="vg8-pills"><span class="vg8-pill a">Index gaps after drop</span><span class="vg8-pill t">reset_index fixes gaps</span><span class="vg8-pill">drop=True prevents extra col</span></div>
      </div>
    </div>

    <div class="vg8-qa-item vg8-reveal">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Gotcha</span><br>inplace=True vs reassignment — which is preferred?</div>
      <div class="vg8-qa-a">Prefer <strong>reassignment</strong> (<code>df_cleaned = df.drop_duplicates()</code>) — it preserves the original DataFrame for comparison and makes pipelines easier to debug. <code>inplace=True</code> modifies the object and returns <code>None</code>, which can cause confusion when chaining operations. Many pandas best-practice guides now recommend avoiding inplace.
        <div class="vg8-pills"><span class="vg8-pill t">Reassignment = safer</span><span class="vg8-pill a">inplace returns None</span></div>
      </div>
    </div>

    <div class="vg8-qa-item vg8-reveal vg8-d1">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Best Practice</span><br>How do you handle duplicates in a production data pipeline?</div>
      <div class="vg8-qa-a"><strong>Three layers:</strong> (1) <strong>Detect and log</strong> before removing — store duplicate counts as data quality metrics. (2) <strong>Deduplicate at ingestion</strong>, not at query time — clean once, use many times. (3) Add a <strong>unique constraint</strong> in your database or Delta Lake table to prevent duplicates from re-entering at source.
        <div class="vg8-pills"><span class="vg8-pill t">Log before removing</span><span class="vg8-pill t">Clean at ingestion</span><span class="vg8-pill a">DB unique constraints</span></div>
      </div>
    </div>

    <div class="vg8-qa-item vg8-reveal">
      <div class="vg8-qa-q"><span class="vg8-q-badge">Use Case</span><br>When should you NOT remove duplicates?</div>
      <div class="vg8-qa-a">When the repeated rows represent <strong>legitimate repeated events</strong> — a customer placing the same order twice on different days, a sensor reading the same value consecutively, or audit log entries. Always validate with domain knowledge before dropping. Use <code>subset</code> to deduplicate on business keys, not entire rows.
        <div class="vg8-pills"><span class="vg8-pill a">Repeated events = valid</span><span class="vg8-pill t">Use subset= for business keys</span></div>
      </div>
    </div>

  </div>
</div>

<!-- FOOTER -->
<div class="vg8-footer">
  <p><strong>GenAI Mastery Series</strong> — vijay-gokarn.com · Vijay Gokarn</p>
  <div class="vg8-footer-links">
    <a href="https://github.com/vijaygokarn130" class="vg8-btn ghost">GitHub ↗</a>
    <a href="https://vijay-gokarn.com" class="vg8-btn primary">Back to Blog ↗</a>
  </div>
</div>

</div><!-- /vg8 -->

<script>
(function(){
  var obs = new IntersectionObserver(function(e){
    e.forEach(function(x){ if(x.isIntersecting) x.target.classList.add('vg8-vis'); });
  }, {threshold: 0.08});
  document.querySelectorAll('.vg8-reveal').forEach(function(el){ obs.observe(el); });
})();
</script>
<p>The post <a href="https://vijay-gokarn.com/pandas-remove-duplicates/">Pandas Remove Duplicates</a> appeared first on <a href="https://vijay-gokarn.com">Vijay Gokarn</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">119</post-id>	</item>
	</channel>
</rss>
