<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[generative ai]]></title><description><![CDATA[generative ai]]></description><link>https://intro-generative-ai.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 24 Sep 2026 13:34:34 GMT</lastBuildDate><atom:link href="https://intro-generative-ai.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How Large Language Models Actually Work: Six Foundations for AI Engineering]]></title><description><![CDATA[A language model can write, summarize, classify, translate, answer questions, generate code, and call tools. The output feels intelligent and conversational, which is exactly the problem: it invites y]]></description><link>https://intro-generative-ai.hashnode.dev/how-large-language-models-actually-work-six-foundations-for-ai-engineering</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/how-large-language-models-actually-work-six-foundations-for-ai-engineering</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Fri, 18 Sep 2026 06:06:38 GMT</pubDate><content:encoded><![CDATA[<p>A language model can write, summarize, classify, translate, answer questions, generate code, and call tools. The output feels intelligent and conversational, which is exactly the problem: it invites you to reason about the system as if it were a knowledgeable colleague. Building reliable software on top of it requires a more mechanical picture of what is happening underneath.</p>
<p>Six ideas explain most of what you will observe in production:</p>
<ol>
<li><p><strong>Tokens</strong> determine what the model actually reads and writes.</p>
</li>
<li><p><strong>Context and attention</strong> determine how much it can use at once, and what that costs.</p>
</li>
<li><p><strong>Sampling</strong> determines how each next token gets picked.</p>
</li>
<li><p><strong>Statelessness</strong> explains why your application, not the model, owns memory.</p>
</li>
<li><p><strong>Three training stages</strong> explain how a text predictor became an assistant.</p>
</li>
<li><p><strong>Hallucination</strong> follows from the gap between sounding plausible and being true.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/b9e18c64-6764-48ee-9914-3be5928d2885.png" alt="" style="display:block;margin:0 auto" />

<p>The shape of a single request:</p>
<pre><code class="language-plaintext">Application builds the prompt
        ↓
Tokenizer turns text into token IDs
        ↓
Model processes the tokens with attention
        ↓
Model outputs next-token probabilities
        ↓
Sampling picks one token  ──┐
        ↓                   │ repeat until done
Application validates  ←────┘
and stores the answer
</code></pre>
<p>Notice how little of that the model does. It handles the middle. Everything else retrieval, tool calls, storage, validation, and deciding what the user finally sees is your architecture. That division is the single most useful thing to internalize.</p>
<hr />
<h2>1. Tokens and tokenization</h2>
<h3>The model never sees your text</h3>
<p>Before anything reaches the neural network, a <strong>tokenizer</strong> splits the text into units called <strong>tokens</strong> and maps each one to a number, a <strong>token ID</strong>. Those numbers are the model's input. The original characters are gone.</p>
<p>A token is not a word. It can be a whole word, a fragment of a word, a space plus the following word, a piece of punctuation, part of a number, part of an emoji, or a raw byte sequence used as a last resort.</p>
<pre><code class="language-plaintext">Text:   The engineer redesigned the tokenizer.
Tokens: ["The", " engineer", " redesigned", " the", " token", "izer", "."]
</code></pre>
<p>Three things to notice there. "engineer" happened to be a single token. "tokenizer" needed two. And the spaces are attached to the <em>front</em> of the following token, not sitting on their own.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/9bd21bf1-fa6f-4149-b7e1-b68d7597bac1.png" alt="" style="display:block;margin:0 auto" />

<h3>How the tokenizer picks the pieces</h3>
<p>A tokenizer has a fixed vocabulary of a few tens of thousands of reusable text fragments. When it encounters text, it tries to cover that text using the largest available pieces. Sequences that appeared constantly in its training data earned their own single entry; rare sequences have to be assembled from smaller parts.</p>
<pre><code class="language-plaintext">unhappiness  →  ["un", "happi", "ness"]
</code></pre>
<p>The common families are <strong>Byte Pair Encoding (BPE)</strong>, <strong>WordPiece</strong>, and <strong>Unigram</strong>, usually with byte-level fallback so no input can ever be unrepresentable. You will almost never implement one. What matters is the consequence: <strong>common words are cheap, rare words are expensive</strong>, and a technical term like <code>electroencephalography</code> might cost four tokens where <code>the</code> costs one.</p>
<p>For a given tokenizer and a given string, the output is deterministic. Across model families it is not. The same paragraph can have meaningfully different token counts on two different providers.</p>
<h3>Tokens are the unit of billing</h3>
<p>Almost every API charges per token, not per word or character, split into two buckets:</p>
<ul>
<li><p><strong>Input tokens</strong> system instructions, conversation history, retrieved documents, tool results, and the current message.</p>
</li>
<li><p><strong>Output tokens</strong> everything generated in response.</p>
</li>
</ul>
<pre><code class="language-plaintext">total cost = input tokens  × input rate
           + output tokens × output rate
</code></pre>
<p>Output usually costs more per token, because it is produced one token at a time and cannot be batched the way input can. Many providers add further categories: cached input, uncached input, reasoning tokens, audio, images.</p>
<p>A single realistic request:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/90773fbf-8e97-4c3d-9202-96fc93aad61f.png" alt="" style="display:block;margin:0 auto" />

<p>The interesting number is 3,000. The user typed a hundred-token question, and 97% of the input charge came from re-sending things that were already sent before. This is the central economic fact of chat applications, and it gets worse linearly with conversation length.</p>
<h3>Tokens are also the unit of latency</h3>
<p>Input tokens are processed in one parallel pass, a stage called <strong>prefill</strong>. Output tokens are then produced strictly one after another, a stage called <strong>decoding</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/3c966f25-7d0d-4164-999f-9570875e041a.png" alt="" style="display:block;margin:0 auto" />

<p>That asymmetry is why a 4,000-token answer can take twenty times longer than a 200-token answer while a 4,000-token prompt does not take twenty times longer than a 200-token prompt. If your product feels slow, the output length is usually the first thing to look at, and capping <code>max_tokens</code> is usually the cheapest fix available.</p>
<h3>Why models miscount letters</h3>
<p>Ask a person how many <code>r</code>s are in "strawberry" and they scan the characters. The model does not start with characters. It starts with something like:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/5efe5d85-8aac-4bc3-9b3b-3f3627086257.png" alt="" style="display:block;margin:0 auto" />

<p>To answer, it has to reconstruct a character-level view from token-level pieces. That is an indirect operation, and indirect operations fail. Models can often get there by spelling the word out deliberately or by writing code, but their default representation simply is not an array of letters.</p>
<p>The engineering answer is not a better prompt:</p>
<pre><code class="language-python">"strawberry".count("r")   # 3
</code></pre>
<p><strong>Use the model for language. Use deterministic code for exact counting, arithmetic, parsing, and validation.</strong> This principle will reappear in section 6, because it is also the main defense against hallucination.</p>
<h3>Tokens are not equally fair across languages</h3>
<p>Token efficiency depends on how much text in a language existed in the tokenizer's training data, which sequences therefore became single vocabulary entries, the writing system, whether words are space-separated, the language's morphology, and the vocabulary size.</p>
<p>So a tokenizer may compress an English sentence into four tokens and split an equally simple sentence in another language into ten. This is not a statement about the languages. It is a statement about the tokenizer's coverage. But the practical consequences are real and land entirely on your users:</p>
<ul>
<li><p>higher cost for the same information</p>
</li>
<li><p>higher latency and more generation steps</p>
</li>
<li><p>less usable content fitting inside the same context window</p>
</li>
</ul>
<p>Modern multilingual tokenizers narrow the gap. They do not close it. If your product ships in several languages, measure each one rather than extrapolating from English.</p>
<h3>A few more things that quietly cost tokens</h3>
<table>
<thead>
<tr>
<th>Case</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td><code>"hello"</code> vs <code>" hello"</code> vs <code>"hello "</code></td>
<td>whitespace changes the token boundaries</td>
</tr>
<tr>
<td><code>model</code> vs <code>Model</code> vs <code>MODEL</code></td>
<td>capitalization can change the split entirely</td>
</tr>
<tr>
<td><code>getUserAccountConfiguration</code></td>
<td>long identifiers fragment into many pieces</td>
</tr>
<tr>
<td><code>a8Kx9QpL2zV7</code></td>
<td>random strings have no reusable patterns</td>
</tr>
<tr>
<td>Emoji with skin tone or gender modifiers</td>
<td>one visible glyph, several Unicode code points</td>
</tr>
<tr>
<td>Indented code, long numbers, URLs, base64</td>
<td>punctuation and structure everywhere</td>
</tr>
</tbody></table>
<p>The rule of thumb that one token is about four English characters, or about three-quarters of a word, is fine for capacity planning and wrong often enough that you should never bill, truncate, or gate on it. When the number matters, run the real tokenizer for the exact model.</p>
<hr />
<h2>2. Context, attention, and the two kinds of caching</h2>
<h3>The context window is a size limit, not a place</h3>
<p>The <strong>context window</strong> is the maximum amount of tokenized information the model can work with in a single request. What you actually send is the <strong>context</strong>; the window is how much the container holds.</p>
<p>It helps to think of a suitcase. What you pack is the contents; the suitcase's capacity is the window. In casual speech people say "my context window is full" the way they say "my suitcase is full," and that is fine, as long as you keep two facts straight:</p>
<p><strong>The output shares the budget.</strong> If the window is 200k tokens and you send 195k, you have about 5k left for the answer. Some APIs also impose a separate output cap on top of that.</p>
<p><strong>Everything competes for the same space.</strong> Instructions, history, retrieved documents, tool results, images, and the reply are all drawing on one pool. A giant pasted document does not just cost money, it crowds out the answer.</p>
<p>When a request will not fit, your options are to shorten history, summarize older turns, retrieve fewer passages, reduce the planned output, or move to a model with a larger window. A larger window buys capacity. It does not buy comprehension, which is a distinction section on lost-in-the-middle will make painfully concrete.</p>
<h3>Attention: how tokens consult each other</h3>
<p><strong>Attention</strong> is the mechanism that lets one position in the sequence look at other positions and decide which of them matter. Consider:</p>
<blockquote>
<p>The animal did not cross the road because it was tired.</p>
</blockquote>
<p>Resolving <code>it</code> requires connecting it back to <code>animal</code> rather than <code>road</code>. Attention is what makes that connection available.</p>
<p>Inside an attention layer, every token produces three vectors:</p>
<ul>
<li><p><strong>Query (Q)</strong> what am I looking for?</p>
</li>
<li><p><strong>Key (K)</strong> what kind of information do I contain?</p>
</li>
<li><p><strong>Value (V)</strong> what can I actually contribute?</p>
</li>
</ul>
<p>Each token's Query is compared against every Key. The resulting weights decide how much of each Value flows into the next representation. Real models do this across many parallel <strong>attention heads</strong> and repeat it through dozens of layers, which is how the simple comparison above turns into something that tracks syntax, reference, and meaning.</p>
<h3>Why attention gets expensive: the handshake problem</h3>
<p>In standard full self-attention, every token can interact with every other token. Picture a room where everyone must shake hands with everyone else, including themselves. Each token is a person; each handshake is one relationship the model evaluates.</p>
<pre><code class="language-plaintext">    4 people  →      4 ×     4 =         16 handshakes
1,000 people  →  1,000 × 1,000 =  1,000,000 handshakes
2,000 people  →  2,000 × 2,000 =  4,000,000 handshakes
</code></pre>
<p>Double the room and the handshakes quadruple, because each new arrival must greet everyone already there. That is <strong>quadratic scaling</strong>, written <code>n²</code>. It is the reason long contexts are structurally hard rather than just "bigger."</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/57d3e1eb-f747-48e8-ac02-04cda7629c3c.png" alt="" style="display:block;margin:0 auto" />

<p>Optimizations soften this. <strong>FlashAttention</strong> performs the same mathematics with far less memory traffic. <strong>Sparse attention</strong> and <strong>sliding-window attention</strong> let each token consult only a subset of the others instead of all of them. Architectural changes sidestep full attention entirely in some models. So real-world cost is not cleanly proportional to <code>n²</code>. The direction of the problem is unchanged: longer contexts need more compute and more memory.</p>
<h3>A clarification worth making: you are not billed for handshakes</h3>
<p>It is easy to slide from "long prompts do more work" into "you pay for that work." You do not. <strong>Your invoice counts input and output tokens. Attention never appears on it.</strong></p>
<p>Attention still reaches you, in three indirect ways:</p>
<ol>
<li><p><strong>It sets the price per token.</strong> The provider pays for the hardware doing all that internal work and prices tokens to cover it on average. A restaurant does not bill you for the kitchen's gas; the menu price already includes it.</p>
</li>
<li><p><strong>Some providers charge a premium on very long prompts.</strong> Because long inputs are disproportionately expensive to serve, a higher per-token rate above a length threshold is a real pricing pattern. This is where the quadratic problem shows up directly on the bill.</p>
</li>
<li><p><strong>It costs you time and ceiling.</strong> Even at a flat price, a very long prompt delays the first token. And memory growth is a major reason the context window has a maximum at all.</p>
</li>
</ol>
<p>So: you pay for tokens, and attention is a large part of <em>why</em> tokens cost what they do.</p>
<p>Beyond the invoice, large prompts raise time-to-first-token, GPU memory use, attention computation, and most insidiously the amount of irrelevant material competing for the model's attention.</p>
<h3>Lost in the middle</h3>
<p>Models tend to use information near the beginning and the end of a long context more reliably than information buried in the middle.</p>
<pre><code class="language-plaintext"> Beginning            Middle             End
 ██████████        ███░░░░░░░       ██████████
usually used      easy to miss      usually used
</code></pre>
<p>This means a fact can be comfortably inside the official token limit and still fail to affect the answer. Position effects, weak relevance signals, several similar-looking passages competing, and patterns from training all contribute.</p>
<p>What actually helps:</p>
<ul>
<li><p>put stable, critical instructions near the top</p>
</li>
<li><p>keep the current question clearly at the bottom</p>
</li>
<li><p>retrieve fewer, more relevant passages instead of more</p>
</li>
<li><p>use headings and a consistent document structure</p>
</li>
<li><p>split very large tasks into stages</p>
</li>
<li><p>test retrieval with the target fact planted at the start, the middle, and the end</p>
</li>
</ul>
<p>That last one is not optional. It is the only way you will find out that your context is technically correct and functionally invisible.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/135a9864-a315-46ce-990f-253df88d08a6.png" alt="" style="display:block;margin:0 auto" />

<h3>KV caching: skipping work inside one answer</h3>
<p>The model generates one token at a time, and before each new token it must look back at everything so far. A naive implementation would rebuild the internal representation of every earlier token at every single step rebuilding 499 tokens to produce token 500, then rebuilding 500 to produce token 501.</p>
<p>Here is the part that makes the fix obvious, and that most explanations skip. <strong>The model was never able to "look back at tokens" directly.</strong> A stored token is an ID number, say word #8342. That number tells attention nothing on its own. To be usable, it has to be pushed through the model's layers and matrix multiplications to produce its Key and Value vectors, and <em>that conversion is the expensive part</em>. Looking back was always looking at K and V. The wasteful version just rebuilt them from scratch every time.</p>
<p>And the crucial property: <strong>a past token's K and V never change.</strong> Token 7 contains the same thing whether you are generating token 8 or token 800. Only the new token brings a fresh Query.</p>
<p>So the model computes each token's K and V once and stores them in the <strong>KV cache</strong>:</p>
<pre><code class="language-plaintext">Without cache, to generate token 500:
    rebuild K,V for 499 tokens  →  compare  →  499 expensive conversions

With cache, to generate token 500:
    499 sets of K,V already sitting there
    convert only the new token   →  compare  →  1 expensive conversion
</code></pre>
<p>It is margin notes. The first time you read a page you write your notes; afterwards you glance at the notes instead of re-reading the book. What you skip is the <em>making</em>, not the <em>looking</em>.</p>
<p>Which is exactly why the cache does not make long sequences free:</p>
<ul>
<li><p>The cache consumes memory roughly in proportion to sequence length.</p>
</li>
<li><p>Every new token still has to attend over all cached positions, so each token gets slower as the sequence grows.</p>
</li>
<li><p>Long generations remain expensive.</p>
</li>
<li><p>The cache normally lives only for the active request, unless the serving system supports reuse.</p>
</li>
</ul>
<p><strong>KV caching removes repeated work, not the work of looking back.</strong> And it is a serving optimization it is not memory, and it does not mean the model learned anything.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/7a693ce3-c600-4d50-afce-84880f9ae914.png" alt="" style="display:block;margin:0 auto" />

<h3>Prefix caching: skipping work across requests</h3>
<p>Now take the same idea and stretch it across separate requests.</p>
<p>Imagine a support assistant. Every request looks like this:</p>
<pre><code class="language-plaintext">[same system instructions] + [same product docs] + [different question]
</code></pre>
<p>The first two blocks never change, and their K and V are identical every single time. So a provider can compute that shared beginning once, store it, and reuse it leaving only your new question to be processed fresh. Depending on the vendor this is called <strong>prompt caching</strong>, <strong>prefix caching</strong>, or cross-request KV-cache reuse. Cached input tokens are typically billed at a lower rate.</p>
<p><strong>The ordering rule matters more than people expect.</strong> Matching runs from the very first token forward and stops at the first difference. It behaves like a contact list: typing a few letters jumps deep into the list, but only because it matches from the left.</p>
<p>This shares thousands of tokens:</p>
<pre><code class="language-plaintext">Request 1: [Instructions][Docs][Question A]
Request 2: [Instructions][Docs][Question B]
</code></pre>
<p>This shares almost nothing:</p>
<pre><code class="language-plaintext">Request 1: [Question A][Instructions][Docs]
Request 2: [Question B][Instructions][Docs]
             ↑ differs at token 1, match ends immediately
</code></pre>
<p>Identical content. Identical token count. One layout saves most of the cost and the other throws it away.</p>
<p>So put stable content first and dynamic content last:</p>
<pre><code class="language-plaintext">1. System instructions
2. Tool definitions
3. Stable reference material
4. Conversation history
5. Current user message
</code></pre>
<p>And watch for the things that silently break the match, because anything that changes inside the stable region invalidates everything after it: a <strong>timestamp</strong> at the top of the system prompt (the classic mistake), random request IDs, JSON keys serialized in a different order, changing metadata, and inconsistent whitespace where it shifts token boundaries. Cache lifetime, minimum prefix length, and billing details are all provider-specific.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/5b9ef26a-393c-4e2e-a9c3-1e5f0a0ea6d2.png" alt="" style="display:block;margin:0 auto" />

<h3>The two caches, side by side</h3>
<table>
<thead>
<tr>
<th></th>
<th>Lives for</th>
<th>Reuses</th>
</tr>
</thead>
<tbody><tr>
<td><strong>KV cache</strong></td>
<td>one response being generated</td>
<td>earlier tokens of that same response</td>
</tr>
<tr>
<td><strong>Prefix caching</strong></td>
<td>across separate requests</td>
<td>the matching beginning of the prompt</td>
</tr>
</tbody></table>
<p>Both are efficiency. Neither is memory, and neither puts a fact inside the model.</p>
<hr />
<h2>3. Sampling: temperature and top-p</h2>
<h3>From logits to one token</h3>
<p>For each output position the model produces a raw score a <strong>logit</strong> for every token in the vocabulary. A <strong>softmax</strong> turns those scores into a probability distribution. Then a decoding method picks one.</p>
<p>For the fragment <code>The sky is</code>, an illustrative distribution:</p>
<pre><code class="language-plaintext">blue      65%
clear     15%
dark      10%
bright     6%
green      3%
falling    1%
</code></pre>
<p>The chosen token is appended to the sequence, and the whole distribution is recomputed for the next position. This is why one different choice early can send the rest of the answer somewhere completely different, and why the same prompt can produce two answers that diverge after the fourth word.</p>
<h3>Greedy decoding</h3>
<p><strong>Greedy decoding</strong> always takes the top-scoring token. Here it picks <code>blue</code>.</p>
<p>It is maximally consistent and worth being clear-eyed about: the highest-probability continuation is the one that best fits the model's learned patterns. That is not the same thing as the true one.</p>
<h3>Temperature</h3>
<p><strong>Temperature</strong> reshapes the distribution before sampling:</p>
<pre><code class="language-plaintext">probability = softmax(logit / temperature)
</code></pre>
<p>You never compute this by hand. The behavior is the point.</p>
<p><strong>Low temperature sharpens.</strong> The gaps get exaggerated:</p>
<pre><code class="language-plaintext">before          after (low temp)
blue    65%     blue    91%
clear   15%     clear    5%
dark    10%     dark     3%
other   10%     other    1%
</code></pre>
<p><strong>Temperature near 1</strong> leaves the distribution roughly as the model produced it. This is the reference point.</p>
<p><strong>High temperature flattens.</strong> The gaps shrink:</p>
<pre><code class="language-plaintext">before          after (high temp)
blue    65%     blue    37%
clear   15%     clear   23%
dark    10%     dark    20%
other   10%     other   20%
</code></pre>
<p>Think of weighted dice. Low temperature loads them heavily onto one face; high temperature evens the faces out. Crucially, <strong>temperature adds no knowledge and no reasoning</strong>. It only changes how conservatively the model chooses among options it already had.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/fcdedda4-c5c9-420b-a096-cee1090acd7b.png" alt="" style="display:block;margin:0 auto" />

<h3>What temperature 0 actually is</h3>
<p>You cannot divide by zero, so <code>temperature: 0</code> is a special mode in most APIs meaning "take the highest-scoring token every time." It is effectively greedy decoding.</p>
<p>Pin it to 0 when repeatability beats variety:</p>
<ul>
<li><p>classification</p>
</li>
<li><p>field extraction from invoices and documents</p>
</li>
<li><p>format conversion and schema-constrained JSON</p>
</li>
<li><p>generating database filters</p>
</li>
<li><p>known code transformations</p>
</li>
<li><p>reproducible evaluations and test cases</p>
</li>
</ul>
<h3>And what temperature 0 is not</h3>
<p>This distinction is worth over-emphasizing, because it is the most common misunderstanding in the entire subject:</p>
<pre><code class="language-plaintext">Deterministic ≠ correct
Consistent    ≠ factual
</code></pre>
<p>If the model confidently prefers a wrong answer, temperature 0 will hand you that wrong answer reliably, every single time, with a straight face. It does not verify facts, fill knowledge gaps, prevent hallucination, guarantee valid JSON, or make arithmetic trustworthy. For those you need schema validation, retrieval, and real tools.</p>
<p>It is not even perfectly deterministic. Two candidates can be nearly tied, and tiny floating-point differences or the order in which parallel GPU operations complete can flip the winner. Add backend routing, hardware differences, model version updates, changed hidden system instructions, and non-deterministic tools or external data. A <strong>seed</strong>, where offered, improves reproducibility but a seed will not survive a model or infrastructure change.</p>
<h3>Top-p (nucleus sampling)</h3>
<p><strong>Top-p</strong> restricts sampling to the smallest set of top tokens whose probabilities add up to at least <code>p</code>.</p>
<pre><code class="language-plaintext">blue       45%   cumulative  45%   ← in
clear      25%   cumulative  70%   ← in
dark       15%   cumulative  85%   ← in
bright      8%   cumulative  93%   ← in (crosses 90% here)
green       4%   cumulative  97%   ← cut
falling     3%   cumulative 100%   ← cut
</code></pre>
<p>With <code>top_p = 0.90</code> the nucleus is <code>blue, clear, dark, bright</code>. The rest are discarded and the survivors are renormalized.</p>
<p>The useful property is that top-p is <strong>adaptive</strong>. When the model is confident, the nucleus might hold two tokens. When it is genuinely uncertain, reaching the same threshold might take thirty. Temperature applies the same adjustment regardless of how confident the model was; top-p responds to it.</p>
<h3>Using them together</h3>
<p>The usual conceptual order:</p>
<pre><code class="language-plaintext">logits → temperature → probabilities → top-p cutoff → sample
</code></pre>
<p>Implementations vary. Practically: <strong>tune one randomness control and leave the other near default.</strong> Moving both aggressively makes behavior almost impossible to diagnose when something goes wrong at 2am.</p>
<p>Starting points, not laws:</p>
<table>
<thead>
<tr>
<th>Task</th>
<th>Randomness</th>
</tr>
</thead>
<tbody><tr>
<td>Extraction, classification, structured output</td>
<td>temperature 0 or very low</td>
</tr>
<tr>
<td>Grounded factual answers</td>
<td>low</td>
</tr>
<tr>
<td>General conversation</td>
<td>moderate</td>
</tr>
<tr>
<td>Brainstorming, creative writing</td>
<td>higher</td>
</tr>
</tbody></table>
<p>Note that some reasoning-oriented models manage sampling internally or expose limited controls, so check before assuming these knobs exist.</p>
<h3>Sampling cannot make things true</h3>
<p>Lower randomness removes unnecessary variation. It cannot check a fact. If the model's top answer is wrong, greedy decoding returns that wrong answer with perfect consistency.</p>
<p>For hard reasoning problems, generating several candidates and comparing them can beat one greedy pass the idea behind <strong>self-consistency</strong>. But it multiplies token cost, and it still needs an independent way to decide which candidate is right.</p>
<hr />
<h2>4. Statelessness and application-managed memory</h2>
<h3>The model does not remember anything</h3>
<p>An inference request is <strong>stateless</strong>. When it ends, the conversation does not become part of the model. If a later request needs earlier information, your application has to supply it again.</p>
<pre><code class="language-plaintext">User → App:   "My preferred language is Python"
App  → Model: "My preferred language is Python"
Model → App:  "Understood"
App:          saves the preference to a database
              ── later ──
User → App:   "What language do I prefer?"
App:          loads the saved preference
App  → Model: "Preferred language: Python
               What language do I prefer?"
Model → App:  "Python"
</code></pre>
<p>The application remembered. The model was simply told, again.</p>
<h3>The desk</h3>
<p>The clearest mental image is a <strong>desk with limited space</strong>, wiped clean after every request.</p>
<p>Chat history is one pile of paper on that desk. Beside it sit the system instructions, retrieved documents, tool outputs, and the current question. All of it has to fit at once. Then the desk is cleared.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/a88af819-abb6-4ef0-a5aa-2f15478e9310.png" alt="" style="display:block;margin:0 auto" />

<p>This is why "is the context window just the chat history?" has a subtle answer. In a plain chat app, yes the desk usually happens to contain the entire conversation, because that is what the app chose to put there. But that is a <em>choice</em>, not a definition:</p>
<ul>
<li><p><strong>The window has a fixed size; the history does not.</strong> History grows until it collides with the ceiling, and then something must be dropped or summarized. If they were the same thing, that collision could not happen.</p>
</li>
<li><p><strong>The window can be full with no history at all.</strong> A one-shot API call with a system prompt and a document has a full context and zero conversation. A RAG app might send instructions, three retrieved chunks, and your question while skipping most older messages entirely.</p>
</li>
</ul>
<p>Once a conversation gets long, or the app starts <em>selecting</em> what to include, the two come apart completely. That selection logic is one of the most important things you will build.</p>
<h3>Four different things called "memory"</h3>
<p>Confusing these causes architecture mistakes that are expensive to undo.</p>
<p><strong>1. Model weights.</strong> Billions of numeric parameters learned during training, holding distributed language and knowledge patterns sometimes called <strong>parametric memory</strong>. Not a searchable database of training documents, and not updated by ordinary conversation. Telling the model your name does not rewrite its weights.</p>
<p><strong>2. Context window.</strong> Temporary working space for one inference, available only because it was supplied or reconstructed for that request. Gone afterwards.</p>
<p><strong>3. Application memory.</strong> A real store that you own: relational database, document store, key-value store, vector database, user profile, conversation table. This is the only one that genuinely persists, and its job is to fetch the right things and place them on the desk.</p>
<p><strong>4. KV cache.</strong> Stored attention calculations for fast generation. Computational state, not semantic memory. It does not mean a fact was learned, stored permanently, or will be recalled in an unrelated future request.</p>
<p>When a product claims it "remembers" you across sessions, that is almost always number 3 quietly loading things into number 2.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/ca1a4835-aec4-43fb-ad51-643a2bc92859.png" alt="" style="display:block;margin:0 auto" />

<h3>Why chat apps feel stateful</h3>
<p>Because they do the work:</p>
<pre><code class="language-python">history = database.load(conversation_id)
history.append({"role": "user", "content": new_message})

response = model.generate(messages=history)

history.append({"role": "assistant", "content": response})
database.save(conversation_id, history)
</code></pre>
<p>Some services expose conversation IDs, threads, or stored responses and manage this for you. That moves the bookkeeping, not the underlying reality: the relevant information still has to be present in the context for that inference, even if prefix caching spares the provider from recomputing the unchanged part.</p>
<h3>Why resending everything stops working</h3>
<p>As the conversation grows, including every message causes token cost to rise, prefill time to lengthen, attention work to increase, KV-cache memory to grow, irrelevant or contradictory material to accumulate, and eventually the window to overflow. Note the second-to-last item it is a <em>quality</em> failure, not just a cost one. A long history full of superseded decisions actively degrades answers.</p>
<p>The standard strategies:</p>
<p><strong>Full history.</strong> Send everything. Simple and accurate; fine for short conversations; does not scale.</p>
<p><strong>Sliding window.</strong> Send only the most recent N messages. Bounded size, but silently drops the important decision made on turn 3.</p>
<p><strong>Summary memory.</strong> Compress older turns into a shorter summary. Saves tokens; loses exact details and can bake in a summarization error that then propagates forever.</p>
<p><strong>Structured state.</strong> Store the facts that matter explicitly:</p>
<pre><code class="language-json">{
  "preferred_language": "Python",
  "database": "PostgreSQL",
  "currency": "INR",
  "use_decimal_for_money": true
}
</code></pre>
<p>Far safer than hoping a natural-language summary preserved them. If a fact would be a bug when lost, it belongs in a field, not a paragraph.</p>
<p><strong>Retrieval-based memory.</strong> Search stored fragments and inject only what is relevant essentially <strong>RAG</strong> applied to conversation history.</p>
<p>Real systems combine these:</p>
<pre><code class="language-plaintext">new user message
        ↓
   orchestrator
   ├── user profile (structured)
   ├── recent messages (window)
   ├── older summary
   └── retrieved relevant memories
        ↓
 build current context
        ↓
    model inference
</code></pre>
<h3>External systems are the source of truth</h3>
<p>If the model used a tool to create a ticket, send an email, or read a balance, the <em>external system</em> holds the real result. On a later request, query that system again rather than trusting a sentence the model generated earlier. A model's claim that an action succeeded is text, not evidence.</p>
<p>One more distinction: statelessness does not mean nobody stores your data. Your application, the provider, logs, analytics, and tool vendors may all retain information according to their own policies. <strong>Model memory</strong> and <strong>data retention</strong> are entirely separate questions, and conflating them will get you in trouble in a security review.</p>
<hr />
<h2>5. From base model to assistant: three training stages</h2>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/c8ee8a7d-6953-422d-8346-adafbe2f9c00.png" alt="" style="display:block;margin:0 auto" />

<p>All three stages adjust the weights. They differ in what signal they use and what behavior they teach.</p>
<h3>How training changes weights at all</h3>
<p>Every training step, at a high level:</p>
<ol>
<li><p>Show the model an example.</p>
</li>
<li><p>Get its prediction.</p>
</li>
<li><p>Measure the error with a <strong>loss function</strong>.</p>
</li>
<li><p>Use <strong>back propagation</strong> to work out how each weight contributed to that error.</p>
</li>
<li><p>Use an <strong>optimizer</strong> to nudge the weights slightly.</p>
</li>
</ol>
<p>Repeat across an enormous number of examples.</p>
<h3>Cross-entropy loss, briefly</h3>
<p>Since it comes up constantly, it is worth understanding directly. Cross entropy is <strong>the score for how wrong the model's probabilities were</strong>.</p>
<p>The model outputs probabilities over the whole vocabulary. You then look at what the correct next token actually was and ask: how much probability did you give <em>that</em>?</p>
<pre><code class="language-plaintext">gave it 90%  →  small loss
gave it 50%  →  bigger loss
gave it  1%  →  huge loss
</code></pre>
<p>The loss for one token is <code>-log(p_correct)</code>. The logarithm is what makes confident mistakes hurt disproportionately. Being 50/50 and wrong is cheap; insisting on <code>blue</code> when the answer was <code>dark</code> is expensive. So cross entropy specifically punishes <strong>confident wrongness</strong> harder than uncertainty.</p>
<p>Training averages this over billions of tokens and nudges the weights so that correct tokens receive more probability next time. Falling loss means the model is assigning more probability to what actually comes next.</p>
<p>And notice the connection: this is the very same distribution that temperature reshapes at generation time. Cross entropy is how that distribution got its shape in the first place.</p>
<h3>Pre training: learning what text looks like</h3>
<p>A causal language model learns to predict the next token across enormous amounts of text.</p>
<pre><code class="language-plaintext">The capital of France is  →  Paris
def add(a, b):            →  return
</code></pre>
<p>Every sequence yields many examples:</p>
<pre><code class="language-plaintext">AI                      → systems
AI systems              → can
AI systems can          → process
AI systems can process  → language
</code></pre>
<p>The targets come from the data itself, which is why this is called <strong>self-supervised learning</strong>.</p>
<p>To get good at this narrow task, the model has to absorb grammar, vocabulary, style, code structure, relationships between concepts, a great many facts, and some reasoning patterns. The result is a <strong>base model</strong> or <strong>foundation model</strong>.</p>
<p>A base model is a text continuer, and that is all it is. Given a question it may well continue with more questions, because that is a plausible continuation of a document containing a question. Pre training creates capability. It says nothing about how to behave.</p>
<h3>Instruction tuning: learning to respond</h3>
<p><strong>Instruction tuning</strong>, usually via <strong>Supervised Fine-Tuning (SFT)</strong>, trains on prompt-and-response demonstrations:</p>
<pre><code class="language-plaintext">Instruction:  Summarize this paragraph in one sentence.
Response:     [a good one-sentence summary]
</code></pre>
<p>Thousands of these teach the model to answer rather than continue, follow system and user instructions, handle summarization and classification and translation and transformation, produce requested formats, use conversational roles, and follow some safety and refusal patterns.</p>
<p>The examples may be human-written, model-generated, expert-reviewed, or some mix. Instruction tuning can add specialized knowledge, but its primary job is <strong>behavioral</strong>: teaching a capable text predictor how to apply itself to a request.</p>
<h3>Preference tuning: learning which response is better</h3>
<p>Many answers can be valid, correct, and still not equally good. Preference tuning uses comparisons to teach which behavior is preferred.</p>
<pre><code class="language-plaintext">one prompt
   ├── Response A ──┐
   └── Response B ──┤
                    ↓
          human or AI evaluator
                    ↓
        chosen  /  rejected
                    ↓
        preference optimization
</code></pre>
<p>Evaluators weigh helpfulness, correctness, relevance, safety, clarity, honesty, tone, and instruction-following. A rejected response is often not wrong merely worse.</p>
<p><strong>RLHF (Reinforcement Learning from Human Feedback).</strong> Three steps: people compare pairs of responses; those comparisons train a <strong>reward model</strong> whose only job is to score a response with a number; then reinforcement learning nudges the assistant toward higher-scoring behavior. <strong>PPO</strong> is the algorithm historically used for that last step.</p>
<p>The reward model is the clever part. It is a <strong>scalable stand-in for human taste</strong>. You cannot have people rate millions of responses, but you can train something that imitates their judgment and let it rate them all day.</p>
<p><strong>RLAIF (Reinforcement Learning from AI Feedback).</strong> Another model provides some or all of the preference judgments, typically applying principles that people wrote or selected. Humans set the standard; the AI applies it at volume.</p>
<p><strong>DPO (Direct Preference Optimization).</strong> Skips the separate reward model entirely. Feed it chosen/rejected pairs and it adjusts directly:</p>
<pre><code class="language-plaintext">chosen response   → make more likely
rejected response → make less likely
</code></pre>
<p>Simpler pipeline, same destination.</p>
<p>All three share one goal: <strong>make preferred responses more likely than less-preferred ones.</strong> And note the careful wording preference tuning shifts the odds across behaviors the model <em>could already produce</em>. It is not teaching new facts.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/abee78b4-58c8-4edf-afbf-db3045f2440e.png" alt="" style="display:block;margin:0 auto" />

<h3>The limits of all three stages</h3>
<pre><code class="language-plaintext">Pretraining:         What text is likely?
Instruction tuning:  How should I respond to a request?
Preference tuning:   Which possible response is preferred?
</code></pre>
<p>Read that list again and notice what is missing. <strong>None of them asks whether the answer is true.</strong></p>
<p>Worse, preference data can actively pull against truth. It can favor persuasive answers over accurate ones. It can produce <strong>sycophancy</strong>, where the model agrees with an incorrect user claim because agreement was rated pleasant. It can produce <strong>reward hacking</strong>, where the model satisfies the measured proxy without satisfying the actual goal.</p>
<p>Real pipelines include more than three stages: continued pre training on specialized text, tool-use training, safety training, synthetic data, reasoning-oriented reinforcement learning, and <strong>distillation</strong> from a larger model. The three-stage picture stays useful because it separates capability, instruction-following, and preferred behavior three things that fail independently.</p>
<hr />
<h2>6. Why language models hallucinate</h2>
<h3>What it means</h3>
<p>A <strong>hallucination</strong> is generated information that is false, unsupported, fabricated, or inconsistent with the evidence provided. In practice:</p>
<ul>
<li><p>an invented person, date, product, or event</p>
</li>
<li><p>a nonexistent paper, quotation, DOI, or URL</p>
</li>
<li><p>a statement contradicting a document you supplied</p>
</li>
<li><p>an API method, parameter, or config option that does not exist</p>
</li>
<li><p>a claim that a tool action succeeded when it never ran</p>
</li>
</ul>
<p>This is not lying. Lying requires intent to deceive. The model is producing likely token sequences, and a confident false sentence is frequently the most likely one.</p>
<h3>The root cause is an objective mismatch</h3>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/d4091b89-e4ce-4e9c-b80c-4c40d78073c9.png" alt="" style="display:block;margin:0 auto" />

<p>Fluency is not evidence of accuracy. A high token probability means a continuation matches learned patterns well. It is emphatically <strong>not</strong> a calibrated probability that the statement is true. Everything in section 5 optimized for the left side of that diagram. The dotted line is your job.</p>
<h3>The mechanisms, which stack</h3>
<p><strong>Knowledge is distributed, not stored as records.</strong> Weights compress statistical patterns. That is what enables paraphrase and generalization, and it is also why exact retrieval of rare names, dates, long numbers, quotations, and citations is unreliable. The model often recovers the correct <em>shape</em> of an answer and fills an exact detail wrongly which is precisely why fabricated citations look so convincing.</p>
<p><strong>Training data is imperfect.</strong> It contains material that is wrong, outdated, contradictory, fictional, biased, or simply low quality. Next-token training does not fact-check sources or reliably identify the authoritative one.</p>
<p><strong>Required context may be absent.</strong> If a company rule, an earlier agreement, or a current event is not in the prompt and not reachable by a tool, the model may still generate the most natural-looking answer. Statelessness makes this sharp: details from an earlier request are not available just because they once existed.</p>
<p><strong>The question may be ambiguous.</strong> <code>Mercury</code> is a planet, an element, a deity, a company, a product, and a person. Pick the wrong one and you get a polished, fluent, entirely irrelevant answer. When ambiguity would change the result materially, asking is safer than guessing.</p>
<p><strong>Attention can miss evidence you supplied.</strong> In long or noisy contexts the right passage gets overlooked especially in the middle, especially when several similar passages compete. The model then falls back on pretrained patterns instead of your document. This is lost-in-the-middle turning into a factual error.</p>
<p><strong>Errors compound auto regressively.</strong> Every generated token becomes input for the next. One wrong early detail causes the model to generate supporting details around it, then an explanation for those, producing something internally consistent and completely false.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/2701a280-8863-4bb3-a802-6f3c292e5983.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Sampling can choose a bad path.</strong> Non-zero temperature lets a less likely token through, which can steer the whole answer wrong. Lowering temperature reduces variation and, as established, greedy decoding will still pick a wrong top answer with total confidence.</p>
<p><strong>Preference pressure can discourage honesty.</strong> Users tend to prefer complete, confident answers. If feedback rewards confidence more than justified uncertainty, the model learns to answer when it should abstain. Good preference training tries to reward honest uncertainty; the tension does not fully go away.</p>
<p><strong>Knowledge goes stale.</strong> Weights do not update when prices, laws, software versions, schedules, or leadership change. Current questions need current sources.</p>
<p><strong>Retrieval and tools fail in their own ways.</strong> RAG can fetch the wrong passage, miss the right one, return outdated material, or drown the model in noise. Tools can get bad arguments, fail silently, or return data the model misreads. Grounding lowers risk only when the whole pipeline works.</p>
<h3>Types worth distinguishing</h3>
<p>Separating these matters because they need different defenses and different metrics:</p>
<table>
<thead>
<tr>
<th>Type</th>
<th>What it looks like</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Factual</strong></td>
<td>a false claim about the world</td>
</tr>
<tr>
<td><strong>Fabricated citation</strong></td>
<td>a realistic source that does not exist or does not support the claim</td>
</tr>
<tr>
<td><strong>Faithfulness failure</strong></td>
<td>an answer contradicting or exceeding the supplied evidence</td>
</tr>
<tr>
<td><strong>Tool hallucination</strong></td>
<td>claiming an external action happened without a successful result</td>
</tr>
<tr>
<td><strong>Code hallucination</strong></td>
<td>a nonexistent library, function, parameter, or API behavior</td>
</tr>
</tbody></table>
<h3>Reducing hallucination through system design</h3>
<p>No prompt setting removes hallucination. Reliable systems layer defenses:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/3498f8f9-9d87-4076-9da4-312a42f2c49e.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Provide authoritative context.</strong> Give the model the exact policy, record, or specification it should use. Tell it not to go beyond that evidence, and explicitly permit it to say the answer is not available.</p>
<p><strong>Retrieve a small, relevant set.</strong> Trusted and current documents, real access controls, useful metadata, deduplication, relevance ranking. More context is not better it is more competition for attention and more room to get lost in the middle.</p>
<p><strong>Require evidence links.</strong> Have the model attach document IDs, sections, or evidence spans to important claims. Then verify <strong>programmatically</strong> that the reference exists and actually supports the claim. A citation the model invented and you never checked is worse than no citation, because it manufactures false confidence.</p>
<p><strong>Use deterministic tools.</strong> Calculator for arithmetic, database for balances, search for current facts, code execution for data processing, compiler and tests for generated code. The model should <em>orchestrate</em> exact operations, not imitate them in prose. This is the strawberry principle applied at system scale.</p>
<p><strong>Validate structured output.</strong> JSON Schema, type checks, required fields, allowed values, range checks, business rules. Necessary and note that structural validity proves nothing about factual correctness. A perfectly well-formed invoice total can be wrong.</p>
<p><strong>Verify high-risk claims independently.</strong> Extract the claims that matter and check them against authoritative data. A second model can help only if it receives <em>independent</em> evidence; two models given the same bad context will agree confidently on the same mistake.</p>
<p><strong>Design for abstention.</strong> "I don't have enough evidence for that" must be an acceptable product outcome, with UI that supports it. Then <em>test</em> whether the model actually abstains when information is missing, rather than assuming an instruction was obeyed.</p>
<p><strong>Evaluate specific failure modes.</strong> Build cases for known answers, unanswerable questions, ambiguous questions, conflicting sources, very long contexts, stale facts, adversarial instructions, and tool failures. Measure factual accuracy, grounded ness, citation correctness, abstention quality, tool-call correctness, and output validity as <strong>separate numbers</strong>. Averaged into one score, they hide exactly the problems you need to see.</p>
<hr />
<h2>Putting the six together</h2>
<p>A production assistant answering a question about company policy:</p>
<ol>
<li><p>The application receives the question and <strong>tokenizes</strong> the instructions, evidence, and history which is also where it learns what this request will cost.</p>
</li>
<li><p>It keeps the request inside the <strong>context window</strong>, retrieves only relevant passages, orders them so stable content sits first for prefix reuse, and positions the critical material where attention will actually find it.</p>
</li>
<li><p>The model emits next-token probabilities, and conservative <strong>sampling</strong> builds the answer token by token.</p>
</li>
<li><p>Because the model is <strong>stateless</strong>, the application stores the conversation and stable user preferences outside it the important facts in structured fields, not in a summary paragraph.</p>
</li>
<li><p><strong>Pre training</strong> supplied the language ability, <strong>instruction tuning</strong> made it answer the request, <strong>preference tuning</strong> made it helpful and safe.</p>
</li>
<li><p>Because none of those stages checks truth, the application limits <strong>hallucination</strong> by grounding every claim in approved policy text and verifying the cited sections before the user sees anything.</p>
</li>
</ol>
<pre><code class="language-plaintext">stored conversation and user state
        ↓
retrieve relevant evidence
        ↓
build token-limited context
        ↓
instruction + preference-tuned model
        ↓
sample answer tokens
        ↓
validate evidence and output
        ↓
return answer, store new state
</code></pre>
<p>Which leads to the one lesson underneath all six:</p>
<blockquote>
<p>A language model is a probabilistic generation component, not an information system. Reliability lives in the architecture around it context management, external state, retrieval, tools, validation, and evaluation.</p>
</blockquote>
<hr />
<h2>Shipping checklist</h2>
<p>Before an LLM feature goes live:</p>
<ul>
<li><p>Which tokenizer does the model use, and what are the real token counts in every language you support?</p>
</li>
<li><p>How much context is genuinely necessary, and where are the critical instructions and evidence placed within it?</p>
</li>
<li><p>Can the stable part of the prompt be reused or cached, and is anything volatile leaking into the prefix?</p>
</li>
<li><p>Which sampling settings match this task's need for consistency versus creativity?</p>
</li>
<li><p>What information must persist outside the model?</p>
</li>
<li><p>Which facts belong in structured state rather than a conversation summary?</p>
</li>
<li><p>Is the model you selected a base model, an instruction model, or a preference-tuned assistant?</p>
</li>
<li><p>Which claims require retrieval, tools, or independent verification?</p>
</li>
<li><p>Can the system abstain safely when evidence is missing, and have you tested that it does?</p>
</li>
<li><p>Which evaluations measure factuality, groundedness, tool correctness, and failure behavior separately?</p>
</li>
</ul>
<p>Clear answers to those ten questions get you most of the way to a system that is predictable, affordable, and trustworthy.</p>
]]></content:encoded></item><item><title><![CDATA[Large Language Models, Explained Briefly]]></title><description><![CDATA[The one picture to keep in your head: text goes in, and probabilities for the next word come out. Everything else in this article is a detail hanging off that sentence.



What's in this article



#
]]></description><link>https://intro-generative-ai.hashnode.dev/large-language-models-explained-briefly</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/large-language-models-explained-briefly</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Thu, 17 Sep 2026 13:04:57 GMT</pubDate><content:encoded><![CDATA[<p><strong>The one picture to keep in your head:</strong> text goes in, and probabilities for the next word come out. Everything else in this article is a detail hanging off that sentence.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/b2f29b82-f4b6-4373-8b3b-654839dae2e7.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>What's in this article</h3>
<table>
<thead>
<tr>
<th>#</th>
<th>Part</th>
<th>What it answers</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>The central idea</td>
<td>What an LLM actually does</td>
</tr>
<tr>
<td>2</td>
<td>From prediction to conversation</td>
<td>How a chatbot writes a reply</td>
</tr>
<tr>
<td>3</td>
<td>How the model learns</td>
<td>Parameters, pre-training, back propagation</td>
</tr>
<tr>
<td>4</td>
<td>Training vs. using the model</td>
<td>Why it doesn't learn while you chat</td>
</tr>
<tr>
<td>5</td>
<td>The scale of computation</td>
<td>How much math this really is</td>
</tr>
<tr>
<td>6</td>
<td>From text predictor to assistant</td>
<td>What RLHF adds</td>
</tr>
<tr>
<td>7</td>
<td>Hardware and architecture</td>
<td>Why GPUs and transformers mattered</td>
</tr>
<tr>
<td>8</td>
<td>Inside the transformer</td>
<td>Attention and feed-forward layers</td>
</tr>
<tr>
<td>9</td>
<td>Designed framework, emergent behaviour</td>
<td>Why nobody programmed the skills</td>
</tr>
<tr>
<td>10</td>
<td>At a glance</td>
<td>The whole thing in one table</td>
</tr>
</tbody></table>
<hr />
<h2>Part 1 The central idea</h2>
<h3>1.1 One job: predict the next word</h3>
<p>Imagine you find a short movie script. A person is talking to an AI assistant, but the assistant's reply is missing.</p>
<p>Now imagine a machine that can read any text and <strong>predict the next word</strong>. You feed it the script. It predicts one word. You append that word to the script and ask again. You repeat until the reply is complete.</p>
<p>That is a modern chatbot. Nothing more exotic is going on.</p>
<h3>1.2 Probabilities, not certainty</h3>
<p>A large language model (LLM) is a very large mathematical function. It reads text and predicts what comes next but it is rarely sure about a single word. Instead it assigns a <strong>probability to every possible next word</strong> in its vocabulary.</p>
<blockquote>
<p><strong>💡 Keep this in mind</strong> The model never outputs <em>a word</em>. It outputs <em>a distribution over all words</em>. Something else picks from it.</p>
</blockquote>
<hr />
<h2>Part 2 From prediction to conversation</h2>
<h3>2.1 The generation loop</h3>
<p>To build a chatbot, the software first sets up text that looks like a conversation between a user and an assistant. Your message is inserted into it. Then the model writes the assistant's turn, one word at a time:</p>
<ol>
<li><p>The model reads all the text so far and produces probabilities for the next word.</p>
</li>
<li><p>The software picks one word from those probabilities.</p>
</li>
<li><p>That word is appended to the text.</p>
</li>
<li><p>The whole thing runs again until the answer is finished.</p>
</li>
</ol>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/bb37bf78-6cd3-4f80-a7c7-7d85cee52621.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>2.2 Why the same question gets different answers</h3>
<p>If the software always chose the single most likely word, replies would come out stiff and repetitive. So it sometimes picks a less likely word at random. This is called <strong>sampling</strong>.</p>
<p>Here's the subtle part: the model itself can be <strong>deterministic</strong> the same input produces the same list of probabilities every time. The randomness is added <em>afterwards</em>, at the picking step. That's why asking the same question twice can give you two different replies.</p>
<hr />
<h2>Part 3 How the model learns</h2>
<h3>3.1 Parameters: billions of dials</h3>
<p>The model learns by reading an enormous amount of text, mostly collected from the internet. For GPT-3 alone, a person reading nonstop day and night would need <strong>more than 2,600 years</strong> to get through it. Newer models read far more.</p>
<p>Inside the model sit billions of numbers called <strong>parameters</strong> or <strong>weights</strong>. Think of them as dials on a giant machine. Turning a dial changes the probabilities the model assigns to the next word.</p>
<p>That's part of what "large" means in <em>large language model</em>: hundreds of billions of dials.</p>
<p>Nobody sets them by hand. They start random, so a fresh model produces pure nonsense. Training slowly turns them until predictions get good.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/8f1c8876-0966-4200-ac11-e1d7fb60bd6c.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>3.2 Pre-training and back propagation</h3>
<p><strong>Pre-training</strong> is the first big learning phase, and the task is deliberately simple: predict the next word.</p>
<p>A training example might be a few words or a few thousand. The model sees everything except the final word, guesses it, and the training system compares that guess to the real word.</p>
<p><strong>Back propagation</strong> is <em>how</em> the model learns from being wrong:</p>
<ol>
<li><p>The model makes a prediction say <strong>"dog"</strong> instead of <strong>"mat"</strong>.</p>
</li>
<li><p>The size of the mistake is measured as a number called the <strong>loss</strong>.</p>
</li>
<li><p>Back propagation works backward through the network and works out how much each weight contributed to that error.</p>
</li>
<li><p>Every weight is nudged slightly so the correct word becomes a little more likely and the wrong ones a little less. That nudging is <strong>gradient descent</strong>.</p>
</li>
</ol>
<p>Repeat across <strong>trillions of examples</strong>, and those tiny nudges accumulate into a model that predicts text remarkably well.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/6b7db6b3-bf6f-4fd1-bf9d-c922a0256e57.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<blockquote>
<p><strong>⚠️ A common misunderstanding</strong> Weights do not belong to individual words. There is no single weight for "mat" or "dog". All the weights work together on every prediction, so one update affects how the model handles many different words and sentences. That sharing is exactly why the model learns general patterns instead of memorising a lookup table.</p>
</blockquote>
<h3>3.3 How can it possibly get through all that text?</h3>
<p>It really does train on almost all of it. A few tricks make that feasible:</p>
<ul>
<li><p><strong>Batches</strong> the model processes huge chunks of text together, averages the errors, and updates weights once per batch rather than once per word.</p>
</li>
<li><p><strong>Every position at once</strong> in "The cat sat on the mat" it predicts "cat" from "The", "sat" from "The cat", and so on, all in a single pass. One sentence yields many training examples.</p>
</li>
<li><p><strong>Thousands of GPUs</strong> working simultaneously.</p>
</li>
<li><p><strong>One pass is usually enough</strong> the model typically reads its giant dataset only about once.</p>
</li>
</ul>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/73f620bd-0eba-4661-bbe8-e4bd984d5c9a.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>3.4 Generalization</h3>
<p>The model doesn't only get better at predicting its training text. It also makes sensible predictions on text it has <strong>never seen before</strong>. That's called <strong>generalization</strong>, and it's the whole reason the thing is useful outside the lab.</p>
<hr />
<h2>Part 4 Training vs. using the model</h2>
<p>It's tempting to assume the model is learning while you chat with it. It isn't.</p>
<p><strong>Back propagation happens only during training.</strong> When you ask a question, the model is in <strong>inference</strong> mode: the weights are frozen. Your text runs forward through the network and words come out. Nothing gets updated.</p>
<p>It also almost certainly hasn't seen your exact question before. Training shaped its weights to capture general patterns grammar, facts, how explanations are structured, how code works. When you ask something new, it recombines those patterns into an answer it may never have seen word for word.</p>
<blockquote>
<p><strong>🎓 Think of a student</strong> A student practises thousands of maths problems with a teacher correcting them that's <strong>training</strong>. In the exam they get a new problem that's <strong>inference</strong>. They don't learn during the exam, and they never saw that exact problem, but they solve it with the methods they absorbed.</p>
</blockquote>
<p>This also explains why LLMs get things wrong. If the learned patterns don't fit your question well, the model can produce an answer that sounds confident and is simply incorrect.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/41ab1ce2-e80a-49dc-befe-7779d3da9f7a.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<hr />
<h2>Part 5 The scale of computation</h2>
<p>Inside the model, training is just simple arithmetic: adding and multiplying numbers. But it happens an absurd number of times, because the dataset is huge <strong>and</strong> every one of the billions of weights participates in every single prediction.</p>
<p>So here's a thought experiment. Imagine you're a superhuman calculator doing <strong>one billion calculations every second</strong>, never stopping. How long to complete all the math used to train the largest language models?</p>
<table>
<thead>
<tr>
<th>Guess</th>
<th>Verdict</th>
</tr>
</thead>
<tbody><tr>
<td>1 year</td>
<td>not close</td>
</tr>
<tr>
<td>10,000 years</td>
<td>still not close</td>
</tr>
<tr>
<td><strong>Well over 100,000,000 years</strong></td>
<td><strong>that's the real answer</strong></td>
</tr>
</tbody></table>
<p>Real training finishes in weeks or months only because thousands of specialised chips do this math simultaneously. Even then, it costs millions of dollars.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/e2e41b01-9944-49cd-a6c2-66c1dc432a3f.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<hr />
<h2>Part 6 From text predictor to assistant</h2>
<p>Everything so far is <strong>pre-training</strong>. But being excellent at continuing random internet text is not the same as being a helpful assistant. Ask a purely pre-trained model "How do I bake a cake?" and it might reply with <em>more questions</em> because that's what a forum page looks like.</p>
<p>So chatbots get a second round of training: <strong>RLHF</strong>, or <strong>reinforcement learning with human feedback</strong>.</p>
<ol>
<li><p>The model produces answers.</p>
</li>
<li><p>Human reviewers flag answers that are unhelpful or problematic, and indicate which answers are better.</p>
</li>
<li><p>That feedback is used to adjust the weights again.</p>
</li>
<li><p>The model becomes more likely to produce answers people actually prefer.</p>
</li>
</ol>
<blockquote>
<p><strong>🎓 The student, again</strong> Pre-training is a student reading an entire library and absorbing enormous knowledge. RLHF is a teacher then showing that student how to answer a question clearly, helpfully, and politely.</p>
</blockquote>
<p>For assistant-like behaviour, this stage matters roughly as much as pre-training does.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/62f75a32-4419-4cd4-82a3-341859f000fc.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<hr />
<h2>Part 7 Why GPUs and transformers mattered</h2>
<h3>7.1 GPUs: thousands of workers at once</h3>
<p>A normal CPU is like one very capable worker handling tasks one after another. A <strong>GPU</strong> (graphics processing unit) is like thousands of simpler workers each handling a small task at the same moment. GPUs were built for video games, where millions of pixels must be computed at once. Training an LLM also needs millions of small calculations at once a near-perfect match.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/9efb3d43-1713-4f7d-a307-eec18507b02f.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>7.2 The architecture has to allow parallel work too</h3>
<p>Thousands of workers are useless if the job can only be done one step at a time. Before 2017, most language models read text <strong>one word at a time</strong>, in order. To process word 5 they had to finish words 1–4 first so most of the GPU sat idle.</p>
<p>In 2017, a team of Google researchers introduced the <strong>transformer</strong>. It doesn't have to read start to finish. It ingests <strong>all the words at the same time</strong>, which keeps every GPU worker busy and makes training on massive text practical.</p>
<blockquote>
<p><strong>📖 Picture it</strong> Older models read a book one word at a time, left to right. A transformer looks at the whole page at once.</p>
</blockquote>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/b06df5bd-db64-4f84-acab-5cd6466cac20.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>7.3 Turning words into numbers</h3>
<p>Computers can't do arithmetic on the word "cat". And training needs smooth numbers that can be nudged slightly up or down. So the first step inside a transformer is converting each word into a long list of numbers called a <strong>vector</strong>.</p>
<pre><code class="language-plaintext">cat  →  [  0.2, −1.3,  0.8, … ]
dog  →  [  0.3, −1.1,  0.7, … ]
car  →  [ −0.9,  0.5,  2.1, … ]
</code></pre>
<p><em>(These numbers are invented for illustration real vectors have hundreds or thousands of dimensions.)</em></p>
<p>Those numbers are learned during training, and a vector can carry aspects of a word's meaning. Words with similar meanings end up with similar vectors: <strong>cat</strong> and <strong>dog</strong> land close together, while <strong>car</strong> sits far away.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/b116269d-0cf2-42cc-a64b-f0f6594d7963.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<hr />
<h2>Part 8 Inside the transformer</h2>
<h3>8.1 Attention: words talk to each other</h3>
<p>Initially, a word's vector is identical in every sentence. But plenty of words change meaning with context. The signature operation inside a transformer <strong>attention</strong> lets the vectors for different words communicate. Each vector looks at the words around it and updates itself. And because the transformer sees all words at once, this happens in parallel.</p>
<p>Take the word <strong>bank</strong>:</p>
<ul>
<li><p><em>"I deposited money in the bank."</em> → a financial institution.</p>
</li>
<li><p><em>"We sat on the bank of the river."</em> → the edge of a river.</p>
</li>
</ul>
<p>In the second sentence, attention notices "river" nearby and adjusts the vector for "bank" so it leans toward the riverbank meaning. The financial sense fades out.</p>
<blockquote>
<p><strong>🗣️ Picture a group discussion</strong> Everyone listens to everyone else simultaneously, and each person updates their understanding based on what the others said.</p>
</blockquote>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/22c26fd0-2eda-43ca-a161-ddbb4e67854f.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>8.2 Feed-forward networks: stored patterns</h3>
<p>A transformer also contains <strong>feed-forward neural networks</strong>. Where attention mixes information <em>between</em> words, a feed-forward network operates on each word's vector independently, applying language patterns the model absorbed during training. They give the model room to store what it knows.</p>
<table>
<thead>
<tr>
<th>Component</th>
<th>The question it asks</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Attention</strong></td>
<td><em>What do the other words tell me?</em></td>
</tr>
<tr>
<td><strong>Feed-forward</strong></td>
<td><em>What do I already know about this?</em></td>
</tr>
</tbody></table>
<h3>8.3 The journey through a transformer</h3>
<p>This doesn't happen once. The vectors pass through many layers, each adding more useful context like revising a draft over and over.</p>
<ol>
<li><p><strong>Encode</strong> turn each input word into a long vector of numbers.</p>
</li>
<li><p><strong>Attend</strong> let vectors share context with each other, in parallel.</p>
</li>
<li><p><strong>Transform</strong> apply feed-forward networks that layer in learned patterns.</p>
</li>
<li><p><strong>Repeat</strong> pass through many layers, making every vector richer.</p>
</li>
<li><p><strong>Predict</strong> use the final vector to produce a probability for every possible next word.</p>
</li>
</ol>
<p>At the end, only the <strong>last vector</strong> in the sequence is used for the prediction. By then it has absorbed information from the entire input plus everything the model learned in training. A final function converts it into probabilities: "mat" 40%, "floor" 25%, and so on.</p>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/9be22fbb-b678-4706-abaf-30ab0a2f91fc.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<p><strong>Then the loop closes:</strong> the transformer turns context into next-word probabilities, the chatbot picks a word, appends it, and runs the whole thing again.</p>
<hr />
<h2>Part 9 Designed framework, emergent behaviour</h2>
<p>Researchers design the structure attention, feed-forward networks, the training procedure. But they <strong>don't write rules</strong> like "here's how to translate French" or "answer cooking questions this way".</p>
<p>Skills such as grammar, translation, summarising, and coding appear on their own once training tunes hundreds of billions of parameters across huge amounts of data. That's an <strong>emergent phenomenon</strong>.</p>
<blockquote>
<p><strong>🌱 Think of a farmer</strong> A farmer supplies soil, water, and sunlight, but doesn't design each leaf and branch. The tree grows its own shape. Researchers set up the conditions; the skills grow out of training.</p>
</blockquote>
<blockquote>
<p><strong>❗ An LLM is not a database of answers</strong> Nobody wrote a list of questions and answers into it. It has weights shaped by training, and it constructs each answer fresh, one word at a time.</p>
</blockquote>
<blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/2ce196a4-7829-42f0-af38-8efc20c1f7da.png" alt="" style="display:block;margin:0 auto" /></blockquote>
<h3>Why it's hard to explain</h3>
<p>Researchers know precisely which mathematical operations run inside. But with billions of weights acting together, it's extraordinarily hard to say <em>why</em> the model chose one particular word over another. It's a little like the brain: we understand how neurons signal, yet we can't point to why you had one specific thought.</p>
<h3>Simple goal, powerful result</h3>
<p>The objective sounds almost too plain: predict the next word. But combine it with enormous models, enormous datasets, GPUs, transformers, and human-feedback training and that plain objective produces fluent, useful, occasionally surprising behaviour.</p>
<p><strong>A simple prediction goal can create powerful behaviour once the model, the data, and the computation all become very large.</strong></p>
<hr />
<h2>Part 10 The whole idea at a glance</h2>
<table>
<thead>
<tr>
<th>Idea</th>
<th>What it means</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Prediction</strong></td>
<td>An LLM assigns probabilities to possible next words.</td>
</tr>
<tr>
<td><strong>Generation</strong></td>
<td>A chatbot picks a word, appends it, and repeats.</td>
</tr>
<tr>
<td><strong>Sampling</strong></td>
<td>Picking with some randomness, so the same prompt can give different answers.</td>
</tr>
<tr>
<td><strong>Parameters</strong></td>
<td>Hundreds of billions of learned numbers that control the model.</td>
</tr>
<tr>
<td><strong>Pre-training</strong></td>
<td>Learning to predict the next word across trillions of examples.</td>
</tr>
<tr>
<td><strong>Back propagation</strong></td>
<td>Working out how to nudge every weight to reduce each error.</td>
</tr>
<tr>
<td><strong>Generalization</strong></td>
<td>Handling text the model has never seen before.</td>
</tr>
<tr>
<td><strong>Inference</strong></td>
<td>Using the trained model; weights frozen, nothing learned.</td>
</tr>
<tr>
<td><strong>RLHF</strong></td>
<td>Human feedback tunes the model toward answers people prefer.</td>
</tr>
<tr>
<td><strong>GPUs</strong></td>
<td>Chips that perform many calculations simultaneously.</td>
</tr>
<tr>
<td><strong>Transformer</strong></td>
<td>An architecture that reads all words in parallel.</td>
</tr>
<tr>
<td><strong>Vectors</strong></td>
<td>Lists of numbers that represent words and carry meaning.</td>
</tr>
<tr>
<td><strong>Attention</strong></td>
<td>Lets context reshape each word's vector.</td>
</tr>
<tr>
<td><strong>Feed-forward</strong></td>
<td>Stores and applies learned language patterns.</td>
</tr>
<tr>
<td><strong>Emergence</strong></td>
<td>Skills grow from training rather than being programmed which is why they're hard to explain.</td>
</tr>
</tbody></table>
<hr />
<p><em>Based on 3Blue1Brown,</em> <a href="https://www.youtube.com/watch?v=LPZh9BOjkQs"><em>Large Language Models explained briefly</em></a> <em>(YouTube, 7:57), with added explanations. Figures are presented as stated in the video; the vector values and probabilities shown are illustrative.</em></p>
]]></content:encoded></item><item><title><![CDATA[Build Reliable AI Agents with LangGraph]]></title><description><![CDATA[When we build AI agents, one of the most important design decisions is how we control the agent’s behavior — how it thinks, acts, and interacts with tools.There are mainly two patterns used in agent design:

The Router Pattern – simple, rule-based, a...]]></description><link>https://intro-generative-ai.hashnode.dev/build-reliable-ai-agents-with-langgraph</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/build-reliable-ai-agents-with-langgraph</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Mon, 13 Oct 2025 16:57:36 GMT</pubDate><content:encoded><![CDATA[<p>When we build AI agents, one of the most important design decisions is <strong>how we control the agent’s behavior</strong> — how it thinks, acts, and interacts with tools.<br />There are mainly <strong>two patterns</strong> used in agent design:</p>
<ol>
<li><p>The <strong>Router Pattern</strong> – simple, rule-based, and predictable.</p>
</li>
<li><p>The <strong>Autonomous Pattern</strong> – powerful, self-directed, and flexible.</p>
</li>
</ol>
<p>But as we’ll see, each has its pros and cons. Eventually, we’ll learn how <strong>LangGraph</strong> helps us <strong>combine the best of both worlds</strong> — flexibility <strong>and</strong> control.</p>
<hr />
<h2 id="heading-1-the-big-picture">1. The Big Picture</h2>
<p>When you design an AI agent, you’re basically building a <strong>flow</strong> — a system that takes input from the user, reasons about it, maybe calls a few tools, and then returns a response.</p>
<p>There are two common ways to design this flow:</p>
<h3 id="heading-the-router-pattern">The Router Pattern</h3>
<p>A <strong>controlled flow</strong>.<br />Your application (not the LLM) decides where the request should go — which tool, chain, or action should handle it. The LLM is used more like a helper, not the decision-maker.</p>
<h3 id="heading-the-autonomous-pattern">The Autonomous Pattern</h3>
<p>A <strong>self-directed flow</strong>.<br />Here, the agent (the LLM) takes the lead. It reasons, plans, and acts on its own — usually using the <strong>ReAct</strong> (Reasoning + Acting) framework.<br />It can think: “What should I do next?” → call a tool → observe the result → think again — repeating until it decides the job is done.</p>
<p>However, there’s a <strong>problem</strong>:<br />In a fully autonomous system, we start to <strong>lose control</strong>.<br />The agent can:</p>
<ul>
<li><p>Loop endlessly,</p>
</li>
<li><p>Retry too often, or</p>
</li>
<li><p>Skip important validation steps.</p>
</li>
</ul>
<p>This makes the system <strong>unpredictable</strong> and <strong>hard to manage</strong> at scale.</p>
<p>That’s where <strong>LangGraph</strong> comes in.<br />It gives us a way to design a <strong>custom workflow (custom graph)</strong> where we decide the <strong>steps</strong>, the <strong>order</strong>, and the <strong>rules</strong> — without losing the reasoning power of an LLM.</p>
<hr />
<h2 id="heading-2-the-router-pattern-simple-and-controlled">2. The Router Pattern — Simple and Controlled</h2>
<p>Let’s start with the <strong>Router Pattern</strong>, the simpler one.</p>
<p>Imagine your application as a <strong>traffic police officer</strong> standing in the middle of a busy road.<br />Every user request is like a vehicle approaching an intersection.<br />The router decides <strong>which direction</strong> each request should go.</p>
<p>For example:</p>
<ul>
<li><p>A user says, “Search for top AI frameworks” → route to the <strong>Search Tool</strong></p>
</li>
<li><p>A user says, “Add meeting to my calendar” → route to the <strong>Calendar Tool</strong></p>
</li>
<li><p>A user says, “Summarize this article” → route to the <strong>Summarizer Chain</strong></p>
</li>
</ul>
<p>You can implement these routing rules using:</p>
<ul>
<li><p>Simple <strong>if-else conditions</strong>, or</p>
</li>
<li><p>A <strong>lightweight LLM classifier</strong> that picks the right branch.</p>
</li>
</ul>
<p>Once the decision is made, that specific tool or chain runs, gives a result, and you return it to the user.</p>
<h3 id="heading-pros-of-the-router-pattern">Pros of the Router Pattern</h3>
<ul>
<li><p><strong>Predictable:</strong> You always know what path the query will take.</p>
</li>
<li><p><strong>Easy to test:</strong> Each route can be tested in isolation.</p>
</li>
<li><p><strong>Production-friendly:</strong> Ideal when consistency and reliability matter most.</p>
</li>
</ul>
<h3 id="heading-cons-of-the-router-pattern">Cons of the Router Pattern</h3>
<ul>
<li><p><strong>Limited flexibility:</strong> If a task needs multiple tools or steps, the router can’t easily handle it.</p>
</li>
<li><p><strong>Manual maintenance:</strong> You have to design and update all the routing rules yourself.</p>
</li>
</ul>
<p>In short:</p>
<blockquote>
<p>Router pattern = “You control every move.”<br />Great for <strong>structured</strong> tasks, not for <strong>open-ended</strong> ones.</p>
</blockquote>
<hr />
<h2 id="heading-3-the-autonomous-pattern-flexible-but-risky">3. The Autonomous Pattern — Flexible but Risky</h2>
<p>The <strong>Autonomous Pattern</strong> is where the agent truly feels “intelligent”.<br />Here, the LLM becomes the <strong>planner</strong> and <strong>decision-maker</strong>.</p>
<p>This is the pattern used in the <strong>ReAct (Reasoning + Acting)</strong> framework — one of the most common agent architectures today.</p>
<p>Let’s break it down.</p>
<h3 id="heading-how-react-works">How ReAct Works</h3>
<p>The ReAct agent follows a simple loop:</p>
<ol>
<li><p><strong>Think</strong> – The LLM reasons: “What do I need to do next?”</p>
</li>
<li><p><strong>Act</strong> – It performs that action, such as calling a tool.</p>
</li>
<li><p><strong>Observe</strong> – It reads the tool’s output.</p>
</li>
<li><p><strong>Repeat</strong> – Based on the observation, it decides the next step.</p>
</li>
</ol>
<p>The agent keeps looping through this “Think → Act → Observe → Repeat” process until it believes the goal is achieved.</p>
<h3 id="heading-example">Example</h3>
<p>If you ask the agent:</p>
<blockquote>
<p>“Schedule a meeting with John for tomorrow and also find the latest AI trends.”</p>
</blockquote>
<p>It might:</p>
<ol>
<li><p>Call the <strong>calendar tool</strong> to schedule the meeting.</p>
</li>
<li><p>Then, call the <strong>search tool</strong> to find AI trends.</p>
</li>
<li><p>Finally, summarize both results and respond.</p>
</li>
</ol>
<p>All of this happens <strong>autonomously</strong> — without you writing specific routing rules.</p>
<h3 id="heading-pros">Pros</h3>
<ul>
<li><p><strong>Highly flexible:</strong> Works for complex, multi-step, or unstructured tasks.</p>
</li>
<li><p><strong>Dynamic reasoning:</strong> The agent can adapt based on context.</p>
</li>
</ul>
<h3 id="heading-cons">Cons</h3>
<ul>
<li><p><strong>Less developer control:</strong> You can’t easily predict what the agent will do next.</p>
</li>
<li><p><strong>Risk of infinite loops:</strong> The agent may keep retrying the same steps endlessly.</p>
</li>
<li><p><strong>Unstable results:</strong> Each run might behave slightly differently.</p>
</li>
</ul>
<p>To avoid this, developers usually set a <strong>maximum loop limit</strong>, such as 25 iterations.<br />But even then, the control is <strong>coarse</strong>, not fine-grained.</p>
<p>In short:</p>
<blockquote>
<p>Autonomous pattern = “The agent decides everything.”<br />Great for <strong>exploration</strong>, risky for <strong>production</strong>.</p>
</blockquote>
<hr />
<h2 id="heading-4-why-build-a-custom-graph-with-langgraph">4. Why Build a Custom Graph with LangGraph?</h2>
<p>Now that we’ve seen both extremes — one too rigid (Router), and one too free (Autonomous) — we need a <strong>middle ground</strong>.</p>
<p>That’s exactly what <strong>LangGraph</strong> provides.</p>
<p>LangGraph allows you to design your agent as a <strong>custom graph</strong>, where you decide:</p>
<ul>
<li><p><strong>The sequence of steps</strong> (like a router),</p>
</li>
<li><p><strong>The intelligence inside each step</strong> (like an autonomous agent), and</p>
</li>
<li><p><strong>The rules and conditions</strong> that control the flow.</p>
</li>
</ul>
<p>You can define exactly what happens after each step let say for example:</p>
<ol>
<li><p>The LLM generates a response →</p>
</li>
<li><p>You send that response for <strong>validation</strong> →</p>
</li>
<li><p>If it’s <strong>invalid</strong>, you can <strong>regenerate</strong> or <strong>adjust</strong> it →</p>
</li>
<li><p>If it’s <strong>valid</strong>, you <strong>send it to the user</strong>.</p>
</li>
</ol>
<p>You can also:</p>
<ul>
<li><p>Limit retries to avoid loops,</p>
</li>
<li><p>Add timeouts for slow tools, and</p>
</li>
<li><p>Log or monitor every step in the process.</p>
</li>
</ul>
<p>So, with a custom LangGraph, you get <strong>the reasoning power of an autonomous agent</strong>, but with <strong>the safety and structure of a router</strong>.</p>
<p>In short:</p>
<blockquote>
<p><strong>LangGraph = Controlled Intelligence.</strong><br />You keep the agent’s brain, but you decide its behavior.</p>
</blockquote>
<hr />
<h2 id="heading-5-langgraph-basics-explained-with-the-veg-biryani-example">5) LangGraph Basics (Explained with the Veg Biryani Example)</h2>
<p>To really understand <strong>LangGraph</strong>, let’s imagine we are cooking <strong>Veg Biryani</strong>.<br />Cooking biryani is a sequence of clear steps that happen one after another — some steps depend on others, and sometimes we even repeat a step if something doesn’t taste right.</p>
<p>This cooking process is a perfect analogy to how <strong>LangGraph</strong> works.</p>
<h3 id="heading-step-1-understanding-nodes-the-building-blocks">Step 1: Understanding Nodes — the Building Blocks</h3>
<p>In LangGraph, each <strong>node</strong> represents one <strong>action</strong> or <strong>step</strong> in your workflow.<br />You can think of a node like a <em>function</em> in code or a <em>task</em> in real life — it does one specific thing and passes its result forward.</p>
<p>For example, when you cook Veg Biryani, you might follow these steps:</p>
<ol>
<li><p><strong>Cut the vegetables</strong></p>
</li>
<li><p><strong>Boil the rice</strong></p>
</li>
<li><p><strong>Add salt</strong></p>
</li>
<li><p><strong>Taste the biryani</strong></p>
</li>
</ol>
<p>Each of these is a <strong>node</strong> in our cooking graph.<br />Every node performs one job, and when it’s done, it sends its result (or “state”) to the next node in the sequence.</p>
<p>So in LangGraph, if you create a node called <code>cut_vegetables</code>, it might run a function that handles all cutting actions. Then the output of this node goes to the next node — <code>boil_rice</code>.</p>
<h3 id="heading-step-2-understanding-edges-connecting-the-steps">Step 2: Understanding Edges — Connecting the Steps</h3>
<p>Now, these nodes don’t exist alone. They are connected by <strong>edges</strong>.<br />An <strong>edge</strong> in LangGraph represents the <strong>flow of control</strong> — it shows which step comes next.</p>
<p>When you finish cutting the vegetables, what do you do next? You boil the rice.<br />So, you draw a connection (or arrow) from <strong>Cut Vegetables ➜ Boil Rice</strong>.</p>
<p>Visually, it’s like drawing arrows between boxes:</p>
<pre><code class="lang-javascript">Cut Vegetables → Boil Rice → Taste Biryani
</code></pre>
<p>This flow tells LangGraph how to move from one task to another.<br />Edges are like the <strong>recipe instructions</strong> that say “after this, do that.”</p>
<h3 id="heading-step-3-conditional-edges-making-decisions">Step 3: Conditional Edges — Making Decisions</h3>
<p>Cooking isn’t always a straight line.<br />Sometimes, we make decisions based on what happens during the process.</p>
<p>For example, after you <strong>taste the biryani</strong>, you might think:</p>
<ul>
<li><p>“Hmm, it needs more salt.”</p>
</li>
<li><p>or, “Perfect! It’s ready to serve.”</p>
</li>
</ul>
<p>In LangGraph, these “if/else” kinds of decisions are represented using <strong>conditional edges</strong>.<br />A conditional edge checks some condition and then decides <strong>which node to go to next</strong>.</p>
<p>So in our example:</p>
<ul>
<li><p>If the biryani <strong>needs salt</strong>, go to the <code>add_salt</code> node.</p>
</li>
<li><p>If the biryani <strong>tastes fine</strong>, go to the <strong>End</strong> node.</p>
</li>
</ul>
<p>Once you add salt, you come back and <strong>taste again</strong> — this creates a small loop:</p>
<pre><code class="lang-javascript">Taste Biryani → Add Salt → Taste Biryani → (Repeat until OK)
</code></pre>
<p>This loop continues until the condition changes — in this case, until the taste is perfect.</p>
<p>So, <strong>conditional edges</strong> make your graph smart.<br />They give your agent the ability to <strong>make decisions</strong> just like you do when cooking.</p>
<h3 id="heading-step-4-state-the-shared-shelf-of-ingredients">Step 4: State — The Shared Shelf of Ingredients</h3>
<p>Now, when you’re cooking, you have a kitchen shelf or counter where all your ingredients sit — rice, salt, vegetables, spices, pots, etc.<br />You keep <strong>using and updating</strong> them as you cook.</p>
<p>In LangGraph, that shelf is called the <strong>state</strong>.</p>
<p>A <strong>state</strong> is the shared data that flows through the graph.<br />Each node can:</p>
<ul>
<li><p><strong>Read</strong> from the state (e.g., “How much salt do we have left?”)</p>
</li>
<li><p><strong>Write</strong> to the state (e.g., “We added 1 tsp of salt.”)</p>
</li>
</ul>
<p>This makes every step <strong>aware</strong> of what happened before.<br />When the “Taste Biryani” node runs, it can look at the state and decide:<br />“Did we already add salt? How much? Should we add more?”</p>
<p>That’s why LangGraph is called a <strong>StateGraph</strong> — it doesn’t just run steps; it also carries and updates shared memory across them.</p>
<h3 id="heading-step-5-start-and-end-the-built-in-boundaries">Step 5: Start and End — The Built-In Boundaries</h3>
<p>In every workflow, there’s always a beginning and an end.<br />In LangGraph, you don’t need to manually create them — they are built-in as <strong>Start</strong> and <strong>End</strong> nodes.</p>
<p>Your graph will automatically begin from the <strong>Start</strong> node and finish at the <strong>End</strong> node once there are no more steps to execute.</p>
<h3 id="heading-step-6-visualizing-it-all-the-cooking-flow">Step 6: Visualizing It All — The Cooking Flow</h3>
<p>If we draw this entire cooking process as a <strong>graph</strong>, it might look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760374377794/af915d6c-be3b-4a9a-8a89-424db7bc9e7b.png" alt class="image--center mx-auto" /></p>
<p>Here’s how to read it:</p>
<ul>
<li><p>The <strong>solid arrows</strong> represent the normal flow of steps.</p>
</li>
<li><p>The <strong>dotted arrows</strong> (or labeled arrows) represent <strong>conditional edges</strong> — they depend on the situation.</p>
</li>
<li><p>The <strong>state</strong> (ingredients, salt level, etc.) moves through every node.</p>
</li>
</ul>
<p>So, this simple biryani recipe actually behaves like a mini <strong>LangGraph workflow</strong>!</p>
<hr />
<h2 id="heading-6-detailed-code-example">6) Detailed code example:</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760374595280/f2319019-8161-4507-a86e-ebd4a54685c3.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-graphjs"><code>graph.js</code></h3>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * Custom LangGraph agent with:
 * - LLM node
 * - Tool execution node
 * - Conditional routing (LLM -&gt; tools -&gt; LLM ... -&gt; END)
 * - Persistent memory via checkpointer
 */</span>

<span class="hljs-keyword">import</span> readline <span class="hljs-keyword">from</span> <span class="hljs-string">'node:readline/promises'</span>;
<span class="hljs-keyword">import</span> { tool } <span class="hljs-keyword">from</span> <span class="hljs-string">'@langchain/core/tools'</span>;
<span class="hljs-keyword">import</span> { ChatGroq } <span class="hljs-keyword">from</span> <span class="hljs-string">'@langchain/groq'</span>;
<span class="hljs-keyword">import</span> { END, MemorySaver, MessagesAnnotation, StateGraph } <span class="hljs-keyword">from</span> <span class="hljs-string">'@langchain/langgraph'</span>;
<span class="hljs-keyword">import</span> { ToolNode } <span class="hljs-keyword">from</span> <span class="hljs-string">'@langchain/langgraph/prebuilt'</span>;
<span class="hljs-keyword">import</span> { TavilySearch } <span class="hljs-keyword">from</span> <span class="hljs-string">'@langchain/tavily'</span>;
<span class="hljs-keyword">import</span> z <span class="hljs-keyword">from</span> <span class="hljs-string">'zod'</span>;
<span class="hljs-keyword">import</span> { printGraph } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.js'</span>;

<span class="hljs-comment">/** -------------------------------
 * MEMORY / CHECKPOINTER
 * -------------------------------
 * - "state" = data passed inside one graph run (between nodes).
 * - "checkpointer" = saves/loads state snapshots across multiple runs (turns) using thread_id.
 *   This gives you conversation memory across user messages.
 */</span>
<span class="hljs-keyword">const</span> checkpointer = <span class="hljs-keyword">new</span> MemorySaver();

<span class="hljs-comment">/** -------------------------------
 * TOOLS
 * -------------------------------
 * Tools are functions the LLM may call during reasoning.
 * We wrap custom functions with `tool(...)` to give them a name + schema.
 */</span>

<span class="hljs-comment">// Internet search tool (prebuilt)</span>
<span class="hljs-keyword">const</span> search = <span class="hljs-keyword">new</span> TavilySearch({
  <span class="hljs-attr">maxResults</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">topic</span>: <span class="hljs-string">'general'</span>,
});

<span class="hljs-comment">// Dummy calendar tool (replace with real Google Calendar)</span>
<span class="hljs-keyword">const</span> calendarEvents = tool(
  <span class="hljs-keyword">async</span> ({ query }) =&gt; {
    <span class="hljs-comment">// do calendar lookup here (query is validated by zod schema below)</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">JSON</span>.stringify([
      {
        <span class="hljs-attr">title</span>: <span class="hljs-string">'Meeting with Sujoy'</span>,
        <span class="hljs-attr">date</span>: <span class="hljs-string">'9 Aug 2025'</span>,
        <span class="hljs-attr">time</span>: <span class="hljs-string">'2 PM'</span>,
        <span class="hljs-attr">location</span>: <span class="hljs-string">'Google Meet'</span>,
      },
    ]);
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">'get-calendar-events'</span>,
    <span class="hljs-attr">description</span>: <span class="hljs-string">'Get calendar events by query.'</span>,
    <span class="hljs-attr">schema</span>: z.object({
      <span class="hljs-comment">// zod schema tells the LLM what input shape is allowed</span>
      <span class="hljs-attr">query</span>: z.string().describe(<span class="hljs-string">'Query used to search calendar events.'</span>),
    }),
  }
);

<span class="hljs-comment">// The ToolNode is a LangGraph node that executes any tool calls requested by the LLM.</span>
<span class="hljs-comment">// We pass all available tools so it knows what it can run.</span>
<span class="hljs-keyword">const</span> tools = [search, calendarEvents];
<span class="hljs-keyword">const</span> toolNode = <span class="hljs-keyword">new</span> ToolNode(tools);

<span class="hljs-comment">/** -------------------------------
 * LLM
 * -------------------------------
 * - We bind tools so the LLM can emit structured `tool_calls`.
 * - temperature: 0 for more deterministic outputs.
 */</span>
<span class="hljs-keyword">const</span> llm = <span class="hljs-keyword">new</span> ChatGroq({
  <span class="hljs-attr">model</span>: <span class="hljs-string">'openai/gpt-oss-120b'</span>,
  <span class="hljs-attr">temperature</span>: <span class="hljs-number">0</span>,
}).bindTools(tools);

<span class="hljs-comment">/** -------------------------------
 * LLM NODE
 * -------------------------------
 * Simple node that:
 *  - reads chat history from state.messages
 *  - calls the LLM
 *  - appends the assistant message (possibly with tool_calls) back into state
 */</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callModel</span>(<span class="hljs-params">state <span class="hljs-regexp">/* MessagesAnnotation state */</span></span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> llm.invoke(state.messages);
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">messages</span>: [response] };
}

<span class="hljs-comment">/** -------------------------------
 * ROUTER / BRANCH FUNCTION
 * -------------------------------
 * After the LLM responds, decide where to go next:
 *  - If LLM asked to call a tool =&gt; go to 'tools' node.
 *  - Otherwise =&gt; finish (END).
 * This is a "conditional edge predicate" (router/policy).
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">shouldContinue</span>(<span class="hljs-params">state</span>) </span>{
  <span class="hljs-keyword">const</span> last = state.messages[state.messages.length - <span class="hljs-number">1</span>];
  <span class="hljs-keyword">return</span> (last.tool_calls?.length) ? <span class="hljs-string">'tools'</span> : <span class="hljs-string">'__end__'</span>;
}

<span class="hljs-comment">/** -------------------------------
 * BUILD THE GRAPH
 * -------------------------------
 * - StateGraph(MessagesAnnotation): we use a chat-style state (has `messages`).
 * - Nodes:
 *    'llm'   =&gt; runs callModel (think/respond)
 *    'tools' =&gt; runs toolNode  (act: execute tool calls)
 * - Edges:
 *    __start__ -&gt; llm                  (begin by asking LLM what to do)
 *    tools -&gt; llm                      (after tools, return to LLM to observe/continue)
 * - Conditional edges from 'llm':
 *    if shouldContinue() === 'tools'   =&gt; go to tools
 *    if shouldContinue() === '__end__' =&gt; END (finish run)
 */</span>
<span class="hljs-keyword">const</span> graph = <span class="hljs-keyword">new</span> StateGraph(MessagesAnnotation)
  .addNode(<span class="hljs-string">'llm'</span>, callModel)
  .addNode(<span class="hljs-string">'tools'</span>, toolNode)
  .addEdge(<span class="hljs-string">'__start__'</span>, <span class="hljs-string">'llm'</span>)
  .addEdge(<span class="hljs-string">'tools'</span>, <span class="hljs-string">'llm'</span>)
  .addConditionalEdges(<span class="hljs-string">'llm'</span>, shouldContinue, {
    <span class="hljs-attr">__end__</span>: END,
    <span class="hljs-attr">tools</span>: <span class="hljs-string">'tools'</span>,
  });

<span class="hljs-comment">/** -------------------------------
 * COMPILE
 * -------------------------------
 * - compile() turns the graph into an executable app.
 * - we pass the checkpointer so the app can persist conversation by thread_id.
 */</span>
<span class="hljs-keyword">const</span> app = graph.compile({ checkpointer });

<span class="hljs-comment">/** -------------------------------
 * CLI MAIN
 * -------------------------------
 * - thread_id identifies the conversation for the checkpointer.
 * - printGraph renders a PNG of the graph for docs/diagnostics.
 * - loop: read user input -&gt; run app.invoke -&gt; print final assistant message.
 */</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> config = { <span class="hljs-attr">configurable</span>: { <span class="hljs-attr">thread_id</span>: <span class="hljs-string">'1'</span> } };

  <span class="hljs-comment">// optional: export a diagram of the compiled graph</span>
  <span class="hljs-keyword">await</span> printGraph(app, <span class="hljs-string">'./customGraph.png'</span>);

  <span class="hljs-keyword">const</span> rl = readline.createInterface({ <span class="hljs-attr">input</span>: process.stdin, <span class="hljs-attr">output</span>: process.stdout });

  <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
    <span class="hljs-keyword">const</span> userInput = <span class="hljs-keyword">await</span> rl.question(<span class="hljs-string">'You: '</span>);
    <span class="hljs-keyword">if</span> (userInput === <span class="hljs-string">'/bye'</span>) <span class="hljs-keyword">break</span>;

    <span class="hljs-comment">// Minimal state input: start with the new user message.</span>
    <span class="hljs-comment">// The checkpointer loads previous context for this thread_id under the hood.</span>
    <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> app.invoke(
      { <span class="hljs-attr">messages</span>: [{ <span class="hljs-attr">role</span>: <span class="hljs-string">'user'</span>, <span class="hljs-attr">content</span>: userInput }] },
      config
    );

    <span class="hljs-keyword">const</span> final = result.messages[result.messages.length - <span class="hljs-number">1</span>];
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'AI:'</span>, <span class="hljs-keyword">typeof</span> final.content === <span class="hljs-string">'string'</span> ? final.content : <span class="hljs-built_in">JSON</span>.stringify(final.content));
  }

  rl.close();
}

main().catch(<span class="hljs-built_in">console</span>.error);
</code></pre>
<h3 id="heading-utilsjs"><code>utils.js</code></h3>
<pre><code class="lang-javascript"><span class="hljs-comment">// utils.js</span>
<span class="hljs-keyword">import</span> { writeFileSync } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:fs'</span>;

<span class="hljs-comment">/**
 * printGraph:
 * - gets a drawable graph from the compiled app
 * - renders Mermaid PNG
 * - writes it to disk
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printGraph</span>(<span class="hljs-params">agent, graphPath</span>) </span>{
  <span class="hljs-keyword">const</span> drawable = <span class="hljs-keyword">await</span> agent.getGraph();
  <span class="hljs-keyword">const</span> png = <span class="hljs-keyword">await</span> drawable.drawMermaidPng();
  <span class="hljs-keyword">const</span> buf = Buffer.from(<span class="hljs-keyword">await</span> png.arrayBuffer());
  writeFileSync(graphPath, buf);
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Building a Smart Personal Assistant with the ReAct Pattern and LangChain]]></title><description><![CDATA[How reasoning, memory, and custom tools turn large language models into truly intelligent agents.

1. Setting the Stage: Why Agents Need More Than Just a Brain
Large Language Models (LLMs) are like brilliant thinkers — they can reason, plan, and writ...]]></description><link>https://intro-generative-ai.hashnode.dev/building-a-smart-personal-assistant-with-the-react-pattern-and-langchain</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/building-a-smart-personal-assistant-with-the-react-pattern-and-langchain</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Fri, 10 Oct 2025 12:08:22 GMT</pubDate><content:encoded><![CDATA[<p><em>How reasoning, memory, and custom tools turn large language models into truly intelligent agents.</em></p>
<hr />
<h2 id="heading-1-setting-the-stage-why-agents-need-more-than-just-a-brain">1. Setting the Stage: Why Agents Need More Than Just a Brain</h2>
<p>Large Language Models (LLMs) are like brilliant thinkers — they can reason, plan, and write, but they don’t <em>do</em> anything on their own.<br />They need a way to <strong>interact with the world</strong> — to fetch information, remember past conversations, or call APIs.</p>
<p>That’s where <strong>agentic patterns</strong> come in.</p>
<p>An <strong>agent</strong> is an AI system that can:</p>
<ul>
<li><p><strong>Think</strong> (reason about what to do),</p>
</li>
<li><p><strong>Act</strong> (use tools or APIs),</p>
</li>
<li><p><strong>Observe</strong> (see what happened),</p>
</li>
<li><p>and <strong>Learn or adjust</strong> based on those observations.</p>
</li>
</ul>
<p>Among the many agent patterns, one of the most powerful and influential is the <strong>ReAct pattern</strong>.</p>
<hr />
<h2 id="heading-2-the-react-pattern-reasoning-acting">2. The ReAct Pattern — Reasoning + Acting</h2>
<p><strong>ReAct</strong> (short for <strong>Reason + Act</strong>) is a framework that allows an AI model to think through its steps while using external tools when needed.<br />It was introduced by <em>Yao et al. (2023)</em> in the paper <em>“ReAct: Synergizing Reasoning and Acting in Language Models.”</em></p>
<p>At its core, ReAct blends two abilities:</p>
<ul>
<li><p><strong>Chain-of-Thought Reasoning (CoT):</strong> letting the LLM “think out loud.”</p>
</li>
<li><p><strong>Action-Taking:</strong> allowing the LLM to perform real operations (search, calculate, look up data).</p>
</li>
</ul>
<p>Here’s how a ReAct loop typically works:</p>
<pre><code class="lang-javascript">Thought → Action → Observation → Thought → ... → Final Answer
</code></pre>
<p>For example:</p>
<blockquote>
<p>Thought: “I don’t know today’s weather.”<br />Action: “Search for current weather in London.”<br />Observation: “It’s 18°C and cloudy.”<br />Thought: “I now know the answer.”<br />Final Answer: “It’s 18°C and cloudy in London.”</p>
</blockquote>
<p>This loop repeats until the model feels confident enough to finalize an answer — or hits a limit to prevent endless reasoning.</p>
<hr />
<h2 id="heading-3-why-react-matters">3. Why ReAct Matters</h2>
<p>Before ReAct, most AI systems separated “thinking” and “doing.”<br />That meant:</p>
<ul>
<li><p>Models reasoned internally, but couldn’t access external data.</p>
</li>
<li><p>Tools or APIs worked independently, without intelligent context.</p>
</li>
</ul>
<p>ReAct merges both.<br />It turns a passive chatbot into an <strong>active problem solver</strong>.</p>
<p>Benefits include:</p>
<ul>
<li><p><strong>Real-world grounding:</strong> Uses live data sources.</p>
</li>
<li><p><strong>Transparency:</strong> You can read the reasoning steps.</p>
</li>
<li><p><strong>Adaptability:</strong> Handles new, unpredictable tasks dynamically.</p>
</li>
<li><p><strong>Accuracy:</strong> Reduces hallucination by checking facts through tools.</p>
</li>
</ul>
<hr />
<h2 id="heading-4-giving-agents-memory-short-term-and-long-term">4. Giving Agents Memory: Short-Term and Long-Term</h2>
<p>Even the best reasoning loop isn’t enough if the agent forgets everything.</p>
<p>Agents, like humans, need <strong>memory</strong>.</p>
<h3 id="heading-short-term-memory">🔹 Short-Term Memory</h3>
<p>This is like your working memory — it stores the immediate context of an ongoing conversation or session.<br />In LangChain, short-term memory helps the agent <strong>recall recent messages, previous tool outputs, or system instructions</strong>.</p>
<p>A <strong>checkpointer</strong> (like <code>MemorySaver</code> in LangGraph) can maintain this conversation history or reasoning trace, so each new step is informed by what just happened.</p>
<h3 id="heading-long-term-memory">🔹 Long-Term Memory</h3>
<p>Long-term memory goes beyond a single session.<br />It stores structured knowledge — like past projects, user preferences, or important facts — in databases or vector stores.<br />This allows the agent to <em>remember who you are</em>, or <em>refer back to previous work</em>, even days later.</p>
<hr />
<h2 id="heading-5-lets-build-a-personal-assistant-agent">5. Let’s Build a Personal Assistant Agent</h2>
<p>Now that we understand the ReAct pattern and memory, let’s bring it to life.</p>
<p>We’ll build a <strong>personal assistant</strong> that can:</p>
<ul>
<li><p>Search the web,</p>
</li>
<li><p>Fetch calendar events,</p>
</li>
<li><p>Maintain conversation history (short-term memory), and</p>
</li>
<li><p>Draw a graph of its internal workflow.</p>
</li>
</ul>
<p>We’ll use:</p>
<ul>
<li><p><strong>LangChain LangGraph</strong> for ReAct agent creation,</p>
</li>
<li><p><strong>TavilySearch</strong> as a prebuilt search tool, and</p>
</li>
<li><p>A <strong>custom calendar tool</strong> built with <code>@langchain/core/tools</code>.</p>
</li>
</ul>
<hr />
<h2 id="heading-6-setting-up-the-code">6. Setting Up the Code</h2>
<p>Here’s the full implementation:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { ChatGroq } <span class="hljs-keyword">from</span> <span class="hljs-string">"@langchain/groq"</span>;
<span class="hljs-keyword">import</span> { createReactAgent } <span class="hljs-keyword">from</span> <span class="hljs-string">"@langchain/langgraph/prebuilt"</span>;
<span class="hljs-keyword">import</span> { TavilySearch } <span class="hljs-keyword">from</span> <span class="hljs-string">"@langchain/tavily"</span>;
<span class="hljs-keyword">import</span> { tool } <span class="hljs-keyword">from</span> <span class="hljs-string">"@langchain/core/tools"</span>;
<span class="hljs-keyword">import</span> { z } <span class="hljs-keyword">from</span> <span class="hljs-string">"zod"</span>;
<span class="hljs-keyword">import</span> { writeFileSync } <span class="hljs-keyword">from</span> <span class="hljs-string">"node:fs"</span>;
<span class="hljs-keyword">import</span> readLine <span class="hljs-keyword">from</span> <span class="hljs-string">"node:readline/promises"</span>;
<span class="hljs-keyword">import</span> { MemorySaver } <span class="hljs-keyword">from</span> <span class="hljs-string">"@langchain/langgraph"</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// 1) Choose and configure the LLM that will do the reasoning.</span>
  <span class="hljs-comment">//    Here we use a Groq-hosted model and set temperature to 0 for deterministic outputs.</span>
  <span class="hljs-keyword">const</span> model = <span class="hljs-keyword">new</span> ChatGroq({
    <span class="hljs-attr">model</span>: <span class="hljs-string">"openai/gpt-oss-120b"</span>,
    <span class="hljs-attr">temperature</span>: <span class="hljs-number">0</span>
  });

  <span class="hljs-comment">// 2) Add a prebuilt tool: web search via Tavily.</span>
  <span class="hljs-comment">//    The agent can call this when it needs fresh information.</span>
  <span class="hljs-keyword">const</span> search = <span class="hljs-keyword">new</span> TavilySearch({
    <span class="hljs-attr">maxResults</span>: <span class="hljs-number">3</span>,
    <span class="hljs-attr">topic</span>: <span class="hljs-string">"general"</span>
  });

  <span class="hljs-comment">// 3) Define a custom tool: fetch calendar events.</span>
  <span class="hljs-comment">//    We wrap an async function with `tool()`, and validate inputs with Zod.</span>
  <span class="hljs-keyword">const</span> calendarEvents = tool(
    <span class="hljs-keyword">async</span> ({ query }) =&gt; {
      <span class="hljs-comment">// In a real app, call your calendar API here and return structured data.</span>
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">JSON</span>.stringify([
        {
          <span class="hljs-attr">title</span>: <span class="hljs-string">"meeting with harshal"</span>,
          <span class="hljs-attr">time</span>: <span class="hljs-string">"2 PM"</span>,
          <span class="hljs-attr">location</span>: <span class="hljs-string">"Google Meet"</span>
        }
      ]);
    },
    {
      <span class="hljs-attr">name</span>: <span class="hljs-string">"get-calendar-events"</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"Fetch calendar events for a given time/person query."</span>,
      <span class="hljs-attr">schema</span>: z.object({
        <span class="hljs-attr">query</span>: z
          .string()
          .describe(<span class="hljs-string">"Natural-language query with time/person to schedule or fetch a meeting"</span>)
      })
    }
  );

  <span class="hljs-comment">// 4) Short-term memory (checkpointer).</span>
  <span class="hljs-comment">//    This persists intermediate state across steps within a thread.</span>
  <span class="hljs-keyword">const</span> checkpointer = <span class="hljs-keyword">new</span> MemorySaver();

  <span class="hljs-comment">// 5) Create the ReAct agent.</span>
  <span class="hljs-comment">//    We pass the LLM, all available tools, and the checkpointer (for short-term memory).</span>
  <span class="hljs-keyword">const</span> agent = createReactAgent({
    <span class="hljs-attr">llm</span>: model,
    <span class="hljs-attr">tools</span>: [search, calendarEvents],
    checkpointer
  });

  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// 6) Simple CLI loop to chat with the agent.</span>
    <span class="hljs-keyword">const</span> rl = readLine.createInterface({
      <span class="hljs-attr">input</span>: process.stdin,
      <span class="hljs-attr">output</span>: process.stdout
    });

    <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
      <span class="hljs-keyword">const</span> userQuery = <span class="hljs-keyword">await</span> rl.question(<span class="hljs-string">"You: "</span>);
      <span class="hljs-keyword">if</span> (userQuery === <span class="hljs-string">"/bye"</span>) <span class="hljs-keyword">break</span>;

      <span class="hljs-comment">// 7) Invoke the agent with a system instruction and the user's message.</span>
      <span class="hljs-comment">//    `thread_id` tells the checkpointer which conversation to attach to.</span>
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> agent.invoke(
        {
          <span class="hljs-attr">messages</span>: [
            {
              <span class="hljs-attr">role</span>: <span class="hljs-string">"system"</span>,
              <span class="hljs-attr">content</span>: <span class="hljs-string">`You are a personal assistant. Use the provided tools if you lack information. Current date/time: <span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toUTCString()}</span>`</span>
            },
            { <span class="hljs-attr">role</span>: <span class="hljs-string">"user"</span>, <span class="hljs-attr">content</span>: userQuery }
          ]
        },
        {
          <span class="hljs-attr">configurable</span>: { <span class="hljs-attr">thread_id</span>: <span class="hljs-string">"1"</span> }
        }
      );

      <span class="hljs-comment">// 8) Print the agent's final message content.</span>
      <span class="hljs-built_in">console</span>.log(
        <span class="hljs-string">"Assistant:"</span>,
        result.messages[result.messages.length - <span class="hljs-number">1</span>].content
      );
    }

    rl.close();

    <span class="hljs-comment">// 9) Export a graph image of the workflow the agent can execute.</span>
    <span class="hljs-comment">//    Useful for visualizing tool-use and control flow.</span>
    <span class="hljs-keyword">const</span> drawableGraphState = <span class="hljs-keyword">await</span> agent.getGraphAsync();
    <span class="hljs-keyword">const</span> graphStateImage = <span class="hljs-keyword">await</span> drawableGraphState.drawMermaidPng();
    <span class="hljs-keyword">const</span> graphStateArrayBuffer = <span class="hljs-keyword">await</span> graphStateImage.arrayBuffer();

    <span class="hljs-keyword">const</span> filePath = <span class="hljs-string">"./graphState.png"</span>;
    writeFileSync(filePath, <span class="hljs-keyword">new</span> <span class="hljs-built_in">Uint8Array</span>(graphStateArrayBuffer));
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"An error occurred during agent invocation:"</span>, error);
  }
}

main();
</code></pre>
<h2 id="heading-what-each-part-does-the-why-behind-the-code">What each part does (the “why” behind the code)</h2>
<h3 id="heading-1-llm-selection">1) LLM selection</h3>
<ul>
<li><p><code>ChatGroq</code> is the model client. You’ve set <code>temperature: 0</code> to make outputs <strong>deterministic</strong> and more <strong>task-focused</strong>—great for a personal assistant.</p>
</li>
<li><p>The <code>model: "openai/gpt-oss-120b"</code> string is the model identifier used by Groq. Treat it like a <strong>model choice handle</strong>. If you swap models later, the agent logic stays the same.</p>
</li>
</ul>
<h3 id="heading-2-prebuilt-tool-tavilysearch">2) Prebuilt tool (TavilySearch)</h3>
<ul>
<li><p>ReAct agents shine when they can <strong>act</strong> (call tools) between reasoning steps.</p>
</li>
<li><p><code>TavilySearch</code> lets the agent fetch <strong>fresh information</strong> (news, facts, pages). You set <code>maxResults: 3</code> to keep token usage down.</p>
</li>
</ul>
<h3 id="heading-3-custom-tool-calendar">3) Custom tool (calendar)</h3>
<ul>
<li><p><code>tool()</code> wraps your function so the agent can discover and call it as an <strong>action</strong>.</p>
</li>
<li><p>The <strong>Zod schema</strong> defines and validates inputs. This is important because the LLM will generate the tool arguments in <strong>structured form</strong>—validation keeps things robust.</p>
</li>
<li><p>Right now it returns a <strong>JSON string</strong>. LangChain is fine with that, but returning an <strong>object/array</strong> is often nicer (the runtime will stringify as needed). Your current approach still works.</p>
</li>
</ul>
<h3 id="heading-4-memory-short-term">4) Memory (short-term)</h3>
<ul>
<li><p><code>MemorySaver</code> is a <strong>checkpointer</strong> that keeps state per <code>thread_id</code>.</p>
</li>
<li><p>This gives you <strong>short-term memory</strong>: the agent can look back at previous steps and tool results in the same thread.</p>
</li>
<li><p>For <strong>long-term memory</strong>, you’d typically add a vector store or database and retrieve relevant chunks into the context. (Not included here, but easy to extend later.)</p>
</li>
</ul>
<h3 id="heading-5-the-react-agent">5) The ReAct agent</h3>
<ul>
<li><p><code>createReactAgent</code> glues <strong>reasoning</strong> + <strong>acting</strong> + <strong>memory</strong> together.</p>
</li>
<li><p>It uses ReAct-style prompting behind the scenes: <strong>Thought → Action → Observation</strong> loops until it’s confident enough to answer or hits internal limits.</p>
</li>
</ul>
<h3 id="heading-68-the-cli-loop">6–8) The CLI loop</h3>
<ul>
<li><p>Simple REPL: user types a prompt, agent responds.</p>
</li>
<li><p>You set a <strong>system</strong> message to define role and policy (“use tools if needed”).</p>
</li>
<li><p><code>thread_id: "1"</code> makes all turns part of the same memory thread. Change it to start a new short-term memory context.</p>
</li>
</ul>
<h3 id="heading-9-graph-export">9) Graph export</h3>
<ul>
<li><p><code>getGraphAsync()</code> and <code>drawMermaidPng()</code> produce a <strong>Mermaid-based PNG</strong> of the workflow graph (the agent’s possible control-flow).</p>
</li>
<li><p>This is great for explaining or debugging how the agent <strong>could</strong> move between nodes/tools.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[ReAct Pattern]]></title><description><![CDATA[What Is a ReAct Agent?
A ReAct agent is an AI system that combines reasoning (thinking through problems step-by-step) with acting (using tools or taking actions).The term ReAct stands for Reasoning + Acting.
This approach was first introduced by Yao ...]]></description><link>https://intro-generative-ai.hashnode.dev/react-pattern</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/react-pattern</guid><category><![CDATA[reactpattern]]></category><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Fri, 10 Oct 2025 12:06:02 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-a-react-agent">What Is a ReAct Agent?</h2>
<p>A <strong>ReAct agent</strong> is an AI system that combines <strong>reasoning</strong> (thinking through problems step-by-step) with <strong>acting</strong> (using tools or taking actions).<br />The term <strong>ReAct</strong> stands for <strong>Reasoning + Acting</strong>.</p>
<p>This approach was first introduced by <strong>Yao et al. (2023)</strong> in the paper <em>“ReAct: Synergizing Reasoning and Acting in Language Models.”</em></p>
<p>In short:</p>
<ul>
<li><p>The <strong>LLM (Large Language Model)</strong> serves as the <strong>“brain”</strong> of the agent.</p>
</li>
<li><p>The agent uses the LLM’s reasoning ability to <strong>decide what to do</strong>, and then <strong>acts</strong> by using tools (like a search engine, API, or calculator).</p>
</li>
<li><p>The process repeats — the agent <strong>thinks</strong>, <strong>acts</strong>, observes what happened, and <strong>thinks again</strong> — until it reaches a final answer.</p>
</li>
</ul>
<p>This integration makes ReAct agents more powerful and flexible than older AI systems that separated thinking from doing.</p>
<hr />
<h2 id="heading-how-react-agents-work">How ReAct Agents Work</h2>
<p>The ReAct framework mimics <strong>how humans solve problems</strong>:</p>
<ol>
<li><p>We <strong>think</strong> (“What’s the next step?”)</p>
</li>
<li><p>We <strong>act</strong> (e.g., check something, calculate, or look it up)</p>
</li>
<li><p>We <strong>observe</strong> the result</p>
</li>
<li><p>We <strong>think again</strong> based on what we learned.</p>
</li>
</ol>
<h3 id="heading-example">Example:</h3>
<p>If you’re packing for a trip:</p>
<ul>
<li><p><strong>Thought:</strong> “What’s the weather like?”</p>
</li>
<li><p><strong>Action:</strong> Check the forecast.</p>
</li>
<li><p><strong>Observation:</strong> It’ll be cold.</p>
</li>
<li><p><strong>Thought:</strong> “I need warm clothes.”</p>
</li>
<li><p><strong>Action:</strong> Look in your closet.</p>
</li>
<li><p><strong>Observation:</strong> Clothes are in storage.</p>
</li>
<li><p><strong>Thought:</strong> “I’ll layer lighter clothes instead.”</p>
</li>
</ul>
<p>ReAct agents do exactly this — but with <strong>prompt engineering</strong> guiding them.</p>
<h3 id="heading-key-components">Key Components</h3>
<ul>
<li><p><strong>Thoughts (Reasoning):</strong> The LLM breaks the big problem into smaller parts using <em>chain-of-thought (CoT)</em> reasoning.</p>
</li>
<li><p><strong>Actions:</strong> The model performs tasks using tools — like calling an API, querying a database, or searching the web.</p>
</li>
<li><p><strong>Observations:</strong> The model reads results and decides what to do next.</p>
</li>
</ul>
<p>The process repeats until the model finds a satisfactory answer or reaches a stopping condition (like a loop limit).</p>
<hr />
<h2 id="heading-the-react-loop">The ReAct Loop</h2>
<p>The <strong>ReAct loop</strong> is the repeating cycle:</p>
<p><img src="https://www.ibm.com/content/dam/connectedassets-adobe-cms/worldwide-content/creative-assets/s-migr/ul/g/ca/0d/react.component.xl.ts=1759174567840.png/content/adobe-cms/us/en/think/topics/react-agent/jcr:content/root/table_of_contents/body-article-8/image" alt="Diagram of a react path" /></p>
<blockquote>
<p>Thought → Action → Observation → (repeat or end)</p>
</blockquote>
<p>The agent keeps looping through this cycle until:</p>
<ul>
<li><p>It’s confident in an answer, <strong>or</strong></p>
</li>
<li><p>It hits a <strong>max loop limit</strong> (to save tokens, time, or cost).</p>
</li>
</ul>
<p>This feedback loop lets the agent <strong>reason dynamically</strong>, adjusting to new data or unexpected results in real time.</p>
<hr />
<h2 id="heading-react-prompting">ReAct Prompting</h2>
<p><strong>ReAct prompting</strong> is a special technique to teach an LLM to follow the “think–act–observe” cycle.<br />The prompt tells the model:</p>
<ul>
<li><p>How to <strong>reason</strong> step by step (CoT reasoning)</p>
</li>
<li><p>What <strong>actions/tools</strong> it can use</p>
</li>
<li><p>How to <strong>make observations</strong> after each action</p>
</li>
<li><p>When to <strong>loop</strong> or <strong>stop</strong></p>
</li>
<li><p>How to <strong>output the final answer</strong></p>
</li>
</ul>
<p>A simple ReAct prompt format looks like this:</p>
<pre><code class="lang-javascript">Question: &lt;user query&gt;
Thought: &lt;model reasoning&gt;
Action: &lt;chosen tool&gt;
Action Input: &lt;input for that tool&gt;
Observation: &lt;tool result&gt;
... (repeats as needed)
Thought: I now know the final answer
Final Answer: &lt;output&gt;
</code></pre>
<p><strong>Example tools</strong> (as in LangChain’s built-in ReAct module):</p>
<ul>
<li><p><strong>Wikipedia:</strong> to look up facts</p>
</li>
<li><p><strong>DuckDuckGo Search:</strong> to check current events</p>
</li>
<li><p><strong>Calculator:</strong> to handle math problems</p>
</li>
</ul>
<p>This design lets the agent reason transparently while using external tools intelligently.</p>
<hr />
<h2 id="heading-benefits-of-react-agents">Benefits of ReAct Agents</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Quality</td><td>Explanation</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Versatility</strong></td><td>Can use many different tools/APIs with minimal setup.</td></tr>
<tr>
<td><strong>Adaptability</strong></td><td>Dynamically changes its strategy as conditions or information change.</td></tr>
<tr>
<td><strong>Explainability</strong></td><td>The step-by-step reasoning is visible and easy to debug.</td></tr>
<tr>
<td><strong>Accuracy</strong></td><td>Reduces “hallucinations” because it checks facts using real-world data sources (like RAG systems).</td></tr>
</tbody>
</table>
</div><p>ReAct’s mix of reasoning + tool use was a key milestone that led to more advanced AI agents, like <strong>Reflexion</strong> and modern <strong>reasoning models</strong>.</p>
<hr />
<h2 id="heading-react-agents-vs-function-calling">ReAct Agents vs. Function Calling</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td><strong>ReAct Agents</strong></td><td><strong>Function Calling</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Core idea</strong></td><td>Thinks step by step, decides when/how to use tools dynamically</td><td>Uses structured JSON calls to pre-defined functions</td></tr>
<tr>
<td><strong>Flexibility</strong></td><td>Very high — adapts to complex or uncertain tasks</td><td>More rigid — good for predictable workflows</td></tr>
<tr>
<td><strong>Speed/Cost</strong></td><td>Slower, more tokens used</td><td>Faster, fewer tokens</td></tr>
<tr>
<td><strong>Transparency</strong></td><td>Shows reasoning steps</td><td>Tool use may be opaque</td></tr>
<tr>
<td><strong>Best for</strong></td><td>Complex, dynamic problems</td><td>Simple, routine tasks</td></tr>
</tbody>
</table>
</div><p>In short:</p>
<ul>
<li><p><strong>Function calling</strong> is efficient for fixed, well-defined APIs.</p>
</li>
<li><p><strong>ReAct</strong> is better when the task requires <strong>adaptive reasoning</strong> or <strong>multiple uncertain steps</strong>.</p>
</li>
</ul>
<hr />
<h2 id="heading-building-react-agents">Building ReAct Agents</h2>
<p>You can build ReAct agents:</p>
<ul>
<li><p><strong>From scratch</strong> in Python or Javascript</p>
</li>
<li><p>Using frameworks like <strong>LangChain (LangGraph)</strong>, <strong>LlamaIndex</strong>, or <strong>BeeAI</strong>, which provide ready-made ReAct modules.</p>
</li>
</ul>
<p>These frameworks let developers easily plug in tools (APIs, search engines, calculators, etc.) and control the agent’s reasoning loop.</p>
<hr />
<h2 id="heading-summary">Summary</h2>
<p><strong>ReAct agents</strong> are AI systems that merge <strong>reasoning (thinking)</strong> with <strong>acting (tool use)</strong> in a feedback loop.<br />They:</p>
<ul>
<li><p>Think → Act → Observe → Repeat</p>
</li>
<li><p>Use <strong>chain-of-thought reasoning</strong> and <strong>external tools</strong></p>
</li>
<li><p>Are flexible, explainable, and accurate</p>
</li>
<li><p>Form the foundation of modern <strong>autonomous AI agents</strong></p>
</li>
</ul>
<p>In short:</p>
<blockquote>
<p>A <strong>ReAct agent</strong> is an intelligent AI framework that doesn’t just <em>think</em> — it <em>does</em>, <em>learns from results</em>, and <em>adapts</em> in real time.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Agentic AI and Its Frameworks: The Dawn of Intelligent Decision-Making]]></title><description><![CDATA[Imagine you’re chatting with ChatGPT.You type: “Hi.”It greets you back.Then you ask, “What’s the capital of India?” — and instantly it says, “Delhi.”
So far, so good.
But what happens when you say, “Do I have any meetings today?” or “Schedule a call ...]]></description><link>https://intro-generative-ai.hashnode.dev/agentic-ai-and-its-frameworks-the-dawn-of-intelligent-decision-making</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/agentic-ai-and-its-frameworks-the-dawn-of-intelligent-decision-making</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Thu, 09 Oct 2025 18:38:45 GMT</pubDate><content:encoded><![CDATA[<p>Imagine you’re chatting with ChatGPT.<br />You type: “Hi.”<br />It greets you back.<br />Then you ask, “What’s the capital of India?” — and instantly it says, “Delhi.”</p>
<p>So far, so good.</p>
<p>But what happens when you say, “Do I have any meetings today?” or “Schedule a call with John at 3 PM”?</p>
<p>You’ll probably get a polite but firm reply:</p>
<blockquote>
<p>“I don’t have access to your calendar.”</p>
</blockquote>
<p>That’s the moment we hit the limits of traditional AI assistants — <strong>they can talk, but they can’t act</strong>.<br />They don’t have access to your personal data, and they can’t take real-world actions on your behalf.</p>
<p>This is where the next evolution begins — <strong>Agentic AI</strong>.</p>
<hr />
<h2 id="heading-what-exactly-is-agentic-ai">What Exactly Is Agentic AI?</h2>
<p>To understand Agentic AI, let’s first break down the word <em>agent</em>.<br />An <strong>agent</strong> is something that can <strong>observe</strong>, <strong>decide</strong>, and <strong>act</strong>.</p>
<p>Traditional Large Language Models (LLMs) — like ChatGPT, Bard, or Claude — are powerful, but they’re bound by a few walls:</p>
<ol>
<li><p><strong>Knowledge Cutoff:</strong><br /> They only know what they were trained on — books, articles, code, and data up to a certain point (for example, till 2024).<br /> Anything after that? They’re in the dark.</p>
</li>
<li><p><strong>No Real-World Access:</strong><br /> They can’t look up today’s weather, check your calendar, or book you a flight — unless they have special tools.</p>
</li>
<li><p><strong>No Action Capability:</strong><br /> They can’t perform tasks — they just <em>suggest</em> what you should do.</p>
</li>
</ol>
<p>Agentic AI changes all that.</p>
<p>When an LLM is given the <strong>ability to make decisions</strong> and <strong>use external tools or APIs</strong> to perform actions, it becomes <strong>Agentic</strong> — capable of <em>reasoning</em>, <em>acting</em>, and <em>learning</em> like a mini digital being.</p>
<hr />
<h2 id="heading-a-simple-example">A Simple Example</h2>
<p>Let’s ask ChatGPT:</p>
<blockquote>
<p>“What’s the weather in Ahmedabad?”</p>
</blockquote>
<p>If the AI shows you real-time weather data — it just used a <strong>web search tool</strong> behind the scenes.<br />That tool call is what makes it <em>agentic</em>.</p>
<p>Here, the model didn’t just “answer.”<br />It <strong>decided</strong> it needed fresh data → <strong>called a tool</strong> → and <strong>gave you the result</strong>.<br />That’s <strong>decision-making in action</strong> — the core idea behind Agentic AI.</p>
<p>Behind the scenes, ChatGPT itself works as a <strong>smart AI agent</strong>, capable of understanding your query, deciding what to do next, and taking the right step — just like a digital assistant who knows when to Google, when to calculate, and when to just talk.</p>
<hr />
<h2 id="heading-why-do-we-need-agentic-frameworks">Why Do We Need Agentic Frameworks?</h2>
<p>Okay, now we know what Agentic AI is.<br />But how do we build one?</p>
<p>We could, in theory, wire everything manually — writing endless tool calls, loops, and API logic.<br />But that’s messy, error-prone, and hard to maintain.</p>
<p>That’s why developers use <strong>Agentic Frameworks</strong> — ready-made, <strong>battle-tested structures</strong> designed for production-grade AI systems.</p>
<p>These frameworks handle the boring stuff — error recovery, workflow control, memory, and state management — so that you can focus on <strong>what your agent does</strong>, not <strong>how it does it</strong>.</p>
<p>Among many, two names dominate the space:</p>
<ul>
<li><p><strong>LangChain</strong></p>
</li>
<li><p><strong>LangGraph</strong></p>
</li>
</ul>
<p>Let’s see how they differ — and how they work together.</p>
<hr />
<h2 id="heading-langchain-vs-langgraph-the-dynamic-duo">LangChain vs. LangGraph: The Dynamic Duo</h2>
<h3 id="heading-langchain-the-chain-builder">LangChain — The Chain Builder</h3>
<p>LangChain started as a utility library but has now evolved into a full company offering multiple AI tools and products — including LangGraph.</p>
<p>Think of LangChain as a <strong>workflow builder</strong>.<br />It helps you connect multiple steps (like Retrieve → Generate → Store → Respond) into a seamless <strong>chain</strong>.</p>
<p>Each step might involve:</p>
<ul>
<li><p>A vector database for retrieving context</p>
</li>
<li><p>A Large Language Model for generating text</p>
</li>
<li><p>A memory component for storing chat history</p>
</li>
<li><p>A final response generator for the user</p>
</li>
</ul>
<p>All these steps are connected like nodes in a flowchart — what we call a <strong>Directed Acyclic Graph (DAG)</strong>.</p>
<p>A DAG means your workflow flows in <strong>one direction only</strong> — from start → process → end.<br />It can’t loop back to a previous step.</p>
<p>That’s perfect for simple tasks, but the real world isn’t always that linear.<br />Sometimes, we need to <strong>loop</strong>, <strong>retry</strong>, or <strong>rethink</strong> decisions dynamically.</p>
<p>That’s where <strong>LangGraph</strong> comes in.</p>
<hr />
<h3 id="heading-langgraph-the-brain-with-loops">LangGraph — The Brain with Loops</h3>
<p>LangGraph takes the concept of LangChain further.<br />It still uses nodes and edges, but here’s the twist — <strong>loops are allowed</strong>.</p>
<p>Imagine a flowchart where the AI generates a draft answer, then checks:</p>
<blockquote>
<p>“Is this good enough?”</p>
</blockquote>
<p>If <strong>yes</strong>, the agent ends.<br />If <strong>no</strong>, it loops back and regenerates until it’s satisfied.</p>
<p>That’s <strong>LangGraph</strong> — dynamic, iterative, and much closer to how humans think.</p>
<p>In real-world use cases, this is a game changer.<br />Why? Because most intelligent systems need to reason, retry, and refine — not just follow a straight path.</p>
<p>LangGraph simplifies this complexity.<br />Each node can run an LLM, call tools, check conditions, or update memory — all while maintaining a <strong>shared state</strong> that every node can access.</p>
<h3 id="heading-explore-more-on-langgraph-with-below-article">Explore more on LangGraph with below article:</h3>
<p><a target="_blank" href="https://langchain-ai.github.io/langgraphjs/concepts/high_level/">https://langchain-ai.github.io/langgraphjs/concepts/high_level/</a></p>
]]></content:encoded></item><item><title><![CDATA[Tool Calling for LLMs]]></title><description><![CDATA[Imagine your LLM is a very smart friend with a great memory but no hands. It can think and plan, but it cannot touch the real world by itself. That’s where tool calling comes in. Tool calling gives your smart friend a set of buttons (tools) it can as...]]></description><link>https://intro-generative-ai.hashnode.dev/tool-calling-for-llms</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/tool-calling-for-llms</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Sun, 05 Oct 2025 10:28:16 GMT</pubDate><content:encoded><![CDATA[<p>Imagine your LLM is a very smart friend with a great memory but no hands. It can <strong>think</strong> and <strong>plan</strong>, but it cannot <strong>touch</strong> the real world by itself. That’s where <strong>tool calling</strong> comes in. Tool calling gives your smart friend a set of buttons (tools) it can ask you to press like “search the web,” “query this database,” or “create a calendar event.” You, or your program, press those buttons, bring back the results, and the LLM continues the conversation using that fresh data.</p>
<h2 id="heading-why-do-we-need-tool-calling">Why do we need tool calling?</h2>
<p>LLMs learn from a snapshot of data. This snapshot ends at a <strong>knowledge cutoff</strong> date. So if you ask, “When was iPhone 16 launched?”, a model that only knows up to earlier data might say, “There is no iPhone 16 yet,” because it simply doesn’t know the latest.</p>
<p>With tool calling, we give the model a <strong>web search tool</strong>. Now the model can decide: “Hmm, I might be out of date. Let me use the webSearch tool.” Your program performs that search, returns the live result, and the model answers with up-to-date information.</p>
<p>We can attach many tools, some of examples are:</p>
<ul>
<li><p><strong>Web search</strong> → for news and real-time facts</p>
</li>
<li><p><strong>Database</strong> → for inventory, users, orders</p>
</li>
<li><p><strong>Calendar</strong> → to check availability or create meetings</p>
</li>
<li><p><strong>Internal APIs</strong> → to place orders, generate reports, fetch metrics</p>
</li>
</ul>
<h2 id="heading-how-it-works">How it works?</h2>
<p>The LLM does <strong>not</strong> execute code. It <strong>proposes</strong> a tool call in a structured format (like JSON): “Call tool <code>webSearch</code> with <code>{ query: "…" }</code>.”<br />Your app (the <strong>tool runner</strong>) reads that proposal, <strong>runs the tool</strong>, collects the result, and <strong>feeds the result back</strong> to the LLM as a special “tool” message. The LLM then uses that result to finish the answer (or to ask for another tool call).</p>
<p>So the loop is:</p>
<ol>
<li><p>You send the <strong>conversation</strong> + <strong>tool definitions</strong> to the LLM.</p>
</li>
<li><p>The LLM either replies with a normal message <strong>or</strong> emits one or more <strong>tool calls</strong>.</p>
</li>
<li><p>Your code detects tool calls, <strong>executes</strong> them, then <strong>attaches their outputs</strong>.</p>
</li>
<li><p>You send those tool outputs back to the LLM.</p>
</li>
<li><p>The LLM produces the final, natural-language answer (or asks for more tools).</p>
</li>
</ol>
<hr />
<h2 id="heading-code-example">Code example</h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Groq <span class="hljs-keyword">from</span> <span class="hljs-string">"groq-sdk"</span>;
<span class="hljs-keyword">import</span> { tavily } <span class="hljs-keyword">from</span> <span class="hljs-string">"@tavily/core"</span>;

<span class="hljs-keyword">const</span> groq = <span class="hljs-keyword">new</span> Groq({ <span class="hljs-attr">apiKey</span>: process.env.GROQ_API_KEY });
<span class="hljs-keyword">const</span> tvly = tavily({ <span class="hljs-attr">apiKey</span>: process.env.TAVILY_API_KEY });

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> messages = [
    {
      <span class="hljs-attr">role</span>: <span class="hljs-string">"system"</span>,
      <span class="hljs-attr">content</span>: <span class="hljs-string">`You are a smart personal assistant who answers asked questions.
You have access to the following tools.

The current date and time is: <span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toLocaleString(<span class="hljs-string">"en-IN"</span>, {
    timeZone: <span class="hljs-string">"Asia/Kolkata"</span>,  
    dateStyle: <span class="hljs-string">"full"</span>,
    timeStyle: <span class="hljs-string">"long"</span>,
  }</span>)}

1. webSearch({query}: {query: string}) // Search the latest information and realtime data on the internet.`</span>,
    },
    {
      <span class="hljs-attr">role</span>: <span class="hljs-string">"user"</span>,
      <span class="hljs-attr">content</span>: <span class="hljs-string">"Today's weather in Ahmedabad?"</span>,
    },
  ];

  <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){
    <span class="hljs-keyword">const</span> completion = <span class="hljs-keyword">await</span> groq.chat.completions.create({
        <span class="hljs-attr">model</span>: <span class="hljs-string">"llama-3.3-70b-versatile"</span>,
        <span class="hljs-attr">temperature</span>: <span class="hljs-number">0</span>,
        messages,
        <span class="hljs-attr">tools</span>: [
          {
            <span class="hljs-attr">type</span>: <span class="hljs-string">"function"</span>,
            <span class="hljs-attr">function</span>: {
              <span class="hljs-attr">name</span>: <span class="hljs-string">"webSearch"</span>,
              <span class="hljs-attr">description</span>: <span class="hljs-string">"Search the latest information and realtime data on the internet."</span>,
              <span class="hljs-attr">parameters</span>: {
                <span class="hljs-attr">type</span>: <span class="hljs-string">"object"</span>,
                <span class="hljs-attr">properties</span>: {
                  <span class="hljs-attr">query</span>: {
                    <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span>,
                    <span class="hljs-attr">description</span>: <span class="hljs-string">"The search query to perform search on."</span>,
                  },
                },
                <span class="hljs-attr">required</span>: [<span class="hljs-string">"query"</span>],
              },
            },
          },
        ],
        <span class="hljs-attr">tool_choice</span>: <span class="hljs-string">"auto"</span>,
      });

      messages.push(completion.choices[<span class="hljs-number">0</span>].message)

      <span class="hljs-keyword">const</span> toolCalls = completion.choices[<span class="hljs-number">0</span>].message.tool_calls;

      <span class="hljs-keyword">if</span> (!toolCalls) {
        <span class="hljs-built_in">console</span>.log(completion.choices[<span class="hljs-number">0</span>].message.content)
        <span class="hljs-keyword">break</span>;
      }

      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> tool <span class="hljs-keyword">of</span> toolCalls) {
        <span class="hljs-keyword">const</span> functionName = tool.function.name;
        <span class="hljs-keyword">const</span> parameters = tool.function.arguments;

        <span class="hljs-keyword">if</span> (functionName === <span class="hljs-string">"webSearch"</span>) {
          <span class="hljs-keyword">const</span> toolResult = <span class="hljs-keyword">await</span> webSearch(<span class="hljs-built_in">JSON</span>.parse(parameters));

          messages.push({
            <span class="hljs-attr">tool_call_id</span>: tool.id,
            <span class="hljs-attr">role</span>: <span class="hljs-string">'tool'</span>,
            <span class="hljs-attr">name</span>: functionName,
            <span class="hljs-attr">content</span>: toolResult
          })
        }
  }
  }
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">webSearch</span>(<span class="hljs-params">{ query }</span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> tvly.search(query);
  <span class="hljs-keyword">const</span> finalResult = response.results.map(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> result.content).join(<span class="hljs-string">"\n\n"</span>);

  <span class="hljs-keyword">return</span> finalResult;
}

main();
</code></pre>
<p>Let’s walkthrough code and understand it.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Groq <span class="hljs-keyword">from</span> <span class="hljs-string">"groq-sdk"</span>;
<span class="hljs-keyword">import</span> { tavily } <span class="hljs-keyword">from</span> <span class="hljs-string">"@tavily/core"</span>;

<span class="hljs-keyword">const</span> groq = <span class="hljs-keyword">new</span> Groq({ <span class="hljs-attr">apiKey</span>: process.env.GROQ_API_KEY });
<span class="hljs-keyword">const</span> tvly = tavily({ <span class="hljs-attr">apiKey</span>: process.env.TAVILY_API_KEY });
</code></pre>
<ul>
<li>Set up SDKs. One for the LLM (Groq), one for the search tool (Tavily).</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> messages = [
  {
    <span class="hljs-attr">role</span>: <span class="hljs-string">"system"</span>,
    <span class="hljs-attr">content</span>: <span class="hljs-string">`You are a smart personal assistant...
The current date and time is: ... 
1. webSearch({query}...) // Search the latest information...`</span>,
  },
  { <span class="hljs-attr">role</span>: <span class="hljs-string">"user"</span>, <span class="hljs-attr">content</span>: <span class="hljs-string">"Today's wheather in ahemedabad?"</span> },
];
</code></pre>
<ul>
<li><p><strong>messages</strong> is the chat history.</p>
</li>
<li><p>The <strong>system</strong> message explains the role and lists available tools.</p>
</li>
<li><p>The <strong>user</strong> asks a question (with a few typos—no problem).</p>
</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> completion = <span class="hljs-keyword">await</span> groq.chat.completions.create({
  <span class="hljs-attr">model</span>: <span class="hljs-string">"llama-3.3-70b-versatile"</span>,
  <span class="hljs-attr">temperature</span>: <span class="hljs-number">0</span>,
  messages,
  <span class="hljs-attr">tools</span>: [
    {
      <span class="hljs-attr">type</span>: <span class="hljs-string">"function"</span>,
      <span class="hljs-attr">function</span>: {
        <span class="hljs-attr">name</span>: <span class="hljs-string">"webSearch"</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">"Search the latest information..."</span>,
        <span class="hljs-attr">parameters</span>: {
          <span class="hljs-attr">type</span>: <span class="hljs-string">"object"</span>,
          <span class="hljs-attr">properties</span>: {
            <span class="hljs-attr">query</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"The search query..."</span> },
          },
          <span class="hljs-attr">required</span>: [<span class="hljs-string">"query"</span>],
        },
      },
    },
  ],
  <span class="hljs-attr">tool_choice</span>: <span class="hljs-string">"auto"</span>,
});
</code></pre>
<ul>
<li><p>You send the conversation to the model <strong>plus</strong> a <strong>tool schema</strong> that describes <code>webSearch(query: string)</code>.</p>
</li>
<li><p><code>tool_choice: "auto"</code> tells the model:<br />  “You can choose to call a tool or not—up to you.”</p>
</li>
</ul>
<pre><code class="lang-js">messages.push(completion.choices[<span class="hljs-number">0</span>].message)
<span class="hljs-keyword">const</span> toolCalls = completion.choices[<span class="hljs-number">0</span>].message.tool_calls;
</code></pre>
<ul>
<li><p>You add the model’s message to the history.</p>
</li>
<li><p>If the model wants a tool, it will fill <code>tool_calls</code> with something like:<br />  <code>{ id, function: { name: "webSearch", arguments: "{...}" } }</code>.</p>
</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (!toolCalls) {
  <span class="hljs-built_in">console</span>.log(completion.choices[<span class="hljs-number">0</span>].message.content)
  <span class="hljs-keyword">break</span>;
}
</code></pre>
<ul>
<li>If there are <strong>no</strong> tool calls, the model already gave the final answer. Print it and stop.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> tool <span class="hljs-keyword">of</span> toolCalls) {
  <span class="hljs-keyword">const</span> functionName = tool.function.name;
  <span class="hljs-keyword">const</span> parameters = tool.function.arguments;

  <span class="hljs-keyword">if</span> (functionName === <span class="hljs-string">"webSearch"</span>) {
    <span class="hljs-keyword">const</span> toolResult = <span class="hljs-keyword">await</span> webSearch(<span class="hljs-built_in">JSON</span>.parse(parameters));
    messages.push({
      <span class="hljs-attr">tool_call_id</span>: tool.id,
      <span class="hljs-attr">role</span>: <span class="hljs-string">'tool'</span>,
      <span class="hljs-attr">name</span>: functionName,
      <span class="hljs-attr">content</span>: toolResult
    })
  }
}
</code></pre>
<ul>
<li><p>For each requested tool call:</p>
<ol>
<li><p>Parse the tool’s arguments.</p>
</li>
<li><p>Run your <strong>real</strong> function (<code>webSearch</code>).</p>
</li>
<li><p>Push the result back as a special <strong>tool message</strong> that references <code>tool_call_id</code>.</p>
</li>
</ol>
</li>
<li><p>After this push, your <code>while(true)</code> loop runs again. You call the model <strong>again</strong> with the updated <code>messages</code>, so it can <strong>read</strong> the tool output and produce the final answer (or ask for another tool).</p>
</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">webSearch</span>(<span class="hljs-params">{ query }</span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> tvly.search(query);
  <span class="hljs-keyword">const</span> finalResult = response.results.map(<span class="hljs-function"><span class="hljs-params">r</span> =&gt;</span> r.content).join(<span class="hljs-string">"\n\n"</span>);
  <span class="hljs-keyword">return</span> finalResult;
}
</code></pre>
<ul>
<li>Your tool implementation. It calls Tavily, merges snippets, and returns a text block to the LLM.</li>
</ul>
<h3 id="heading-whats-happening">What’s happening?</h3>
<ol>
<li><p>The model sees: “What’s today’s weather in Ahmedabad?”</p>
</li>
<li><p>It thinks: “I need live data → call <code>webSearch</code> with a query like <em>weather Ahmedabad today</em>.”</p>
</li>
<li><p>Your code runs <strong>Tavily</strong>, collects results, and returns them to the model.</p>
</li>
<li><p>The model reads those results and answers in simple language.</p>
</li>
</ol>
<hr />
<h2 id="heading-the-meaning-of-toolchoice-auto-and-the-none-option">The meaning of <code>tool_choice: "auto"</code> (and the “none” option)</h2>
<ul>
<li><p><code>tool_choice: "auto"</code>: The model decides when to call a tool. This is the most natural setting. It improves answers for fresh/unknown facts and avoids calling tools when not needed.</p>
</li>
<li><p><code>tool_choice: "none"</code> (you wrote “note”; I’m explaining the likely intent): Force <strong>no</strong> tool calls. Useful when you want a purely “brain-only” answer (drafting text, explaining concepts) and you know the model already has everything it needs.</p>
</li>
<li><p><strong>Force a specific tool</strong> (provider-specific syntax): Sometimes you can instruct: “Use exactly this tool now.” This is helpful for strict workflows (e.g., <em>always</em> check the calendar first).</p>
</li>
</ul>
<hr />
<h2 id="heading-how-we-pass-tools-and-attach-tool-responses">How we “pass tools” and “attach tool responses”</h2>
<ul>
<li><p><strong>Pass tools</strong>: You include a list of tool <strong>definitions</strong> (name, description, JSON schema) in the API call. You’re <em>not</em> passing function pointers; you’re passing <strong>contracts</strong> that explain <em>what arguments a tool expects</em>.</p>
</li>
<li><p><strong>Attach tool responses</strong>: After the model asks for a tool, you run it, then add a <code>role: "tool"</code> message that includes <code>tool_call_id</code>, <code>name</code>, and the <code>content</code> (the result). The model then treats that content like evidence and continues reasoning.</p>
</li>
</ul>
<hr />
<h2 id="heading-understanding-the-roles-in-messages">Understanding the Roles in <code>messages</code></h2>
<p>Every conversation has a <strong>role</strong>, which tells the model <em>who</em> is speaking and what context to follow:</p>
<ul>
<li><p><strong>system</strong> → the rules of the game. Sets instructions, personality, or constraints.<br />  Example: “You are a polite weather assistant who always answers in simple English.”</p>
</li>
<li><p><strong>user</strong> → the person asking the question.<br />  Example: “What’s the weather today in Ahmedabad?”</p>
</li>
<li><p><strong>assistant</strong> → the AI’s replies. The model generates this role automatically.<br />  Example: “It is sunny and 27°C in Ahmedabad.”</p>
</li>
<li><p><strong>tool</strong> → responses from external functions you called.<br />  Example: “Tool result: Weather API says 27°C, humidity 40%.”</p>
</li>
</ul>
<p>Think of this as <strong>actors in a play</strong>: system = director, user = audience, assistant = actor, tools = props.</p>
<hr />
<h2 id="heading-key-parameters-in-create">Key Parameters in <code>.create()</code></h2>
<p>Now let’s explain those famous fields (<code>temperature</code>, <code>top_p</code>, etc.) in plain English.</p>
<h3 id="heading-temperature"><code>temperature</code></h3>
<p>Controls how <strong>creative or random</strong> the model is.</p>
<ul>
<li><p>Low (0–0.2) → safe, predictable, accurate. Best for coding, math, and tool calls.</p>
</li>
<li><p>High (0.7–1.0) → more variety, storytelling, or creative text.</p>
</li>
</ul>
<blockquote>
<p>Example: Ask “Write a slogan for a coffee shop.”</p>
<ul>
<li><p>Temperature 0 → “Fresh coffee every morning.”</p>
</li>
<li><p>Temperature 0.9 → “Awaken your senses with a cup of magic!”</p>
</li>
</ul>
</blockquote>
<hr />
<h3 id="heading-topp-nucleus-sampling"><code>top_p</code> (nucleus sampling)</h3>
<p>Controls how much of the <strong>probability space</strong> the model considers.</p>
<ul>
<li><p><code>top_p = 1.0</code> → consider all possible words.</p>
</li>
<li><p><code>top_p = 0.9</code> → only keep the top 90% most likely words, ignore the rest.</p>
</li>
</ul>
<p>Usually, you use <strong>either</strong> <code>temperature</code> or <code>top_p</code>, not both.</p>
<hr />
<h3 id="heading-stop"><code>stop</code></h3>
<p>Tells the model <strong>where to stop generating text</strong>.</p>
<p>Example:</p>
<pre><code class="lang-javascript">stop: [<span class="hljs-string">"\nHuman:"</span>]
</code></pre>
<p>This makes the model stop whenever it sees <code>"\nHuman:"</code>. Useful if you want to cut output at certain markers.</p>
<hr />
<h3 id="heading-maxcompletiontokens"><code>max_completion_tokens</code></h3>
<p>The maximum number of tokens (words + pieces of words) the model can generate in one reply.</p>
<ul>
<li><p>Small value → shorter answers.</p>
</li>
<li><p>Large value → longer essays or detailed outputs.</p>
</li>
</ul>
<hr />
<h3 id="heading-presencepenalty"><code>presence_penalty</code></h3>
<p>Encourages the model to <strong>talk about new topics</strong> instead of repeating what’s already in the conversation.</p>
<ul>
<li><p>High presence penalty = more diverse, less repetitive.</p>
</li>
<li><p>Low (or 0) = model can repeat itself freely.</p>
</li>
</ul>
<hr />
<h3 id="heading-frequencypenalty"><code>frequency_penalty</code></h3>
<p>Reduces the chance of repeating the <strong>same words/phrases</strong> over and over.</p>
<ul>
<li><p>Example: Without penalty, it might say:<br />  “Yes, yes, yes, yes.”</p>
</li>
<li><p>With penalty, it tries to vary:<br />  “Yes, of course. Absolutely.”</p>
</li>
</ul>
<hr />
<p>So together:</p>
<ul>
<li><p><strong>temperature</strong> = creativity dial</p>
</li>
<li><p><strong>top_p</strong> = filter for word pool</p>
</li>
<li><p><strong>stop</strong> = cutoff point</p>
</li>
<li><p><strong>max_completion_tokens</strong> = response length limit</p>
</li>
<li><p><strong>presence_penalty</strong> = discourages repeating <em>ideas</em></p>
</li>
<li><p><strong>frequency_penalty</strong> = discourages repeating <em>words</em></p>
</li>
</ul>
<hr />
<h2 id="heading-structured-output-with-responseformat">Structured Output with <code>response_format</code></h2>
<p>Sometimes, you don’t just want plain text. You want the LLM to <strong>always return JSON</strong> that your code can parse safely. That’s where <code>response_format</code> comes in.</p>
<h3 id="heading-1-responseformat-type-jsonobject">1. <code>response_format: { type: "json_object" }</code></h3>
<p>This forces the model to return a <strong>valid JSON object</strong>.</p>
<p>Example:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"weather"</span>: <span class="hljs-string">"Sunny"</span>,
  <span class="hljs-string">"temperature"</span>: <span class="hljs-string">"27°C"</span>
}
</code></pre>
<p>👉 Good when you just want <em>any</em> JSON, but don’t care about exact shape.</p>
<hr />
<h3 id="heading-2-responseformat-type-jsonschema">2. <code>response_format: { type: "json_schema" }</code></h3>
<p>This is more strict. You give the model a <strong>schema</strong> (like a blueprint) of what fields are required, their types, and constraints. The model must follow it.</p>
<p>Example schema:</p>
<pre><code class="lang-javascript">response_format: {
  <span class="hljs-attr">type</span>: <span class="hljs-string">"json_schema"</span>,
  <span class="hljs-attr">schema</span>: {
    <span class="hljs-attr">type</span>: <span class="hljs-string">"object"</span>,
    <span class="hljs-attr">properties</span>: {
      <span class="hljs-attr">city</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span> },
      <span class="hljs-attr">temperature</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">"number"</span> },
      <span class="hljs-attr">condition</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">"string"</span> }
    },
    <span class="hljs-attr">required</span>: [<span class="hljs-string">"city"</span>, <span class="hljs-string">"temperature"</span>]
  }
}
</code></pre>
<p>Output (LLM must match this):</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"city"</span>: <span class="hljs-string">"Ahmedabad"</span>,
  <span class="hljs-string">"temperature"</span>: <span class="hljs-number">27</span>,
  <span class="hljs-string">"condition"</span>: <span class="hljs-string">"Sunny"</span>
}
</code></pre>
<p>This is <strong>super important</strong> when your app depends on predictable structure (like saving to a database or making API calls).</p>
<hr />
<h2 id="heading-one-minute-mental-model">One-minute mental model</h2>
<ul>
<li><p>LLM = <strong>brain</strong></p>
</li>
<li><p>Tools = <strong>hands</strong> (but only when <strong>you</strong> move them)</p>
</li>
<li><p>Tool calling = the <strong>conversation</strong> where the brain politely asks you to use certain hands, you do it, and then the brain continues with better knowledge.</p>
</li>
</ul>
<p>That’s the whole magic. Simple, powerful, and safe when you keep control.</p>
]]></content:encoded></item><item><title><![CDATA[Fundamental Concepts You Must Know Before Using LLMs]]></title><description><![CDATA[When people first start working with AI models, especially Large Language Models (LLMs), they often get overwhelmed by technical jargon. But here’s the truth: if you understand just four fundamental concepts—Tokens, Context, Context Window, and Infer...]]></description><link>https://intro-generative-ai.hashnode.dev/fundamental-concepts-you-must-know-before-using-llms</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/fundamental-concepts-you-must-know-before-using-llms</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Wed, 01 Oct 2025 18:49:45 GMT</pubDate><content:encoded><![CDATA[<p>When people first start working with AI models, especially <strong>Large Language Models (LLMs)</strong>, they often get overwhelmed by technical jargon. But here’s the truth: if you understand just <strong>four fundamental concepts</strong>—<strong>Tokens, Context, Context Window, and Inference</strong>—you’ll have the foundation to really understand how these models work.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759344481704/cbc44436-cf20-48df-a073-fd55b332d6ba.png" alt class="image--center mx-auto" /></p>
<p>Let’s break them down one by one.</p>
<hr />
<h2 id="heading-1-tokens-the-smallest-building-blocks">1. Tokens – The Smallest Building Blocks</h2>
<p>Think of a token as the <strong>LEGO block of language</strong>.</p>
<p>LLMs don’t directly understand human text like <em>“What is ChatGPT?”</em>. Instead, they break it down into <strong>tokens</strong>. A token can be:</p>
<ul>
<li><p>A whole word (like “what”)</p>
</li>
<li><p>A part of a word (like “chat” + “gpt”)</p>
</li>
<li><p>Or sometimes just punctuation (“?”)</p>
</li>
</ul>
<p>This process is called <strong>tokenization</strong>, and it’s done by a special component called a <strong>tokenizer</strong>. Each token is then mapped to a number (an integer), because LLMs understand numbers, not raw text.</p>
<p>Why tokens matter:</p>
<ul>
<li><p><strong>Pricing</strong> – When you use an AI API, pricing is usually based on tokens (e.g., $1 per 1M tokens). Both input and output tokens count separately.</p>
</li>
<li><p><strong>Efficiency</strong> – The fewer tokens your text uses, the cheaper and faster the processing.</p>
</li>
</ul>
<p>So, next time you hear <em>“token limit”</em>, just remember it’s about how many <strong>LEGO blocks of language</strong> the model can handle.</p>
<hr />
<h2 id="heading-2-context-the-models-understanding-of-your-input">2. Context – The Model’s Understanding of Your Input</h2>
<p>Imagine you’re explaining something to a friend. The way they respond depends on the <strong>context</strong>—what you’ve said before, what instructions you give, and any extra details.</p>
<p>For an LLM, <strong>context = everything the model uses to understand your request</strong>. This usually includes:</p>
<ul>
<li><p><strong>Your input / question</strong> → e.g., <em>“Summarize this document.”</em></p>
</li>
<li><p><strong>Instructions</strong> → how you want the answer (bullet points, formal, casual).</p>
</li>
<li><p><strong>Additional information</strong> → company data, documents, or references you provide.</p>
</li>
<li><p><strong>Message history</strong> → previous conversation turns, so the AI “remembers” the flow.</p>
</li>
</ul>
<p>Important: LLMs are <strong>stateless</strong>. They don’t truly remember past chats unless you provide that history again as context. That’s why chatbots pass message history in every request.</p>
<hr />
<h2 id="heading-3-context-window-the-memory-span-of-a-model">3. Context Window – The Memory Span of a Model</h2>
<p>The <strong>context window</strong> is the maximum number of tokens a model can “see” and use at once while generating an answer.</p>
<ul>
<li><p>A small context window → The model forgets older parts of the conversation.</p>
</li>
<li><p>A large context window → The model can keep track of long documents, history, and instructions without losing track.</p>
</li>
</ul>
<p>For example:</p>
<ul>
<li><p>GPT-3 had a context window of ~2,000 tokens.</p>
</li>
<li><p>GPT-4 can handle up to 128,000 tokens (almost a full book!).</p>
</li>
</ul>
<p>Choosing the right model often depends on your <strong>context needs</strong>. If your input is too large for the context window, the model may “forget” earlier details or start skipping parts.</p>
<hr />
<h2 id="heading-4-inference-the-act-of-thinking-and-responding">4. Inference – The Act of Thinking and Responding</h2>
<p>Finally, we come to <strong>inference</strong>.</p>
<p>Inference is the process where the LLM takes your input (in tokens), processes it through its trained neural network, and <strong>generates an output</strong>.</p>
<p>You can think of inference as:</p>
<ul>
<li><p>The <strong>“reasoning process”</strong> of the model.</p>
</li>
<li><p>The <strong>speed</strong> at which it responds. (Bigger models with more parameters may be slower, but smarter.)</p>
</li>
</ul>
<p>Every time you interact with ChatGPT, Bard, or Claude—you’re essentially running an <strong>inference request</strong>.</p>
<hr />
<h2 id="heading-wrapping-it-up">Wrapping It Up</h2>
<p>These four concepts may sound technical at first, but they’re actually quite intuitive:</p>
<ul>
<li><p><strong>Tokens</strong> → The words/parts of words broken into numbers.</p>
</li>
<li><p><strong>Context</strong> → The information the model uses to understand your request.</p>
</li>
<li><p><strong>Context Window</strong> → How much information the model can “remember” at once.</p>
</li>
<li><p><strong>Inference</strong> → The actual process of generating output.</p>
</li>
</ul>
<p>Once you get these basics, you’ll not only understand how LLMs work under the hood but also use them more effectively—saving cost, improving accuracy, and picking the right model for your needs.</p>
]]></content:encoded></item><item><title><![CDATA[AI Models and Their Capabilities]]></title><description><![CDATA[When people first step into the world of AI, they often make a common mistake: they treat all AI models as the same. For example, while building an agentic system, many simply pick whichever model they have access to and plug it in. But here’s the tr...]]></description><link>https://intro-generative-ai.hashnode.dev/ai-models-and-their-capabilities</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/ai-models-and-their-capabilities</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Wed, 01 Oct 2025 18:23:22 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759342987197/2ed0004a-e327-489a-8091-fbc8cfaad059.png" alt class="image--center mx-auto" /></p>
<p>When people first step into the world of AI, they often make a common mistake: they treat <strong>all AI models as the same</strong>. For example, while building an agentic system, many simply pick whichever model they have access to and plug it in. But here’s the truth—<strong>not every model is designed for every task</strong>.</p>
<p>Just like you wouldn’t use a sports car to plow a field, you shouldn’t use the wrong AI model for the wrong problem.</p>
<hr />
<h2 id="heading-why-so-many-models">Why So Many Models?</h2>
<p>At the core, AI models aren’t “magical” in themselves. They’re just <strong>neural networks trained on data for specific purposes</strong>. Depending on how they’re trained, some models are better at <strong>reasoning</strong>, while others are optimized for <strong>speed and efficiency</strong>.</p>
<p>That’s why the market has so many different AI models—each tuned for a unique use case.</p>
<hr />
<h2 id="heading-two-broad-categories-of-models">Two Broad Categories of Models</h2>
<h3 id="heading-1-reasoning-models">1. <strong>Reasoning Models</strong></h3>
<p>Think of these as the “deep thinkers” of AI.</p>
<ul>
<li><p>They don’t just spit out an answer instantly.</p>
</li>
<li><p>They go through a process of <strong>step-by-step reasoning</strong> or “chain of thought” before responding.</p>
</li>
<li><p>This makes them ideal for <strong>complex, critical tasks</strong> where accuracy and logical planning matter.</p>
</li>
</ul>
<p>Example: If you ask such a model to solve a multi-step math problem or plan a project timeline, it will carefully think it through instead of rushing.</p>
<p>Downside? They take a bit longer to generate results.</p>
<hr />
<h3 id="heading-2-gpt-like-models-fast-responders">2. <strong>GPT-like Models (Fast Responders)</strong></h3>
<p>These are the “sprinters” of AI.</p>
<ul>
<li><p>They prioritize <strong>speed</strong> over deep reasoning.</p>
</li>
<li><p>They generate output quickly without long internal deliberation.</p>
</li>
<li><p>Perfect for tasks where <strong>fast responses</strong> are more important than multi-step thinking.</p>
</li>
</ul>
<p>Example: Drafting emails, summarizing text, or quickly answering straightforward queries.</p>
<p>Downside? For <strong>critical decision-making tasks</strong>, they may give shallow or incorrect answers.</p>
<hr />
<p><strong>Important Note</strong>: These categories aren’t “official” standards. They’re a way to <em>understand</em> how different models behave. In reality, companies design models with different trade-offs depending on what they want to optimize—speed, accuracy, reasoning depth, or cost.</p>
<hr />
<h2 id="heading-big-vs-small-models">Big vs Small Models</h2>
<p>Another dimension is <strong>model size</strong>, often measured in <strong>parameters</strong> (the internal weights that the model learns during training).</p>
<ul>
<li><p><strong>Small Models</strong> (e.g., 8 billion parameters) → Faster, cheaper, but limited in intelligence. Great for lightweight tasks if paired with <strong>good prompting techniques</strong>.</p>
</li>
<li><p><strong>Large Models</strong> (hundreds of billions or even trillions of parameters) → More intelligent and context-aware, but heavier, slower, and more expensive to run.</p>
</li>
</ul>
<p>With clever prompting and fine-tuning, even smaller models can often deliver surprisingly good results at a fraction of the cost.</p>
<hr />
<h2 id="heading-which-model-should-you-use">Which Model Should You Use?</h2>
<p>There’s no universal “best” model—it depends entirely on your use case:</p>
<ul>
<li><p><strong>Critical, reasoning-heavy tasks</strong> → Go with reasoning models.</p>
</li>
<li><p><strong>Quick, repetitive tasks</strong> → GPT-like fast models are enough.</p>
</li>
<li><p><strong>Budget-sensitive use cases</strong> → Try smaller models with optimized prompting.</p>
</li>
<li><p><strong>Enterprise-grade applications</strong> → Large, advanced models might be worth the cost.</p>
</li>
</ul>
<hr />
<h2 id="heading-the-bottom-line">The Bottom Line</h2>
<p>AI models are like tools in a toolbox. Some are hammers, some are screwdrivers. If you try to use one tool for every job, you’ll only make a mess.</p>
<ul>
<li><p><strong>Reasoning Models</strong> → Accuracy &amp; depth.</p>
</li>
<li><p><strong>GPT-like Models</strong> → Speed &amp; efficiency.</p>
</li>
<li><p><strong>Small Models</strong> → Cost-effective with smart prompting.</p>
</li>
<li><p><strong>Large Models</strong> → High power, but resource-intensive.</p>
</li>
</ul>
<p>The real skill lies not in just knowing AI, but in <strong>choosing the right model for the right task</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction to LLM: The Brains Behind Generative AI]]></title><description><![CDATA[Before we dive into the colorful world of Generative AI—where machines create text, images, music, and even videos—we first need to understand one of its most important foundations: the LLM, or Large Language Model.

From Simple Predictions to True U...]]></description><link>https://intro-generative-ai.hashnode.dev/introduction-to-llm-the-brains-behind-generative-ai</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/introduction-to-llm-the-brains-behind-generative-ai</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Wed, 01 Oct 2025 17:04:19 GMT</pubDate><content:encoded><![CDATA[<p>Before we dive into the colorful world of Generative AI—where machines create text, images, music, and even videos—we first need to understand one of its most important foundations: the <strong>LLM</strong>, or <strong>Large Language Model</strong>.</p>
<hr />
<h2 id="heading-from-simple-predictions-to-true-understanding">From Simple Predictions to True Understanding</h2>
<p>Long before ChatGPT or Bard, there were models that could “generate” text. But they were nothing like today’s LLMs. Early systems were mostly <strong>statistical models</strong>, which predicted the next word based only on the previous word.</p>
<p>For example, if you typed <em>“I like to drink …”</em>, the model might predict <em>“water”</em> or <em>“coffee”</em> simply because those words often followed that phrase in the data it had seen.</p>
<p>But there were problems:</p>
<ul>
<li><p>Context was shallow → Models could only “look” at a few words behind.</p>
</li>
<li><p>Accuracy was low → Predictions often felt random or repetitive.</p>
</li>
<li><p>Memory was limited → They couldn’t hold on to long sentences or paragraphs.</p>
</li>
</ul>
<hr />
<h2 id="heading-enter-nlp-and-recurrent-models">Enter NLP and Recurrent Models</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759337384109/9e4a874a-6401-41d5-bbc0-6627acfa9e78.png" alt class="image--center mx-auto" /></p>
<p>To improve text generation, researchers started using <strong>NLP (Natural Language Processing)</strong> with techniques like <strong>Recurrent Neural Networks (RNNs)</strong>. These allowed models to handle sequences better—like remembering what was said a few words earlier.</p>
<p>But even RNNs had big limitations:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759337421703/0085d374-8642-4227-8555-a94835f0f291.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>They struggled with long-range dependencies (couldn’t remember words far back in the text).</p>
</li>
<li><p>Training was slow and complex.</p>
</li>
</ul>
<p>So while they were better, they still weren’t enough.</p>
<hr />
<h2 id="heading-2017-the-breakthrough-moment">2017: The Breakthrough Moment</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759337456101/1746a32d-d8c7-4a12-b5d6-4ce89c595f1a.png" alt class="image--center mx-auto" /></p>
<p>Everything changed in <strong>2017</strong>, when Google published a groundbreaking paper: <strong>“Attention Is All You Need.”</strong></p>
<p>This introduced a new architecture called the <strong>Transformer</strong>. Unlike earlier models, which read text word by word in sequence, Transformers use <strong>self-attention</strong>.</p>
<p>In simple terms: instead of just looking at the last word, a Transformer can look at <strong>all words in a sentence at the same time</strong> and figure out which ones are most important for predicting the next word.</p>
<p>This was a revolution because:</p>
<ul>
<li><p>It captured <strong>longer context</strong> → a paragraph, even pages, not just a few words.</p>
</li>
<li><p>It was faster and more efficient to train.</p>
</li>
<li><p>It scaled beautifully → the bigger the model, the smarter it got.</p>
</li>
</ul>
<hr />
<h2 id="heading-the-birth-of-llms">The Birth of LLMs</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759337476499/0e6c1d9f-bf1d-47ef-98e6-433b2136d66d.png" alt class="image--center mx-auto" /></p>
<p>Based on this Transformer architecture, researchers built models that were trained on <strong>massive datasets</strong>: books, websites, research papers, Wikipedia, and more.</p>
<p>The result? <strong>Large Language Models (LLMs)</strong>.</p>
<ul>
<li><p>These models have <strong>billions or even trillions of parameters</strong> (weights in their neural network).</p>
</li>
<li><p>Parameters are like the “memory” of the model—it’s what the model learns during training.</p>
</li>
<li><p>The more parameters, the more patterns it can capture, and the more powerful it becomes.</p>
</li>
</ul>
<hr />
<h2 id="heading-examples-of-todays-llms">Examples of Today’s LLMs</h2>
<p>Some of the most well-known LLMs include:</p>
<ul>
<li><p><strong>OpenAI’s GPT-4</strong> (the brain behind ChatGPT)</p>
</li>
<li><p><strong>Anthropic’s Claude</strong></p>
</li>
<li><p><strong>Google’s Gemini</strong></p>
</li>
<li><p><strong>Mistral</strong> and other open-source models</p>
</li>
</ul>
<p>Some are private, some are open-source, but all share the same Transformer DNA.</p>
<hr />
<h2 id="heading-so-what-does-an-llm-actually-do">So, What Does an LLM Actually Do?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759337662409/7ce75107-d80e-469c-9ffd-b45a22075bb1.png" alt class="image--center mx-auto" /></p>
<p>At its core, the job of an LLM is <strong>simple yet powerful</strong>:</p>
<ol>
<li><p><strong>You provide input</strong> (a prompt) → e.g., <em>“Who is the President of India?”</em></p>
</li>
<li><p><strong>The model processes it</strong> using its neural network and context understanding.</p>
</li>
<li><p><strong>It generates an output</strong> → <em>“Droupadi Murmu is the President of India.”</em></p>
</li>
</ol>
<p>That’s it. But when scaled to billions of parameters and trained on vast knowledge, this simple mechanism becomes the foundation for everything we call <strong>Generative AI</strong> today.</p>
<hr />
<h2 id="heading-why-it-matters">Why It Matters</h2>
<p>Without LLMs, there would be no ChatGPT writing stories, no AI assistants summarizing reports, and no educational bots answering your doubts.</p>
<p>LLMs are the <strong>engine</strong> that powers modern AI applications. They are not just statistical text predictors anymore—they are <strong>context-aware, knowledge-rich, and creative collaborators</strong>.</p>
<hr />
<p><strong>In short:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759337682144/ade289cf-4f14-4b65-9ec8-66a9d5c6dd62.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>LLMs = Large Language Models = neural networks trained on text to generate text.</p>
</li>
<li><p>Built on the <strong>Transformer architecture</strong> introduced in 2017.</p>
</li>
<li><p>They are the <strong>foundation of Generative AI</strong>, powering tools like ChatGPT, Bard, and Gemini.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[What is Generative AI? – The Creative Side of Artificial Intelligence]]></title><description><![CDATA[Imagine walking into an art gallery where every painting, sculpture, and piece of music was not created by humans but by machines. Sounds futuristic, right? Well, welcome to the world of Generative AI—a field of artificial intelligence that doesn’t j...]]></description><link>https://intro-generative-ai.hashnode.dev/what-is-generative-ai-the-creative-side-of-artificial-intelligence</link><guid isPermaLink="true">https://intro-generative-ai.hashnode.dev/what-is-generative-ai-the-creative-side-of-artificial-intelligence</guid><dc:creator><![CDATA[Harshal Chauhan]]></dc:creator><pubDate>Wed, 01 Oct 2025 16:09:59 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759334896714/a75b9022-eef9-4a21-9ccd-c33b702a0de8.png" alt class="image--center mx-auto" /></p>
<p>Imagine walking into an art gallery where every painting, sculpture, and piece of music was not created by humans but by machines. Sounds futuristic, right? Well, welcome to the world of <strong>Generative AI</strong>—a field of artificial intelligence that doesn’t just analyze data, it <em>creates</em>.</p>
<h3 id="heading-ai-more-than-just-classifiers">AI: More Than Just Classifiers</h3>
<p>Traditionally, when we thought of AI, we pictured systems that could classify or detect patterns. For example:</p>
<ul>
<li><p><strong>Spam detection in emails</strong> – Is this message spam or safe?</p>
</li>
<li><p><strong>Image classification</strong> – Is this a cat or a dog?</p>
</li>
</ul>
<p>This kind of AI is powerful, but limited. It looks at data and makes a decision. That’s where <strong>Generative AI</strong> steps in and changes the game.</p>
<h3 id="heading-the-rise-of-generative-ai">The Rise of Generative AI</h3>
<p>Generative AI, often called <em>Gen AI</em>, is a special class of AI that can <strong>generate new content</strong>. Instead of only classifying existing information, it creates fresh material text, images, audio, even video.</p>
<p>The magic lies in its training process. These models are trained on massive datasets, and then they learn patterns so well that they can produce content that feels similar to what they’ve seen yet still new.</p>
<h3 id="heading-examples-we-see-every-day">Examples We See Every Day</h3>
<ul>
<li><p><strong>ChatGPT</strong> → You type: <em>“Write me a story about a time-traveling chef”</em>. Within seconds, you get a creative, human-like story.</p>
</li>
<li><p><strong>DALL·E</strong> → You write: <em>“Draw a cat in astronaut gear floating on Mars”</em>. The AI paints the image for you.</p>
</li>
<li><p><strong>Sora (by OpenAI)</strong> → From just text, it generates full-blown videos.</p>
</li>
<li><p><strong>Text-to-Speech &amp; Voice Cloning</strong> → AI that doesn’t just read aloud but can mimic your favorite actor’s voice.</p>
</li>
<li><p><strong>Music Generation Models</strong> → Compose background scores, songs, or beats, all from simple text prompts.</p>
</li>
</ul>
<h3 id="heading-why-generative">Why “Generative”?</h3>
<p>The name says it all because this AI <strong>generates</strong>. Whether it’s words, visuals, sounds, or motion, generative AI goes beyond recognition. It creates something new, something we can interact with, something that feels <em>alive</em>.</p>
<h3 id="heading-the-bigger-picture">The Bigger Picture</h3>
<p>Generative AI is not just a cool party trick. It’s already transforming industries:</p>
<ul>
<li><p><strong>Education</strong> – Personalized learning material.</p>
</li>
<li><p><strong>Healthcare</strong> – Simulating proteins for drug discovery.</p>
</li>
<li><p><strong>Entertainment</strong> – Movies, music, and gaming experiences tailored on demand.</p>
</li>
<li><p><strong>Business</strong> – Automating reports, designs, and even marketing content.</p>
</li>
</ul>
<p>We are standing at the edge of a creative revolution where machines are not just calculators but collaborators.</p>
]]></content:encoded></item></channel></rss>