<?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[Prarabdha Srivastava]]></title><description><![CDATA[Prarabdha Srivastava]]></description><link>https://sriprarabdha.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 02 Sep 2026 05:57:18 GMT</lastBuildDate><atom:link href="https://sriprarabdha.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Build a Vector db from Scratch in c++]]></title><description><![CDATA[Vector databases are everywhere now.
Search, recommendation systems, retrieval-augmented generation (RAG), semantic similarity — almost every modern ML system quietly depends on fast nearest-neighbor search. And yet, for most of us, vector databases ...]]></description><link>https://sriprarabdha.hashnode.dev/build-a-vector-db-from-scratch-in-cpp</link><guid isPermaLink="true">https://sriprarabdha.hashnode.dev/build-a-vector-db-from-scratch-in-cpp</guid><category><![CDATA[Databases]]></category><category><![CDATA[AI]]></category><category><![CDATA[RAG ]]></category><dc:creator><![CDATA[Prarabdha Srivastava]]></dc:creator><pubDate>Tue, 06 Jan 2026 17:50:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767439206300/88229830-7344-4cbe-8f8e-8b7069667ae8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Vector databases are everywhere now.</p>
<p>Search, recommendation systems, retrieval-augmented generation (RAG), semantic similarity — almost every modern ML system quietly depends on fast nearest-neighbor search. And yet, for most of us, vector databases remain a black box. We use them, we tune a few parameters, but rarely stop to ask <em>why</em> they work the way they do — or <em>when</em> they stop working.</p>
<p>This project is my attempt to change that.</p>
<p>Instead of starting from a mature system or a clever approximation technique, I decided to rebuild a vector database <strong>from first principles</strong> in C++. The goal was not to compete with production-grade systems, but to understand the fundamentals: why certain designs work, where they break down, and what trade-offs they make between speed, accuracy, and complexity.</p>
<p>I start with the simplest possible baseline — an exact linear scan — and gradually layer in optimizations, SIMD instructions, multithreading, and tree-based indexing.</p>
<p>This blog documents that journey. It’s not a tutorial on “how to build the fastest vector database,” but a practical exploration of <strong>how vector search behaves on real hardware</strong> and <strong>why modern systems are designed the way they are</strong>.</p>
<p>If you want to dig deeper, experiment, or go through the full implementation, you can find the complete codebase here:<br />👉 <a target="_blank" href="https://github.com/SriPrarabdha/vector_db_from_scratch"><strong>github.com/SriPrarabdha/vector_db_from_scratch</strong></a></p>
<h1 id="heading-baseline-implementation-linear-scanhttpsgithubcomsriprarabdhavectordbfromscratch"><a target="_blank" href="https://github.com/SriPrarabdha/vector_db_from_scratch">Baseline Implementation (Linear Scan)</a></h1>
<p>Every optimization only makes sense if we clearly understand what we are optimizing <strong>against</strong>.<br />So before touching SIMD, threads, or tree structures, the project starts with the most boring solution possible: <strong>linear scan</strong>.</p>
<p>Given a query vector, we compute its distance to <strong>every single vector</strong> in the database and then pick the top-k closest ones. That’s it. No shortcuts, no pruning, no approximation.</p>
<p>At first glance, this feels obviously inefficient. But linear scan has one extremely important property: <strong>it is exact</strong>. Whatever result it gives is the ground truth. Every faster method we build later will be judged relative to this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767419637129/cc53d077-09c3-4ca9-8d2f-b6f9d7ee6ea6.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-how-linear-scan-is-actually-working-here">How linear scan is actually working here</h3>
<p>Assume we have <code>N</code> vectors, each of dimension <code>D</code>. For a single query:</p>
<ol>
<li><p>Take one stored vector.</p>
</li>
<li><p>Compute the distance to the query (L2 / Cosine distance).</p>
</li>
<li><p>Repeat for all <code>N</code> vectors.</p>
</li>
<li><p>Sort (or partially select) the closest <code>k</code>.</p>
</li>
</ol>
<p>The time complexity is simple and brutal: <strong>O(N × D)</strong> per query.</p>
<pre><code class="lang-cpp"><span class="hljs-comment">//square of euclidean distance</span>
<span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">l2_distance</span> <span class="hljs-params">(<span class="hljs-keyword">const</span> Vector&amp; a, <span class="hljs-keyword">const</span> Vector&amp; b)</span></span>{
    assert (a.dim == b.dim);

    <span class="hljs-keyword">float</span> sum = <span class="hljs-number">0.0f</span>;
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">dim_t</span> i = <span class="hljs-number">0</span>; i&lt;a.dim ; ++i){
        <span class="hljs-keyword">float</span> d = (a.data[i] - b.data[i]);

        sum += d*d;
    }

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

<span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">cosine_distance</span><span class="hljs-params">(<span class="hljs-keyword">const</span> Vector&amp; a, <span class="hljs-keyword">const</span> Vector&amp; b)</span></span>{
    assert (a.dim == b.dim);

    <span class="hljs-keyword">float</span> dot = <span class="hljs-number">0.0f</span>;
    <span class="hljs-keyword">float</span> na = <span class="hljs-number">0.0f</span>;
    <span class="hljs-keyword">float</span> nb = <span class="hljs-number">0.0f</span>;

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">dim_t</span> i = <span class="hljs-number">0</span> ; i&lt;a.dim ; ++i){
        dot += a.data[i] * b.data[i];
        na += a.data[i] * a.data[i];
        nb += b.data[i] * b.data[i];
    }

    <span class="hljs-keyword">if</span> (na == <span class="hljs-number">0.0f</span> || nb == <span class="hljs-number">0.0f</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">1.0f</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-number">1.0f</span> - (dot / (<span class="hljs-built_in">sqrt</span>(na) * <span class="hljs-built_in">sqrt</span>(nb)));
}
</code></pre>
<p>Now let’s use this vanilla implementation of l2_distance to implement our linear scan index. Refer <a target="_blank" href="https://github.com/SriPrarabdha/vector_db_from_scratch/blob/59ad3202dae1420dc9149dcb2855147c72a9ece0/indexes/linear_scan.cpp">here</a> to see the complete code implementing the Linear Scan Index class and other utility methods. Below is just the logic for the Search methods of the Linear Index Class.</p>
<pre><code class="lang-cpp"><span class="hljs-comment">// search in linear scan index</span>
<span class="hljs-function"><span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">pair</span>&lt;<span class="hljs-keyword">uint32_t</span> , <span class="hljs-keyword">float</span>&gt;&gt; <span class="hljs-title">LinearScanIndex::search</span><span class="hljs-params">(<span class="hljs-keyword">const</span> Vector&amp; query , <span class="hljs-keyword">size_t</span> k)</span> <span class="hljs-keyword">const</span> </span>{
    assert (query.dim == dim_);

    <span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">pair</span>&lt;<span class="hljs-keyword">uint32_t</span>, <span class="hljs-keyword">float</span>&gt;&gt; results;

    results.reserve(data_.size());

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">size_t_t</span> i = <span class="hljs-number">0</span>; i&lt;data_.size() ; ++i){
        <span class="hljs-keyword">dist_t</span> d = l2_distance(query , data_[i]);
        results.emplace_back(i, d);
    }

    <span class="hljs-keyword">if</span>(results.size() &gt; k){
        nth_element(results.begin() , 
                    results.begin() + k,
                    results.end() , 
                    [](<span class="hljs-keyword">auto</span>&amp; a , <span class="hljs-keyword">auto</span>&amp; b) {<span class="hljs-keyword">return</span> a.second &lt; b.second ;}
                );
        results.resize(k);
    }

    sort(results.begin() , results.end() , 
        [](<span class="hljs-keyword">auto</span>&amp; a , <span class="hljs-keyword">auto</span>&amp; b) {<span class="hljs-keyword">return</span> a.second &lt; b.second ;}
    );

    <span class="hljs-keyword">return</span> results;
}
</code></pre>
<h1 id="heading-lets-try-amp-optimize-this-linear-scan">Let’s try &amp; Optimize this Linear Scan</h1>
<p>At this point the algorithm is still exactly the same. We are still comparing the query against <strong>every</strong> vector. We are still computing the exact L2 distance.</p>
<p>The only thing that changes now is <strong>how efficiently the CPU is allowed to do the work</strong>.</p>
<h2 id="heading-doing-more-work-per-cpu-cycle-with-avx2">Doing more work, per CPU cycle with AVX2</h2>
<p>A modern CPU is not meant to process one floating-point number at a time. It has wide vector registers that can hold multiple values and operate on all of them in a single instruction. AVX2 gives us 256-bit registers, which means <strong>8 floats at once</strong>.</p>
<p>The idea behind AVX2 distance computation is simple:<br />instead of computing : (a_i - b_i)²</p>
<p>one dimension at a time, we compute <strong>eight of them together</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767604831476/7bd2ce1f-398a-4117-89df-496de15fa381.gif" alt class="image--center mx-auto" /></p>
<p>If you look at the <code>l2_avx2</code> routine, the core loop moves through the vectors in chunks of 8. <code>_mm256_loadu_ps</code> loads 8 floats from memory into a single register. One register holds part of vector <code>a</code>, another holds the corresponding part of vector <code>b</code>.</p>
<p>Once both are in registers, subtraction happens in parallel for all 8 values. Squaring is also done in parallel, and the results are accumulated into a running sum. This accumulation uses a fused multiply-add instruction, which computes : sum = diff² + sum</p>
<p>in one step. This is both faster and numerically stable. What is important here is that the <strong>inner loop becomes branch-free and dense</strong>. The CPU sees a tight stream of predictable instructions, which is exactly what it likes.</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">l2_avx2</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-keyword">float</span>* a, <span class="hljs-keyword">const</span> <span class="hljs-keyword">float</span>* b, <span class="hljs-keyword">size_t</span> dim)</span> </span>{
    __m256 sum = _mm256_setzero_ps();
    <span class="hljs-keyword">size_t</span> i = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">for</span> (; i + <span class="hljs-number">8</span> &lt;= dim; i += <span class="hljs-number">8</span>) {
        __m256 va = _mm256_loadu_ps(a + i);
        __m256 vb = _mm256_loadu_ps(b + i);
        __m256 diff = _mm256_sub_ps(va, vb);
        sum = _mm256_fmadd_ps(diff, diff, sum);
    }

    <span class="hljs-keyword">float</span> tmp[<span class="hljs-number">8</span>];
    _mm256_storeu_ps(tmp, sum);

    <span class="hljs-keyword">float</span> res = tmp[<span class="hljs-number">0</span>] + tmp[<span class="hljs-number">1</span>] + tmp[<span class="hljs-number">2</span>] + tmp[<span class="hljs-number">3</span>]
              + tmp[<span class="hljs-number">4</span>] + tmp[<span class="hljs-number">5</span>] + tmp[<span class="hljs-number">6</span>] + tmp[<span class="hljs-number">7</span>];

    <span class="hljs-keyword">for</span> (; i &lt; dim; ++i) {
        <span class="hljs-keyword">float</span> d = a[i] - b[i];
        res += d * d;
    }

    <span class="hljs-keyword">return</span> res;
}
</code></pre>
<p>Important Thing to Note : AVX does not do automatically is reduce a vector register to a single scalar. After the loop finishes, the sum still lives in a register holding 8 partial values.</p>
<p>To finish the distance computation, the register is stored back to memory and the 8 values are added together in normal scalar code. This step looks a bit ugly, but its cost is negligible compared to the main loop, especially for high-dimensional vectors.</p>
<p>Any leftover dimensions that do not fit into a multiple of 8 are handled at the end using a simple scalar loop. This ensures correctness for all dimensions without complicating the main vectorized loop. AVX2 does not change the number of arithmetic operations mathematically. It changes <strong>how many are executed per CPU cycle</strong>.</p>
<p>Instead of issuing one subtract and one multiply per dimension, the CPU now issues eight of them at once. Memory access also becomes more efficient because data is consumed in wide, predictable chunks.</p>
<blockquote>
<p>Below table is for the following setting : Dataset size : 100000 , Dimension : 1024 , Queries : 100 ,Top-K : 10</p>
</blockquote>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Implementation Type</strong></td><td><strong>Search Time</strong></td><td><strong>Queries Per Second (QPS)</strong></td><td><strong>instructions per cycle</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Scalar</strong></td><td>7.792 sec</td><td>12.83</td><td>0.97</td></tr>
<tr>
<td><strong>AVX2</strong></td><td>2.339 sec</td><td>42.74</td><td>1.04</td></tr>
</tbody>
</table>
</div><h2 id="heading-multi-threading-with-openmp">Multi-threading with OpenMP</h2>
<p>Once distance computation is fast, the next bottleneck becomes obvious: there are still many vectors to process.</p>
<p>Each query–vector distance is independent of every other one. So our mind very quickly asks the question can we use Multi-Threading . The easiest form of parallelism is using OpenMP at the outer level which allows the loop over database vectors to be split across CPU cores with almost no code changes.</p>
<p>The key lesson here is that multi-threading only helps <strong>after</strong> the inner loop is efficient. Parallelizing slow code just gives you slow code running on multiple cores.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;omp.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">pair</span>&lt;<span class="hljs-keyword">idx_t</span> , <span class="hljs-keyword">dist_t</span>&gt;&gt; <span class="hljs-title">LinearScanIndex::search</span><span class="hljs-params">(<span class="hljs-keyword">const</span> Vector&amp; query , <span class="hljs-keyword">size_t</span> k)</span> <span class="hljs-keyword">const</span> </span>{
    assert (query.dim == dim_);

    <span class="hljs-function"><span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">pair</span>&lt;<span class="hljs-keyword">idx_t</span>, <span class="hljs-keyword">dist_t</span>&gt;&gt; <span class="hljs-title">results</span><span class="hljs-params">(aos_.size())</span></span>;

    <span class="hljs-keyword">auto</span> compute = [&amp;] (<span class="hljs-keyword">idx_t</span> i) {
        <span class="hljs-keyword">dist_t</span> d = l2_dispatch(query , aos_[i] , cfg_.distance);
        results[i] = {i , d};
    };

    <span class="hljs-keyword">if</span>(cfg_.exec == ExecPolicy::OPENMP){
        <span class="hljs-meta">#<span class="hljs-meta-keyword">pragma</span> omp parralel for schedule(static)</span>
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">idx_t</span> i = <span class="hljs-number">0</span> ; i&lt;aos_.size() ; i++)compute(i);
    }<span class="hljs-keyword">else</span>{
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">idx_t</span> i = <span class="hljs-number">0</span> ; i&lt;aos_.size() ; i++) compute(i);
    }

    <span class="hljs-keyword">if</span>(results.size() &gt; k){
        nth_element(results.begin() , 
                    results.begin() + k,
                    results.end() , 
                    [](<span class="hljs-keyword">auto</span>&amp; a , <span class="hljs-keyword">auto</span>&amp; b) {<span class="hljs-keyword">return</span> a.second &lt; b.second ;}
                );
        results.resize(k);
    }

    sort(results.begin() , results.end() , 
        [](<span class="hljs-keyword">auto</span>&amp; a , <span class="hljs-keyword">auto</span>&amp; b) {<span class="hljs-keyword">return</span> a.second &lt; b.second ;}
    );

    <span class="hljs-keyword">return</span> results;
}
</code></pre>
<blockquote>
<p>Below table is for the following setting : Dataset size : 100000 , Dimension : 1024 , Queries : 100 ,Top-K : 10 , threads : 12</p>
</blockquote>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Implementation Type</strong></td><td><strong>Search Time</strong></td><td><strong>Queries Per Second (QPS)</strong></td><td><strong>instructions per cycle</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Scalar</strong></td><td>7.06 sec</td><td>14.52</td><td>0.97</td></tr>
<tr>
<td><strong>AVX2</strong></td><td>2.025 sec</td><td>44.07</td><td>1.05</td></tr>
</tbody>
</table>
</div><h2 id="heading-memory-layout-aos-vs-soa">Memory layout: AoS vs SoA</h2>
<p>Another optimization that matters more than expected is how vectors are stored in memory. With an array-of-structures layout, each vector is stored contiguously, but different vectors are interleaved. With a structure-of-arrays layout, each dimension is stored contiguously across all vectors.</p>
<p>For linear scan with AVX2, contiguous memory access is critical. When data is laid out in a cache-friendly way, the CPU can prefetch aggressively and avoid stalling on memory. A bad layout can completely erase the gains from SIMD and multithreading.</p>
<p>This is where theory meets reality: the same algorithm, the same math, but very different performance depending on layout.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767430737818/d9ea5983-b864-483e-8a1a-d12d182a454c.gif" alt class="image--center mx-auto" /></p>
<h1 id="heading-kd-tree">KD Tree</h1>
<p>After squeezing everything we could out of linear scan, the next logical step is to reduce the amount of work altogether. Instead of comparing the query against every vector, the goal now is to <strong>avoid computing distances that clearly cannot matter</strong>.</p>
<p>This is where KD-Trees come in. A KD-Tree recursively partitions the vector space by splitting along one dimension at a time. At each node, vectors are divided based on whether they lie on one side of a splitting value or the other. Over time, this creates a tree where nearby points in space tend to live close together in the structure.</p>
<p>The key idea is that if a region of space is far from the query, we can skip all vectors inside it without ever computing their distances.</p>
<h2 id="heading-building-the-tree">Building The Tree</h2>
<p>The KD-Tree is constructed top-down. At the root, all vectors are considered. A splitting axis is chosen based on the current depth, usually by cycling through dimensions. Along that axis, vectors are sorted and split at the median. This guarantees that the tree remains roughly balanced.</p>
<p>Each node stores the splitting axis, the split value, and pointers to its left and right children. Leaf nodes contain a small set of vectors and act as stopping points for recursion.</p>
<p>This construction cost is paid once, offline. The real question is whether it pays off during search.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767604199763/47d08f8c-6ec6-4a11-a0b6-68a864ed8c87.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-querying-the-tree">Querying the Tree</h2>
<p>Searching the KD-Tree starts by descending into the subtree that contains the query point. This is the “greedy” path, following the side of the split where the query lies.</p>
<p>Once a leaf is reached, distances to its vectors are computed and the current best neighbors are updated. Then comes the crucial part: <strong>backtracking</strong>.</p>
<p>When backtracking, the algorithm checks whether the other side of a split could possibly contain a closer neighbor than the current best. This decision is made using geometry. If the distance from the query to the splitting plane is larger than the worst distance in the current top-k set, the entire subtree can be safely pruned.</p>
<p>This pruning is what makes KD-Trees fast in low dimensions. Large parts of the dataset are never touched.</p>
<h2 id="heading-the-curse-of-dimensionality-shows-up">The curse of Dimensionality Shows up</h2>
<p>As dimensionality increases, something interesting — and slightly depressing — happens.</p>
<p>Distances become less informative. Points start to look equally far from the query in all directions. The distance to the splitting plane rarely exceeds the current best distance, which means pruning almost never triggers.</p>
<p>In high dimensions, the KD-Tree ends up visiting most of the nodes. At that point, the search degenerates back into something very close to linear scan, with extra overhead from recursion and tree traversal.</p>
<blockquote>
<p>Below table is for the following setting : Dataset size : 100000 , Dimension , Queries : 1 ,Top-K : 10</p>
</blockquote>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>dimension</strong></td><td><strong>linear Search Time</strong></td><td><strong>kd_tree Search Time</strong></td><td><strong>Visited Nodes</strong></td><td><strong>Pruned Branches</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>4</strong></td><td>2.15 ms</td><td>0.088 ms</td><td>376</td><td>129</td></tr>
<tr>
<td><strong>8</strong></td><td>2.74 ms</td><td>1.32 ms</td><td>8982</td><td>3432</td></tr>
<tr>
<td><strong>32</strong></td><td>5.59 ms</td><td>35.75 ms</td><td>100000</td><td>0</td></tr>
<tr>
<td><strong>128</strong></td><td>17.11 ms</td><td>64.73 ms</td><td>100000</td><td>0</td></tr>
<tr>
<td><strong>1024</strong></td><td>158.299 ms</td><td>188.459 ms</td><td>100000</td><td>0</td></tr>
</tbody>
</table>
</div><p>This is not a bug. It is a fundamental limitation . Implementing KD-Trees makes this painfully clear in practice, not just in theory.</p>
]]></content:encoded></item><item><title><![CDATA[LangGraph for Beginners: A new way to build AI Agents]]></title><description><![CDATA[Introduction
LangGraph is built on top of LangChain. One of the common patterns we see when people are creating more complex LLM applications is the introduction of cycles into the runtime. These cycles often use the LLM to reason about what to do ne...]]></description><link>https://sriprarabdha.hashnode.dev/langgraph-for-beginners-a-new-way-to-build-ai-agents</link><guid isPermaLink="true">https://sriprarabdha.hashnode.dev/langgraph-for-beginners-a-new-way-to-build-ai-agents</guid><category><![CDATA[AI]]></category><category><![CDATA[langchain]]></category><category><![CDATA[LLM's ]]></category><category><![CDATA[genai]]></category><dc:creator><![CDATA[Prarabdha Srivastava]]></dc:creator><pubDate>Mon, 08 Apr 2024 18:31:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712589037652/411c5ab7-dffa-404d-b547-4eac89b834e5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p><a target="_blank" href="https://github.com/langchain-ai/langgraph?ref=blog.langchain.dev">LangGraph</a> is built on top of LangChain. One of the common patterns we see when people are creating more complex LLM applications is the introduction of cycles into the runtime. These cycles often use the LLM to <em>reason</em> about what to do next in the cycle. A big unlock of LLMs is the ability to use them for these reasoning tasks. This can essentially be thought of as running an LLM in a for-loop. These types of systems are often called agents.</p>
<p>It adds new value primarily through the introduction of an easy way to create cyclical graphs. This is often useful when creating agent runtimes.</p>
<p>Don't worry if this all seems very daunting (it was the same for me😨 not a long time ago). We will break down how this state-of-the-art library works and how we can use it to make amazing AI Agents.</p>
<h2 id="heading-laggraph-level-1">LagGraph: Level 1</h2>
<p>Basic Components in the LangGraph Workflow:</p>
<ol>
<li><p><strong>Node</strong> - Think these node are part of a graph and they just call a function on the input they have and pass the output. Nothing else</p>
</li>
<li><p><strong>Edge</strong> - Like any graph it is the connection between any 2 node where output of one node is passed as input to the second node</p>
</li>
<li><p><strong>Entry_Point</strong> - It's just a node which gets the initial user prompt as it's input</p>
</li>
<li><p><strong>Finish_Point</strong> - It's also just a node that gives the output to the user</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712589427756/0c0c0350-ca46-4bc6-8e51-3fadd2ab86cd.png" alt class="image--center mx-auto" /></p>
<p>The above illustration is an example of the simplest graph where we can see node 1,2 are just calling function 1,2. And the output of node 1 or function call 1 is a input for the node 2/ function call 2</p>
<blockquote>
<p>Define Nodes (aka functions) --&gt; Define edges between Nodes --&gt; Define Entry Point --&gt; Define Finish Point</p>
</blockquote>
<p>Also node 1 acts as a starting point as it gets the initial user prompt as input. And node 2 is the Finish_Point as it's output is the Graph Output to the user.</p>
<p>Now let's try to code this out step by step. First, let's install all the dependencies for this project</p>
<pre><code class="lang-bash">pip install langchain-openai langgraph python-dotenv
</code></pre>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">function1</span>(<span class="hljs-params">input1:str</span>)-&gt;str:</span>
    <span class="hljs-keyword">return</span> input1 + <span class="hljs-string">" Hi"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">function2</span>(<span class="hljs-params">input2:str</span>) -&gt; str:</span>
    <span class="hljs-keyword">return</span> input2+ <span class="hljs-string">" There"</span>
</code></pre>
<p>The above code snippet defines 2 very basic functions. 'Function1' just adds "Hi" to it's input and returns it. And 'Function2' just adds "There" to its input and returns it.</p>
<p>Now the JUICY Part:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langgraph.graph <span class="hljs-keyword">import</span> Graph

Workflow = Graph()

Workflow.add_node(<span class="hljs-string">"node_1"</span>, function1)
Workflow.add_node(<span class="hljs-string">"node_2"</span>, function2)

Workflow.add_edge(<span class="hljs-string">'node_1'</span>, <span class="hljs-string">'node_2'</span>)

Workflow.set_entry_point(<span class="hljs-string">"node_1"</span>)
Workflow.set_finish_point(<span class="hljs-string">"node_2"</span>)

app = Workflow.compile()
</code></pre>
<p>Just like discussed before we set up 'function1' as "node1" and 'function2' as "node2". Add an edge between the 2 nodes. Set "node1" as entry point and "node2" as the finish point. And that's it. This is the main ideology behind LangGraph. And now we can use this exact same method to build the strongest AI Agent.</p>
<p>Now run this agent on the given user prompt</p>
<pre><code class="lang-python">app.invoke(<span class="hljs-string">"hello"</span>)
</code></pre>
<pre><code class="lang-bash"><span class="hljs-string">'hello Hi There'</span>
</code></pre>
<p>And that's all it takes to build with LangGraph😎</p>
<h2 id="heading-langgraph-level-2">LangGraph: Level 2</h2>
<p>Now that we have seen the basics of LangGraph let's make our Workflow a little more useful by adding LLM call</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712592518734/b3b79f5d-e527-4257-b1ed-86c3d1f16d49.png" alt class="image--center mx-auto" /></p>
<p>This is a simple code snippet using Langchain to use chat models of openai</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langchain_openai <span class="hljs-keyword">import</span> ChatOpenAI

model = ChatOpenAI(temperature=<span class="hljs-number">0.8</span>)

model.invoke(<span class="hljs-string">"Hey there"</span>).content
</code></pre>
<pre><code class="lang-bash"><span class="hljs-string">'Hello! How can I assist you today?'</span>
</code></pre>
<p>Now we just have to modify our functions to handle calling of a llm model</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func1</span>(<span class="hljs-params">input1: str</span>)-&gt;str:</span>
    <span class="hljs-keyword">return</span> model.invoke(input1).content

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func2</span>(<span class="hljs-params">input2: str</span>)-&gt;str:</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Agents says:"</span> + input2
</code></pre>
<p>Now just follow the previous Workflow</p>
<p>Define Nodes (aka functions) --&gt; Define edges between Nodes --&gt; Define Entry Point --&gt; Define Finish Point</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langgraph.graph <span class="hljs-keyword">import</span> Graph

Workflow = Graph()

Workflow.add_node(<span class="hljs-string">"node_1"</span>, func1)
Workflow.add_node(<span class="hljs-string">"node_2"</span>, func2)

Workflow.add_edge(<span class="hljs-string">'node_1'</span>, <span class="hljs-string">'node_2'</span>)

Workflow.set_entry_point(<span class="hljs-string">"node_1"</span>)
Workflow.set_finish_point(<span class="hljs-string">"node_2"</span>)

app = Workflow.compile()
</code></pre>
<p>And now with everything set up run our LangGraph Agent</p>
<pre><code class="lang-python">app.invoke(<span class="hljs-string">"aaj date kya h?"</span>)
</code></pre>
<pre><code class="lang-bash"><span class="hljs-string">'Agents says: Maine Internet ki permission nahi hai, isliye main aapko current date and time provide nahi kar sakti. Aap apne device ya kisi aur source se current date aur time pata kar sakte hain.'</span>
</code></pre>
<h2 id="heading-langgraph-level-3">LangGraph: Level 3</h2>
<p>Now that we have added LLM function calling to our LangGraph Agent there is just one thing left to make an amazing AI Agent i.e. Tools</p>
<p>Tools gives us extraordinary power by providing some extra information that the agent needs and solve any complex problem. Here we will be using 'OpenWeatherMap' API to get the weather of any city using our Agent</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712592536395/71fb351f-1174-446b-b6a2-b253ad7d8022.png" alt class="image--center mx-auto" /></p>
<p>Visit this link to make an account with Open Weather Map org and you will get your API Key without the need to use your Credit Card. Now let's go through the code to use its Langchain wrapper and the weather report of any city</p>
<pre><code class="lang-bash">pip install pyowm
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langchain_community.utilities <span class="hljs-keyword">import</span> OpenWeatherMapAPIWrapper
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">import</span> os

load_dotenv()

os.environ[<span class="hljs-string">"OPENWEATHERMAP_API_KEY"</span>] = os.environ.get(<span class="hljs-string">"OPENWEATHERMAP_API_KEY"</span>)

weather = OpenWeatherMapAPIWrapper()

weather_data = weather.run(<span class="hljs-string">"New Delhi"</span>)
print(weather_data)
</code></pre>
<pre><code class="lang-bash">In New Delhi, the current weather is as follows:
Detailed status: haze
Wind speed: 2.57 m/s, direction: 300°
Humidity: 18%
Temperature: 
  - Current: 33.09°C
  - High: 33.09°C
  - Low: 33.09°C
  - Feels like: 30.9°C
Rain: {}
Heat index: None
Cloud cover: 0%
</code></pre>
<p>Now we have to modify our 'function1' in such a way that given any prompt the LLM call output just contains the name of the city . And 'function2' just picks the name of city generated before and uses <em>OpenWeatherMapAPIWrapper()</em> to get the weather report for that city</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">function1</span>(<span class="hljs-params">prompt: str</span>)-&gt;str:</span>
    complete_prompt = <span class="hljs-string">f"Your task is to provide only the city name based on the user query. Nothing more, just the city name mentioned. Following is the user query: <span class="hljs-subst">{prompt}</span>"</span>
    <span class="hljs-keyword">return</span> model.invoke(complete_prompt).content

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">function2</span>(<span class="hljs-params">input1: str</span>)-&gt;str:</span>
    <span class="hljs-keyword">return</span> weather.run(input1)
</code></pre>
<p>Now let's compile our functions into the nodes of our agents and invoke our LangGraph Agent</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langgraph.graph <span class="hljs-keyword">import</span> Graph

Workflow = Graph()

Workflow.add_node(<span class="hljs-string">"agent"</span>, function1)
Workflow.add_node(<span class="hljs-string">"tool"</span>, function2)

Workflow.add_edge(<span class="hljs-string">'agent'</span>, <span class="hljs-string">'tool'</span>)

Workflow.set_entry_point(<span class="hljs-string">"agent"</span>)
Workflow.set_finish_point(<span class="hljs-string">"tool"</span>)

app = Workflow.compile()
app.invoke(<span class="hljs-string">"What is the weather right now in Kanpur"</span>)
</code></pre>
<pre><code class="lang-bash"><span class="hljs-string">'In Kanpur, the current weather is as follows:\nDetailed status: clear sky\nWind speed: 6.4 m/s, direction: 305°\nHumidity: 6%\nTemperature: \n  - Current: 38.78°C\n  - High: 38.78°C\n  - Low: 38.78°C\n  - Feels like: 35.41°C\nRain: {}\nHeat index: None\nCloud cover: 0%'</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you made it so far Private. You Deserve it!!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712593985181/dc6cbaec-1228-44c6-9311-d943593c740f.gif" alt class="image--center mx-auto" /></p>
<p>All jokes apart this covers everything there is to the basics of LangGraph. Now go on and build some amazing AI Agents</p>
<p>In the upcoming blogs, we will be covering more advanced concepts of LangGraph</p>
]]></content:encoded></item><item><title><![CDATA[Transformers United : Guide to Fine Tuning your model]]></title><description><![CDATA[Introduction
In this series, we will be making a discord bot that talks like your favorite character. We will first learn how to collect our own data, Fine-Tune a Transformer Model on this custom data, use this model as an inference API and finally d...]]></description><link>https://sriprarabdha.hashnode.dev/transformers-united</link><guid isPermaLink="true">https://sriprarabdha.hashnode.dev/transformers-united</guid><category><![CDATA[nlp]]></category><category><![CDATA[AI]]></category><category><![CDATA[transformers]]></category><category><![CDATA[WeMakeDevs]]></category><dc:creator><![CDATA[Prarabdha Srivastava]]></dc:creator><pubDate>Tue, 27 Dec 2022 15:29:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1672121643038/aab3991d-132b-492c-ab6b-c66c53a10c92.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>In this series, we will be making a discord bot that talks like your favorite character. We will first learn how to collect our own data, <strong>Fine-Tune</strong> a Transformer Model on this custom data, use this model as an <strong>inference API</strong> and finally deploy it as a discord Bot that you can play around with and show off to your friends!</p>
<p>Inspired by one of my favorite sci-fi shows Rick and Morty we will be making a Rick chatbot. But you can do this for any character and bring them to life</p>
<p>In this Part 2 we will be seeing the Basic theory of the <strong>Transformer Architecture</strong> and use the dataset that we made in <a target="_blank" href="https://sriprarabdha.hashnode.dev/turning-your-favorite-characters-lines-into-a-dataset-a-web-scraping-guide">Part 1</a> to fine-tune a Transformer Model and deploy this model onto Hugging Face🤗</p>
<h1 id="heading-but-why-transformer">But Why Transformer</h1>
<p><strong>The famous paper “Attention is all you need” in 2017 changed the way we were thinking about attention. With enough data, matrix multiplications, linear layers, and layer normalization we can perform state-of-the-art-machine-translation.</strong></p>
<p>The Transformer Architecture is our first attempt at the unification of different fields of Deep Learning like Natural Language Processing , Computer Vision , Reinforcment Learning</p>
<p>In recent years, the transformer model has become one of the main highlights of advances in deep learning .This tweet by Andrej Karpathy summarizes the Transformer Architecture nicely</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/karpathy/status/1582807367988654081">https://twitter.com/karpathy/status/1582807367988654081</a></div>
<p> </p>
<p>Over the years Transformer Models have evolved and you may have been using them with out even knowing about it . Some of the highlights include</p>
<ul>
<li><p>The original <a target="_blank" href="https://jalammar.github.io/illustrated-transformer/">Transformer</a> breaks previous performance records for machine translation.</p>
</li>
<li><p><a target="_blank" href="https://jalammar.github.io/illustrated-bert/">BERT</a> popularizes the pre-training then finetuning process, as well as Transformer-based contextualized word embeddings. It then rapidly starts to power <a target="_blank" href="https://blog.google/products/search/search-language-understanding-bert/">Google Search</a> and <a target="_blank" href="https://azure.microsoft.com/en-us/blog/bing-delivers-its-largest-improvement-in-search-experience-using-azure-gpus/">Bing Search</a>.</p>
</li>
<li><p><a target="_blank" href="https://jalammar.github.io/illustrated-gpt2/">GPT-2</a> demonstrates the machine’s ability to write as well as humans do.</p>
</li>
<li><p>First <a target="_blank" href="https://arxiv.org/abs/1910.10683">T5</a>, then <a target="_blank" href="https://huggingface.co/bigscience/T0pp">T0</a> push the boundaries of transfer learning (training a model on one task, and then having it do well on other adjacent tasks) and posing a lot of different tasks as text-to-text tasks.</p>
</li>
<li><p><a target="_blank" href="https://jalammar.github.io/how-gpt3-works-visualizations-animations/">GPT-3</a> showed that massive scaling of generative models can lead to shocking emergent applications (the industry continues to train larger models like <a target="_blank" href="https://deepmind.com/research/publications/2021/scaling-language-models-methods-analysis-insights-from-training-gopher">Gopher</a>, <a target="_blank" href="https://www.microsoft.com/en-us/research/blog/using-deepspeed-and-megatron-to-train-megatron-turing-nlg-530b-the-worlds-largest-and-most-powerful-generative-language-model/">MT-NLG</a>…etc).</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672124713529/d16c1d96-2117-44fe-9feb-49f63dd51942.png" alt class="image--center mx-auto" /></p>
<p>So next time if some one asks you about GPT Models you know that these state of the art model are nothing but <strong><em>transformer decoder block</em></strong> stacked on each other!!!</p>
<p>If you want to dig deeper into the nitty-gritty of the transformer Architecture and the maths behind it I would recommend everyone to check these amazing Blogs</p>
<ul>
<li><p><a target="_blank" href="https://theaisummer.com/transformer/">AI Summer</a></p>
</li>
<li><p><a target="_blank" href="https://jalammar.github.io/illustrated-transformer/">Jalammar.github.io</a></p>
</li>
</ul>
<h1 id="heading-t5-transformers">T5 Transformers</h1>
<p>A <strong>T5</strong> is an encoder-decoder model. It converts all NLP problems like language translation, summarization, text generation, question-answering, to a <strong>text-to-text</strong> task.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672124921485/96872aba-cf6e-44c1-a86d-3a6c3b723539.gif" alt class="image--center mx-auto" /></p>
<p>The original T5 paper, proposes reframing all NLP tasks into a unified text-to-text-format where the input and output are always text strings, in contrast to BERT-style models that can only output either a class label or a span of the input.</p>
<p>The text-to-text framework allows it to use the same model, loss function, and hyperparameters on <em>any</em> NLP task, including machine translation, document summarization, question answering, and classification tasks (e.g., sentiment analysis). We can even apply T5 to regression tasks by training it to predict the string representation of a number instead of the number itself.</p>
<h1 id="heading-fine-tuning-on-custom-dataset">Fine Tuning on Custom Dataset</h1>
<p>For fine-tuning this model on our dataset, we will require high computing power. So if you have a GPU like RTX 2060 on your local machine you can use that. But even if you don't have a high-end machine you can still fine-tune the model using Google Colab for free , which we will be using in this Blog</p>
<h2 id="heading-what-is-fine-tuning">What is Fine Tuning</h2>
<p>Fine-tuning a pre-trained language model (LM) has become the de facto standard for doing transfer learning in natural language processing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672129142901/3fda0cfd-8a30-4fdd-9cdf-95574e406e0b.png" alt class="image--center mx-auto" /></p>
<p>In the standard transfer learning setup , a model is first pre-trained on large amounts of unlabelled data using a language modelling loss such as masked language modelling (MLM; <a target="_blank" href="https://www.aclweb.org/anthology/N19-1423/">Devlin et al., 2019</a>). The pre-trained model is then fine-tuned on labelled data of a downstream task using a standard cross-entropy loss.</p>
<p>For the purpose of this tutorial going through each step will take long time so we will be using a Python Library <strong>SimpleT5</strong> that abstracts away a lot of this process.</p>
<h1 id="heading-fine-tuning-using-simplet5">Fine Tuning Using SimpleT5</h1>
<p><a target="_blank" href="https://github.com/Shivanandroy/simpleT5"><strong>simpleT5</strong></a> is built on top of PyTorch-lightning⚡️ and Transformers🤗 that lets you quickly train/fine-tune T5 models.</p>
<p>With <a target="_blank" href="https://github.com/Shivanandroy/simpleT5"><strong>simpleT5</strong></a> — It is very easy to fine-tune any T5 model on your dataset (Pandas dataframe )— for any task (summarization, translation, question-answering, or other sequence-to-sequence tasks), just — <strong>import, instantiate, download a pre-trained model and train.</strong>You can learn more about SimpleT5 in the <a target="_blank" href="https://openbase.com/python/simplet5/documentation">docs</a></p>
<p>Let's fine tune our chatbot :</p>
<h2 id="heading-processing-data">Processing Data</h2>
<p>We can use the dataset we made in <a target="_blank" href="https://sriprarabdha.hashnode.dev/turning-your-favorite-characters-lines-into-a-dataset-a-web-scraping-guide">Part 1</a> or simply download it from any Platforms like Kaggle or HuggingFace as a CSV File</p>
<p>But <a target="_blank" href="https://github.com/Shivanandroy/simpleT5"><strong>simpleT5</strong></a> expects a pandas dataframe as a dataset with 2 columns — <strong>source_text</strong> and <strong>target_text</strong> .</p>
<p>The dataset I am using is the RickAndMortyScripts.csv from <a target="_blank" href="https://sriprarabdha.hashnode.dev/turning-your-favorite-characters-lines-into-a-dataset-a-web-scraping-guide">Part 1</a> and we can simply convert it into a pandas dataframe</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672146881232/f18a1198-57f2-49a6-aed4-da271faebec7.png" alt class="image--center mx-auto" /></p>
<p>For the context of making a chatbot that talks like Rick our target_text can be the lines by rick .</p>
<p>And source_text can be all the lines said just earlier to the given line . eg . If target_text is the line at index = 2 then source text will be the line at index = 1</p>
<pre><code class="lang-python">context_x = []
response_y = []

<span class="hljs-comment">#excluding i=0 bcz i-1 will be out of bound</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span> , len(df)):
  <span class="hljs-keyword">if</span> df[<span class="hljs-string">'name'</span>][i] == <span class="hljs-string">'Rick'</span> :
    context_x.append(df[<span class="hljs-string">'line'</span>][i<span class="hljs-number">-1</span>])
    response_y.append(df[<span class="hljs-string">'line'</span>][i])
</code></pre>
<p>We can convert these lists into pandas dataframe</p>
<pre><code class="lang-python">col = [ <span class="hljs-string">'source_text'</span> , <span class="hljs-string">'target_text'</span>]

data = pd.DataFrame(list(zip(context_x, response_y)),
               columns =[<span class="hljs-string">'source_text'</span>, <span class="hljs-string">'target_text'</span>])
</code></pre>
<p>Next Let's split our dataset into train and test - and we're done</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split

train_df , test_df = train_test_split(data , test_size = <span class="hljs-number">.2</span>)
</code></pre>
<p>Now our training dataset looks some thing like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672148210993/b234127f-e761-4a0b-8a64-7043f5fddfda.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-training">Training</h2>
<p>First of all we need to install SimpleT5 package</p>
<pre><code class="lang-bash">pip install simplet5
</code></pre>
<p>We will import <strong>SimpleT5</strong> class and download a pre-trained T5 model</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> simplet5 <span class="hljs-keyword">import</span> SimpleT5

model = SimpleT5()
model.from_pretrained(<span class="hljs-string">"t5"</span>,<span class="hljs-string">"t5-base"</span>)
</code></pre>
<p>Finally Load the dataset in the model and train it</p>
<pre><code class="lang-python">model.train(train_df=train_df, <span class="hljs-comment"># pandas dataframe with 2 columns: source_text &amp; target_text</span>
            eval_df=test_df, <span class="hljs-comment"># pandas dataframe with 2 columns: source_text &amp; target_text</span>
            source_max_token_len = <span class="hljs-number">256</span>, 
            target_max_token_len = <span class="hljs-number">256</span>,
            batch_size = <span class="hljs-number">8</span>,
            max_epochs = <span class="hljs-number">12</span>,
            use_gpu = <span class="hljs-literal">True</span>,
            outputdir = <span class="hljs-string">"outputs"</span>,

            )
</code></pre>
<ul>
<li>source_max_token_len and target_max_token_length control the length of the encoded token of source and target text</li>
</ul>
<p>You can tweak around with hyper-parameters to see which performs better for your use case</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://media.giphy.com/media/XEOdmFHVznCerkI6CI/giphy.gif">https://media.giphy.com/media/XEOdmFHVznCerkI6CI/giphy.gif</a></div>
<p> </p>
<p>Now grab a cup of Coffee because training is gonna take some while . Training with a Colab Free tier on a Tesla T4 took me around 20 minutes to train.</p>
<h2 id="heading-inference">Inference</h2>
<p>Now that the model is trained now it's to yield it's power</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://media.giphy.com/media/Ph5ELYJov9n5oHzVHZ/giphy.gif">https://media.giphy.com/media/Ph5ELYJov9n5oHzVHZ/giphy.gif</a></div>
<p> </p>
<p>In the output directory we will have folders containing the model's weight at each epoch . load the one with the minimum loss</p>
<pre><code class="lang-python">model.load_model(<span class="hljs-string">"t5"</span> , <span class="hljs-string">"/content/outputs/simplet5-epoch-11-train-loss-1.7831-val-loss-3.6891"</span> , use_gpu=<span class="hljs-literal">True</span>)

model.predict(<span class="hljs-string">"are we in living in a simulation?"</span>)
</code></pre>
<p>Now you can go crazy with what you want to ask to your favourite character🎉</p>
<h1 id="heading-deploying-the-model">Deploying the Model</h1>
<p>We will be deploying this model onto HuggingFace🤗 where every one can play around with you model</p>
<p>Create a new <strong>repository</strong> on your Hugging Face Account</p>
<p><a target="_blank" href="https://huggingface.co/new"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672150359711/e7086895-11ed-47eb-8f39-cb920eb0e49f.png" alt class="image--center mx-auto" /></a></p>
<h2 id="heading-connect-your-colab-environment-to-your-hugging-face-account">Connect your Colab Environment to your Hugging Face Account</h2>
<pre><code class="lang-bash">!pip install huggingface_hub
</code></pre>
<p>Generate a Access Token for your Hugging Face Account and keep it with yourself to login</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> huggingface_hub <span class="hljs-keyword">import</span> notebook_login

notebook_login()
</code></pre>
<h2 id="heading-push-your-files-onto-your-repository">Push your files onto your <strong>repository</strong></h2>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> huggingface_hub <span class="hljs-keyword">import</span> HfApi
api = HfApi()

api.upload_file(
    path_or_fileobj=<span class="hljs-string">"/content/outputs/simplet5-epoch-11-train-loss-1.7831-val-loss-3.6891/tokenizer_config.json"</span>,
    path_in_repo=<span class="hljs-string">"tokenizer_config.json"</span>,
    repo_id=<span class="hljs-string">"Prarabdha/T5-Transformer-RickBot"</span>,
    repo_type=<span class="hljs-string">"model"</span>,
)
</code></pre>
<ul>
<li><p>path_or_fileobj : Path to the file that you are pushing</p>
</li>
<li><p>path_in_repo : Path of the file in your <strong>repository</strong></p>
</li>
<li><p>repo_id : is just Your_Username/Name_of_<strong>repository</strong></p>
</li>
<li><p>repo_type : model or dataset</p>
</li>
</ul>
<p>Push all your files in the folder with least loss onto Hugging Face one by one</p>
<p>Now your repo should look something like this</p>
<p><a target="_blank" href="https://huggingface.co/Prarabdha/T5-Transformer-RickBot"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672151320001/ec5e7bf2-3c83-4783-97c6-ca55ec06c6ff.png" alt class="image--center mx-auto" /></a></p>
<p>** Without the T5-Transformer-RickBot folder in the repo (that was a mistake)</p>
<h1 id="heading-voila-youre-done"><strong>Voila — You’re done !🎉</strong></h1>
<p>Now you have successfully deployed you model on Huggin Face Hub it can be used by developers across the globe</p>
<p>Without you spending hours and hours on trying to make inference API on you own and trying to host it on something like AWS</p>
<p><a target="_blank" href="https://huggingface.co/Prarabdha/T5-Transformer-RickBot"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672151654664/f0ce7ff2-4c2d-41ac-a696-13a56da746c6.png" alt class="image--center mx-auto" /></a></p>
<p>Have fun chatting with your favourite character!!🤩</p>
<p>Check Out <a target="_blank" href="https://huggingface.co/Prarabdha/T5-Transformer-RickBot">RickBot</a> ❤️</p>
<p>I hope that you found this tutorial helpful. See you in the next part of this series and Happy Coding!!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://media.giphy.com/media/dRvEZLV0ORAmHT1L5u/giphy.gif">https://media.giphy.com/media/dRvEZLV0ORAmHT1L5u/giphy.gif</a></div>
]]></content:encoded></item><item><title><![CDATA[Turning Your Favorite Characters' Lines into a Dataset: A Web Scraping Guide]]></title><description><![CDATA[Introduction
In this series, we will be making a discord bot that talks like your favorite character. We will first learn how to collect our own data, Fine-Tune a Transformer Model on this custom data , use this model as an inference API and finally ...]]></description><link>https://sriprarabdha.hashnode.dev/turning-your-favorite-characters-lines-into-a-dataset-a-web-scraping-guide</link><guid isPermaLink="true">https://sriprarabdha.hashnode.dev/turning-your-favorite-characters-lines-into-a-dataset-a-web-scraping-guide</guid><category><![CDATA[nlp]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[web scraping]]></category><category><![CDATA[bot]]></category><category><![CDATA[WeMakeDevs]]></category><dc:creator><![CDATA[Prarabdha Srivastava]]></dc:creator><pubDate>Mon, 26 Dec 2022 15:57:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1671961015818/249d8cd3-6c3e-4087-982f-249addf61fe8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>In this series, we will be making a discord bot that talks like your favorite character. We will first learn how to collect our own data, <strong>Fine-Tune</strong> a Transformer Model on this custom data , use this model as an <strong>inference API</strong> and finally deploying it as a discord Bot that you can play around with and show off to your friends!</p>
<p>Inspired by one of my favorite sci-fi shows Rick and Morty I we will be making a Rick chatbot . But you can do this for any character and bring them to life</p>
<p>In this <strong>Part 1</strong> we will be making our own dataset by scrapping the internet with the help of BueatifulSoup , conveting the dataset into a CSV File and finally publishing it</p>
<h1 id="heading-but-why-data">But Why Data?🤔</h1>
<p>Data is the most important and must-have food for machine learning. It can be any fact, text, symbols, images, videos, etc., but in unprocessed form. Machine learning without data is nothing but a bare machine with no soul and no mind. This data makes machines do such amazing tasks, which we have not thought of a few years back in history.</p>
<p>Most of us don't pay any attention to the kind of data we are using even though our Quality of data dictates the Quality of our model</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672048841908/3d7ad3c0-bada-42b4-936b-50c23822157c.jpeg" alt class="image--center mx-auto" /></p>
<p>If I would ask you how many projects did you abandon , just because you couldn't find a dataset for your use case ?</p>
<p>Atleast for me there would be so many of them that I couldn't complete just because there was no dataset on any platforms like Kaggle and HuggingFace</p>
<h1 id="heading-web-scraping-using-beautifulsoup">Web Scraping using Beautifulsoup🤗</h1>
<p>In this section, we will be learning how to create a web scraper in Python. You will learn how to inspect a website to prepare for scraping, extract specific data using BeautifulSoup</p>
<p>For our project, we can get the transcripts of almost all episodes of Rick and Morty on these 2 sites -</p>
<ul>
<li><p><a target="_blank" href="http://RickandMorty.fandom.com"><strong>RickandMorty.fandom.com</strong></a></p>
</li>
<li><p><a target="_blank" href="http://RickandMorty.newtfire.org"><strong>RickandMorty.newtfire.org</strong></a></p>
</li>
</ul>
<p>When scraping data we will need to get a basic idea of HTML code</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
topic_url = <span class="hljs-string">"https://rickandmorty.fandom.com/wiki/Rickipedia"</span>
response = requests.get(topic_url)
</code></pre>
<p>Request Library helps us to extract the HTML code of any web page and response will return the complete code as a string</p>
<p>But getting a large string of code is not very helpful to us so we can use a python package BeautifulSoup. To install it, just run this command on your terminal:</p>
<pre><code class="lang-bash">pip install beautifulsoup4
</code></pre>
<p>Now we can use BeautifulSoup to wrap our HTML Code and send in our queries</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> bs4 <span class="hljs-keyword">import</span> BeautifulSoup
doc = BeautifulSoup(page_contents , <span class="hljs-string">'html.parser'</span>)
topics_link_tags = doc.find_all(<span class="hljs-string">'a'</span> , {<span class="hljs-string">'class'</span> : <span class="hljs-string">'image link-internal'</span>})
len(topics_link_tags)
</code></pre>
<p>This code helps us to find all the anchor tags in our code that have a class name as '<em>image link-internal' .</em> We can send in all types of queries to search tags by ids or extract their inner text to read further you can see the <a target="_blank" href="https://beautiful-soup-4.readthedocs.io/en/latest/">docs</a> . But we will be covering all the commonly used functions in this blog</p>
<h1 id="heading-journey-begins">Journey Begins 😎</h1>
<p>If you go to the <a target="_blank" href="http://RickandMorty.fandom.com"><strong>RickandMorty.fandom.com</strong></a> site and scroll you can see that the transcripts we need are not here. We need to open the 'Episodes' link in this table</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672052858828/441eec74-8017-4a24-a963-effccc8dd96c.png" alt class="image--center mx-auto" /></p>
<p>To extract this link we need an understanding of HTML written on this page. You can simply use the inspect tool on chrome to get the code</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672053306182/5ed945c0-8768-421c-8f50-fbb779b947ab.png" alt class="image--center mx-auto" /></p>
<p>We will need to extract the link present inside the anchor tag wrapping the highlighted image tag , in order to scrape the next page</p>
<pre><code class="lang-python"><span class="hljs-comment">#Since the anchor we want to extract is 9th on the page</span>
episode_url = <span class="hljs-string">'https://rickandmorty.fandom.com'</span> + topics_link_tags[<span class="hljs-number">8</span>][<span class="hljs-string">'href'</span>]
response_episode = requests.get(episode_url)
episode_page_content = response_episode.text
doc_episode = BeautifulSoup(episode_page_content , <span class="hljs-string">'html.parser'</span>)
</code></pre>
<p>On the next page we have the link to all the episode and on further inspection of these individual links we can get transcripts</p>
<p><strong>Plan of Action</strong></p>
<ul>
<li><p>Get a strategy to extract transcript on the individual episode</p>
</li>
<li><p>Store the Data</p>
</li>
<li><p>Repeat it on every episode page</p>
</li>
</ul>
<h2 id="heading-extracting-transcripts-for-a-individual-page">Extracting transcripts for a Individual Page</h2>
<p>On the transcript page of the one of the episode we can see that each line is wrapped inside &lt;paragraph&gt;tags . The name of Character is either in&lt;bold&gt; tag or &lt;anchor&gt; tag and the line by that character is written outside these tags</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672056745565/c53f208e-770e-45ae-bef3-05a884050d24.png" alt class="image--center mx-auto" /></p>
<p><strong>Plan of Action</strong></p>
<ul>
<li><p>loop over all paragraph&gt; tags present on that page</p>
</li>
<li><p>Find the &lt;b&gt; tag inside a &lt;p&gt; tag and check for &lt;a&gt; tag in it</p>
</li>
<li><p>If no &lt;a&gt; tag present inside &lt;b&gt; , then content of &lt;b&gt; is name of character , otherwise go for&lt;a&gt;</p>
</li>
<li><p>Extract the line by that character</p>
</li>
</ul>
<p>We can define a simple function that can parse the HTML for every page extract the data and store it in array</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">page_transcript</span>(<span class="hljs-params">link , episode_num</span>) :</span>

    data = []

    response_episode_page = requests.get(link)
    page_content = response_episode_page.text

    doc_episode_page = BeautifulSoup(page_content , <span class="hljs-string">'html.parser'</span>)
    para_tags = doc_episode_page.find_all(<span class="hljs-string">'p'</span>)

    <span class="hljs-keyword">for</span> tag <span class="hljs-keyword">in</span> para_tags :
        <span class="hljs-keyword">try</span> :
            <span class="hljs-keyword">if</span> tag.find(<span class="hljs-string">'b'</span>) == <span class="hljs-literal">None</span>:
                <span class="hljs-keyword">continue</span>
            <span class="hljs-keyword">else</span> :
                list_child = list(tag.children)
                dialouge = list_child[<span class="hljs-number">1</span>]

                <span class="hljs-keyword">if</span> list_child[<span class="hljs-number">0</span>].find(<span class="hljs-string">'a'</span>) == <span class="hljs-literal">None</span> :
                    name = list_child[<span class="hljs-number">0</span>].contents[<span class="hljs-number">0</span>]
                    <span class="hljs-comment"># print(list_child[0].contents[0])</span>

                <span class="hljs-keyword">else</span> :
                    name = list_child[<span class="hljs-number">0</span>].find(<span class="hljs-string">'a'</span>).contents[<span class="hljs-number">0</span>]
                    <span class="hljs-comment"># print(list_child[0].find('a').contents[0])</span>

        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
            <span class="hljs-keyword">continue</span>

        data.append([episode_num , name , dialouge])

    <span class="hljs-keyword">return</span> data
</code></pre>
<p>There may be a better way to write the above code you are free to explore and play around with the code</p>
<h2 id="heading-extracting-data-from-every-transcript-page-link">Extracting Data from every transcript page link</h2>
<p>To navigate to the transcript page we need to go through each link of episode contained inside the season table and further add '/Transcript' in that episode URL</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672061003215/fb98adea-0b98-4dea-8fc7-4e84bd4eb0d2.png" alt class="image--center mx-auto" /></p>
<p>In this code we loop over all the tables, extract the links of episodes and call our <em>page_transcript()</em> function to store the data for every episode</p>
<pre><code class="lang-python">dataset = []

j = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span> , <span class="hljs-number">6</span>):
    table = doc_episode_tables[i]
    anchor_tags = doc_episode_tables[i].find_all(<span class="hljs-string">'a'</span>)

    <span class="hljs-keyword">for</span> tags <span class="hljs-keyword">in</span> anchor_tags :

        <span class="hljs-keyword">try</span> :
            dataset_episode_title.append(tags[<span class="hljs-string">'title'</span>])
            link = <span class="hljs-string">'https://rickandmorty.fandom.com'</span> +tags[<span class="hljs-string">'href'</span>] + <span class="hljs-string">'/Transcript'</span>
            j+=<span class="hljs-number">1</span>
            print(link , j)
            data = page_transcript(link=link , episode_num=j)
            dataset.append(data)

        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
            <span class="hljs-keyword">continue</span>
</code></pre>
<p>Finally! You have the dataset list containing the transcripts for all the episodes🎉</p>
<p><strong>But our work is not done yet!!!</strong></p>
<h2 id="heading-common-errors">Common Errors</h2>
<p>In general when scrapping data this way we make a bet that code will be standardized for every page in the website but that is always not the case</p>
<p>We come across this problem with this website many of the transcript pages have totally different ways of writing transcripts in HTML code or sometimes even data is completely missing. Which will result in Low-Quality Data.So we will have to manually check for the faulty pages and come up with scripts to solve them</p>
<h3 id="heading-1all-content-put-in-one-p-tag-error">1)All content put in one p tag error</h3>
<p>In this rather than putting the name of the character in a &lt;b&gt; or &lt;a&gt; tag it is simply put in a &lt;p&gt; tag with the lines of the character</p>
<p>In this code, we are extracting the transcript of episode 24</p>
<pre><code class="lang-python">url_error = <span class="hljs-string">"https://rickandmorty.fandom.com/wiki/Pickle_Rick/Transcript"</span>

response_error = requests.get(url_error)
content_error = response_error.text
doc_episode_error = BeautifulSoup(content_error , <span class="hljs-string">'html.parser'</span>)

para_tag_error  = doc_episode_error.find(<span class="hljs-string">'p'</span>)

text_error = para_tag_error.get_text()
text_error = text_error.rsplit(<span class="hljs-string">"\n"</span>)

<span class="hljs-keyword">for</span> text_e <span class="hljs-keyword">in</span> text_error :
    <span class="hljs-keyword">try</span>:
        text_e_i = text_e.rsplit(<span class="hljs-string">': '</span>)
        dataset[<span class="hljs-number">23</span>].append([<span class="hljs-number">24</span> , text_e_i[<span class="hljs-number">0</span>] , text_e_i[<span class="hljs-number">1</span>]])
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-keyword">continue</span>
</code></pre>
<h3 id="heading-2retriving-missing-content-from-other-site">2)Retriving missing content from other site</h3>
<p>We solve this problem by getting the missing content from a different site <a target="_blank" href="http://RickandMorty.newtfire.org"><strong>RickandMorty.newtfire.org</strong></a></p>
<p>In this code we extract the transcript for episode 27 and by simply changing the ID of div in the page we can do the same for different episodes</p>
<pre><code class="lang-python">url_error_2 = <span class="hljs-string">"http://rickandmorty.newtfire.org/transcripts.html"</span>
response_error_2 = requests.get(url_error_2)
content_error_2 = response_error_2.text
doc_episode_error_2 = BeautifulSoup(content_error_2 , <span class="hljs-string">'html.parser'</span>)

opt_26 = doc_episode_error_2.find(<span class="hljs-string">'div'</span> , id = <span class="hljs-string">'aboutopt26'</span>)

opt_26_speaker = opt_26.find_all(<span class="hljs-string">'span'</span> , {<span class="hljs-string">'class'</span>:<span class="hljs-string">'speaker'</span>})
opt_26_speech = opt_26.find_all(<span class="hljs-string">'span'</span> , {<span class="hljs-string">'class'</span>:<span class="hljs-string">'speech'</span>})
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range (<span class="hljs-number">0</span> , len(opt_26_speaker)):
     dataset[<span class="hljs-number">26</span>].append([<span class="hljs-number">27</span> , opt_26_speaker[i].get_text() , opt_0_speech[i].get_text()])
</code></pre>
<h1 id="heading-exporting-dataset-as-csv-file">Exporting Dataset as CSV File 🙌</h1>
<p>Finally after correcting a lot of errors our dataset is finally readyand we can export it into a CSV File</p>
<p>In this code we will first convert this python list into pandas dataframe and finally convert it to a csv file</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

col = [<span class="hljs-string">'episode no.'</span> , <span class="hljs-string">'speaker'</span> , <span class="hljs-string">'dialouge'</span>]
df = pd.DataFrame(dataset[<span class="hljs-number">0</span>] , columns=col)

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span> , <span class="hljs-number">51</span>) :
    df_temp = pd.DataFrame(dataset[i] , columns=col)
    df = df.append(df_temp , ignore_index = <span class="hljs-literal">True</span>)

df.to_csv(<span class="hljs-string">'Rick&amp;Morty.csv'</span>)
</code></pre>
<h1 id="heading-share-your-work-in-public">Share your work in Public 🤩</h1>
<p>Now that you have created your dataset, it wouldn't be fun just to keep it with yourself . You can <strong>Publish</strong> it on platforms like HuggingFace and Kaggle so that it can be used by anyone</p>
<p>You can simply do that by creating a new dataset on any of these of platforms and importing your CSV File and that's it. Make Sure to add good Documentation for your dataset to make it easy to use for others.</p>
<p>That's it you just made your <strong>Dataset</strong> publicly available which can now be used by everyone</p>
<p><a target="_blank" href="https://www.kaggle.com/datasets/prarabdhasrivastava/rickmorty-transcripts"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672063864296/a1ca11e6-297b-4ba2-a831-803704fca6e3.png" alt class="image--center mx-auto" /></a></p>
<p>You can find the Rick And Morty dataset on <a target="_blank" href="https://www.kaggle.com/datasets/prarabdhasrivastava/rickmorty-transcripts">Kaggle</a> or <a target="_blank" href="https://huggingface.co/datasets/Prarabdha/Rick_and_Morty_Transcript">HuggingFace</a> make sure to use it in your next project and give an upvote!</p>
<p>I hope that you found this tutorial helpful. See you in the next part of this series and Happy Coding!!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://media.giphy.com/media/3o8doZFy4iPd8VBL8I/giphy.gif">https://media.giphy.com/media/3o8doZFy4iPd8VBL8I/giphy.gif</a></div>
]]></content:encoded></item><item><title><![CDATA[AlphaTensor : Reinforcment Learning's approach to Multiplication]]></title><description><![CDATA[Just a few days back Deepmind pub it's new paper AlphaTensor, the first artificial intelligence (AI) system for discovering novel, efficient, and provably correct algorithms for fundamental tasks such as matrix multiplication.
In this article we are ...]]></description><link>https://sriprarabdha.hashnode.dev/alphatensor-reinforcment-learnings-approach-to-multiplication</link><guid isPermaLink="true">https://sriprarabdha.hashnode.dev/alphatensor-reinforcment-learnings-approach-to-multiplication</guid><category><![CDATA[#deepmind]]></category><category><![CDATA[Reinforcement Learning]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[Deep Learning]]></category><dc:creator><![CDATA[Prarabdha Srivastava]]></dc:creator><pubDate>Wed, 19 Oct 2022 20:06:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665227097676/hpHnsUWux.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Just a few days back Deepmind pub it's new paper AlphaTensor, the first artificial intelligence (AI) system for discovering novel, efficient, and provably correct algorithms for fundamental tasks such as matrix multiplication.</p>
<p>In this article we are gonna cover the following topics - </p>
<ol>
<li>Maths Behind SVD</li>
<li>TensorGame</li>
<li>Challenges posed by TensorGame<ul>
<li>Synthetic demonstrations</li>
<li>Change of basis</li>
<li>Data augmentation</li>
<li>Neural network architecture</li>
</ul>
</li>
<li>Conclusion</li>
</ol>
<h2 id="heading-singular-value-decomposition-svd">Singular Value Decomposition (SVD)</h2>
<p>SVD is one of the most important algorithms in linear algebra. You can think of it as a tool that helps in data reduction of Big Data eg. high-resolution images or videos. In the last generation of computational science, we used may be things like the Fourier transform, Bessel's function, and spherical harmonics to map the system of interest to new and simpler co-ordinate. But for example, if we have a complex system like turbulent flow over a Boeing wing, there is no off-the-shelf transformation to cater to this problem but a technique like SVD can be tailored to any general problem
This algorithm is literally used all over the place like compression of large data, Google's page rank algorithm, Facebooks's face recognition algorithms and recommendation systems at Netflix, and Amazon to find correlation patterns</p>
<p>Now that I have got you hyped enough let's dive in</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665231624323/-t_3gNVPP.png" alt="download.png" class="image--center mx-auto" />  </p>
<p>Let's assume we have image with a million pixels and it is vectorized to a column vector m x 1 and we use n such images putting them togather to get a m x n matrix where m&gt;&gt;&gt;n (m is in order of millions and n is no.of image in order of thousands)
Then that matrix can be represented as</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665231942933/hPDwmrK3j.png" alt="330px-Singular_value_decomposition_visualisation.svg.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666209512806/OfcaqWTHk.png" alt="Screenshot 2022-10-20 012823.png" class="image--center mx-auto" /></p>
<p>where U , V are orthogonal matrices which is represented in the above image 
U is of same dimension as of M but with some distortionand that's why you can guess it is called the eigenvector
and the sigma matrix is a diagonal matrix till n x n matrix and other than that it's all zero where all enteries are in hierichal order describing the importance of first row of U and first column of V in representing our data M</p>
<p>But we can approximate our data M by just using first k columns in our matrices U , V , W </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666199459794/XHqIOFLFb.png" alt="Screenshot 2022-10-19 224042.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666199350122/-HCC3gJ3i.png" alt="Screenshot 2022-10-19 223827.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666209443558/XQri_mZci.png" alt="Screenshot 2022-10-20 012643.png" class="image--center mx-auto" /></p>
<p>To get a even deeper understanding of SVD I would highly recommend this youtube playlist by <a target="_blank" href="https://www.youtube.com/watch?v=nbBvuuNVfco&amp;list=PLMrJAkhIeNNSVjnsviglFoY2nXildDCcv&amp;index=2">Steve Brunton</a></p>
<h2 id="heading-alphatensor">AlphaTensor</h2>
<p>When we talk about efficient algorithms the efficiency doesn’t come from thin air it comes by optimizing our algorithm to the kind of hardware we have . The GPUs or TPUs we use take a lot time in multiplication than addition so if we could reduce the number of multiplication operation by some kind of manipulation and replace it with  addition . You all must remember this from your high school mathematics</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666189338327/AUEluMtoV.png" alt="Screenshot 2022-10-19 195140.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666189380646/fwtX0Jqum.png" alt="Screenshot 2022-10-19 195246.png" class="image--center mx-auto" /></p>
<p>As you can see with a simple manipulation we reduce the number of multiplications from 2 to 1 thus optimizing our calculation  and when we do some similar things in a 2 x 2 matrix multiplication we can optimize matrix multiplication</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665425563161/JNE4lsaLZ.png" alt="pic2.png" class="image--center mx-auto" /></p>
<p>As you can clearly see there can be many combination that we can form with trial and error to get our required result and this is where reinforcement learning come where our agents learns the suitable parameters in form of a game 
Now we are gonna look at the structure of this game</p>
<p>Let’s assume we have two 2 x 2 matrices to multiply (A &amp; B) to get a resultant matrix C</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666191039250/JJRcjixax.png" alt="Screenshot 2022-10-19 202016.png" class="image--center mx-auto" /></p>
<p>Tensor T2 representing the multiplication of two 2 × 2 matrices. Tensor entries equal to 1 are depicted in purple, and 0 entries are semi-transparent. The tensor specifies which entries from the input matrices to read, and where to write the result. For example, as c1 = a1b1 + a2b3, tensor entries located at (a1, b1, c1) and (a2, b3, c1) are set to 1</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665425859327/tQShZi4ca.png" alt="pic4.png" class="image--center mx-auto" /></p>
<p>Then if we could do a matrix decomposition of T2 we can find the values of parameter let me unroll this 
Looking at the given state our agent makes a policy i.e choses a set of triplet (u(t) , v(t) , w(t) )
Let’s assume agent chooses the given combination of u , v , w taking a outer product would give us</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666200407522/9GY7i-yEn.png" alt="Screenshot 2022-10-19 225613.png" class="image--center mx-auto" /></p>
<p>Taking outer product of these vectors would give us , </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666200663140/MLaxrjx_t.png" alt="Screenshot 2022-10-19 230016.png" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666202496679/j_f9qXbB9.png" alt="Screenshot 2022-10-19 233114.png" class="image--center mx-auto" /></p>
<p>where above picture represents a 4x4x4 tensor with the same 4x4 matrix repeated 4 times in z direction is the rank 1 approximation of the data M</p>
<p>Now if we keep coming up with good values to the triplet u , v, w make 3d tensors with them then add them we shall get back our initial T2</p>
<h3 id="heading-tensorgame">TensorGame</h3>
<p>The state of TensorGame after step t is described by a tensor St and initially S0 = T2 then agent finds a worthy triplet find out it’s outer product then subtract the result with the current state , again use that new state and new triplets to find next state and so on . And the game is finally won if after 7 approximation of u , v , w triplet we get the final state as zero which is what it should be if you remember the maths from previous section</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666188679668/LgZ1GfM66.png" alt="Screenshot 2022-10-19 194044.png" class="image--center mx-auto" /></p>
<ul>
<li>For every step taken, we provide a reward of −1 to encourage finding the shortest path to the zero tensor.</li>
<li>, we constraint {u(t), v(t), w(t)} to have entries in a user-specified discrete set of coefficients F (for example, F = {−2, −1, 0, 1, 2}). </li>
<li>TensorGame is played by the agent AlphaZero1, which achieved  superhuman performance in the classical board games of Go, chess and shogi,
Similarly to AlphaZero, AlphaTensor uses a deep neural network to guide a Monte Carlo tree search (MCTS) planning procedure. The network takes as input a state (that is, a tensor St to decompose), and outputs a policy and a value.</li>
</ul>
<h3 id="heading-challenges-posed-by-tensorgame">challenges posed by TensorGame</h3>
<p>The main challenge posted by TensorGame is that of a enormous action space . We can overall improve the performance over aplain AlphaZero agent by following methods</p>
<p><strong>1. Synthetic demonstrations</strong></p>
<p>Although decomposition of matrices is a difficult task but the task of making matrices from randomly choosen {u(t), v(t), w(t)} and adding them up to get a matrix is quite easy</p>
<p>Then we can train the network on this diverse set of examples</p>
<p><strong>2. Change of basis </strong></p>
<p>Tn (Fig. 1a) is the tensor representing the matrix multiplication bilinear operation in the canonical basis. The same bilinear operation can be expressed in other bases, resulting in other tensors. To know more about basis you can see this amazing video by <a target="_blank" href="https://www.youtube.com/watch?v=k7RM-ot2NWY">3Blue1Brown</a></p>
<p>These different tensors are equivalent they have the same rank, and decompositionsobtained in a custom basis We leverage this observation by sampling a random change of basis at the beginning of every game, applying it to Tn, and letting AlphaTensor play the game in that basis . This crucial step injects diversity into the games played by the agent.</p>
<p><strong>3. Data augmentation </strong></p>
<p>From every played game, we can extract additional tensor-factorizationpairs for training the network.Specifically, as factorizations are order invariant (owing to summation), we build an additional tensor-factorization training pair by swapping a random action with the last action from each finished game.</p>
<p><strong>4. Neural network architecture</strong></p>
<p>The network broadly consists of the following components Input, a torso, followed by a policy head that
predicts a distribution over actions, and a value head that predicts a distribution of the returns from the current state</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665778468690/-hciIColI.png" alt="Screenshot 2022-10-15 014253.png" class="image--center mx-auto" /></p>
<p>4.1 ) Input - The model is given all relevant information about the current state and the previous state . We plug in the the current state St as a tensor and  last h actions (h being a hyperparameter usually set to 7) as a scalar</p>
<p>4.2 )Torso - It basically maps the tensors and scalars from the input to a representation that is useful to both policy and value heads
It is a architecture based on modification of  transformers and its main signature is that it operates over three S × S grids projected from the S × S × S input tensors.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665778990416/-7QxOkhnZ.png" alt="Screenshot 2022-10-15 014928.png" class="image--center mx-auto" /></p>
<p>4.3 )Policy Head - Using the embedding generated by the torso network , this architecture gives a possible move for the agent i.e. choosing a correct set of {u(t), v(t), w(t)} given the previous state . The network makes the use of various attention mechanisms form transformers architecture you can learn more about it from this amazing <a target="_blank" href="https://machinelearningmastery.com/the-transformer-attention-mechanism/">blog</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666187684111/iLYIV3jeh.png" alt="Screenshot 2022-10-19 192424.png" class="image--center mx-auto" /></p>
<p>4.4 )Value Head - The value network assigns value/score to the state of the game by calculating an expected cumulative score for the current state s .  Actions that result in good state gets higher score . The key objective of our agent is to maximize this score </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666188244861/F_16fg9_I.png" alt="Screenshot 2022-10-19 193349.png" class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p> AlphaTensor’s algorithm improves on Strassen’s two-level algorithm in a finite field for the first time since its discovery 50 years ago. </p>
<p>AlphaTensor also discovers a diverse set of algorithms with state-of-the-art complexity – up to thousands of matrix multiplication algorithms for each size, showing that the space of matrix multiplication algorithms is richer than previously thought . These algorithms multiply large matrices 10-20% faster than the commonly used algorithms.</p>
<p>Because matrix multiplication is a core component in many computational tasks, spanning computer graphics, digital communications, neural network training, and scientific computing, AlphaTensor-discovered algorithms could make computations in these fields significantly more efficient.</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Code your First DAPP]]></title><description><![CDATA[I don't know about you but whenever I open twitter to shitpost , I just get distracted by everyone just talking about Web3 ecosystem and how building this ecosystem is like building internet companies in early 2000s . So if you are the same and ever ...]]></description><link>https://sriprarabdha.hashnode.dev/code-your-first-dapp</link><guid isPermaLink="true">https://sriprarabdha.hashnode.dev/code-your-first-dapp</guid><category><![CDATA[Solidity]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Prarabdha Srivastava]]></dc:creator><pubDate>Thu, 28 Apr 2022 15:18:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/L2QB-rG5NM0/upload/v1651124949958/mz8z7dq5w.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I don't know about you but whenever I open twitter to shitpost , I just get distracted by everyone just talking about Web3 ecosystem and how building this ecosystem is like building internet companies in early 2000s . So if you are the same and ever wondered how to create a basic Decentralized Application on ethereum then you are gonna enjoy this read!!!</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To make anything on blockchain you should have a decent grab over web2 topics</p>
<ul>
<li>Very basic knowledge of HTML &amp; CSS </li>
<li>Knowledge of Asynchronous programming in Javascript</li>
<li>Basic idea of smart contracts and solidity</li>
</ul>
<p>For this tutorial we will be using <a target="_blank" href="https://metamask.io/">metamask</a> as our digital wallet and <a target="_blank" href="https://remix.ethereum.org/">remix</a> IDE for compiling and deploying our smart contract</p>
<h2 id="heading-now-the-fun-starts"><strong>Now the FUN Starts</strong></h2>
<h3 id="heading-1-setting-up-metamask">1. <strong>Setting up Metamask</strong></h3>
<ul>
<li>Download the Metamask wallet extension if you haven't</li>
<li>Switch to Ropsten Testnet from the Ethereum Mainnet by clicking on the top</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651125481297/MdkQal4Hv.png" alt="image.png" /></p>
<p>If you are working with metamask for first time then probably you will have 0 etheres on any testnet but here is the amazing thing since these are testnet ethers on this network have no valueso you can get it for free from any faucet by entering your metamask wallet address 
<a target="_blank" href="https://faucet.egorfine.com/">Faucet link to request funds</a></p>
<h3 id="heading-2-create-and-serve-a-simple-webpage">2. <strong>Create and Serve a Simple Webpage</strong></h3>
<p>The first step is to create a basic HTML page.</p>
<ul>
<li>Create a new folder (directory) in your terminal using mkdir </li>
<li>In a code editor (e.g. Atom, or Visual Studio Code), open the folder</li>
<li>Create a new file called index.html</li>
<li>Open index.html</li>
<li>Create HTML boilerplate</li>
<li>We will need a label, an input, and buttons.</li>
</ul>
<pre><code><span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span>DOCTYPE html<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>html lang<span class="hljs-operator">=</span><span class="hljs-string">"en"</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>head<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta charset<span class="hljs-operator">=</span><span class="hljs-string">"UTF-8"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta http<span class="hljs-operator">-</span>equiv<span class="hljs-operator">=</span><span class="hljs-string">"X-UA-Compatible"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"IE=edge"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta name<span class="hljs-operator">=</span><span class="hljs-string">"viewport"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"width=device-width, initial-scale=1.0"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>title<span class="hljs-operator">&gt;</span>My first Dapp<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>head<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">""</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>h1<span class="hljs-operator">&gt;</span>This <span class="hljs-keyword">is</span> my first Dapp<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>h1<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>Here we can either set the mood or read the mood<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>button onclick<span class="hljs-operator">=</span><span class="hljs-string">"getMood()"</span><span class="hljs-operator">&gt;</span>Get Mood<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span> <span class="hljs-operator">&lt;</span>br<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text"</span> id<span class="hljs-operator">=</span><span class="hljs-string">"mood"</span> placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Input Mood"</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>button onclick<span class="hljs-operator">=</span><span class="hljs-string">"setMood()"</span><span class="hljs-operator">&gt;</span>Set Mood<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>

<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>html
<span class="hljs-operator">&gt;</span>
</code></pre><p>OPTIONAL: Create a new file index.css , add some styles to make it look nicer</p>
<pre><code><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">font-family</span>: Arial, Helvetica, sans-serif;
  }

<span class="hljs-selector-tag">div</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">20%</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span> <span class="hljs-number">10px</span> <span class="hljs-number">5px</span> <span class="hljs-number">0px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2rem</span>;
}
</code></pre><p>Feel free to add more styling as to be honest ui looks kinda ugly</p>
<ul>
<li>Install a http server. Use any you like, but we recommend lite-server for beginners:</li>
</ul>
<p><code>npm install -g lite-server #install lite-server globally</code> </p>
<ul>
<li>Serve the webpage via terminal/command prompt from the directory that has index.html in it and run:</li>
</ul>
<p><code>lite-server</code> </p>
<ul>
<li>Go to http://127.0.0.1:3000/ in your browser to see your page!</li>
</ul>
<p>Your front end is now complete!</p>
<h3 id="heading-3-create-a-basic-smart-contract"><strong>3. Create a Basic Smart Contract</strong></h3>
<p>For this tutorial we will be using Remix IDE</p>
<p>Make a new file mood.sol in the file structure and specify the solidity version you want to use </p>
<pre><code><span class="hljs-attribute">pragma</span> solidity &gt;=<span class="hljs-number">0</span>.<span class="hljs-number">7</span>.<span class="hljs-number">0</span> &lt;<span class="hljs-number">0</span>.<span class="hljs-number">9</span>.<span class="hljs-number">0</span>;
</code></pre><p>Create a contract moodDiary</p>
<pre><code><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> &gt;=0.7.0 &lt;0.9.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">moodDiary</span></span>{

}
</code></pre><p>Define a string variable that stores the value of mood and a function getMood() that returns it's value</p>
<pre><code><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> &gt;=0.7.0 &lt;0.9.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">moodDiary</span></span>{

      <span class="hljs-keyword">string</span> mood;

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMood</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>)</span>{
        <span class="hljs-keyword">return</span> mood;
    }
}
</code></pre><p>Also define a function that can change the state of variable mood on the blockchain i.e. setMood()</p>
<pre><code><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> &gt;=0.7.0 &lt;0.9.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">moodDiary</span></span>{

      <span class="hljs-keyword">string</span> mood;

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMood</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>)</span>{
        <span class="hljs-keyword">return</span> mood;
    }

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setMood</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _mood</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span></span>{
        mood <span class="hljs-operator">=</span> _mood;
    }
}
</code></pre><p>Compile the solidity file </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651144632760/fWn2DLDNw.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Deploying on Ropsten Network</p>
<p>Make sure that you are on Ropsten testchain on your Metamask wallet
on the Deploy/Run section of remix select Injected Web3 as encironment</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651144752341/6FFpv_12g.png" alt="image.png" class="image--center mx-auto" /></p>
<p>Click on Deploy button It will take some time so take a sip of your coffee as this transaction is being added to the blockchain</p>
<p>Remember to copy:</p>
<ul>
<li><p>The deployed contract's address
Copy it via the copy button next to the deployed contracts pulldown in remix's Run tab</p>
</li>
<li><p>The contract ABI
Copy it via the copy button under to the contract in remix's Compile tab (also in Details)</p>
</li>
</ul>
<h2 id="heading-4connect-your-webpage-to-your-smart-contract"><strong> 4.Connect your Webpage to your Smart Contract</strong></h2>
<p>Back in your local text editor in index.html, add the following code to your html page:</p>
<p>Import the Ethers.js source into your index.html page inside a new set of script tags:</p>
<pre><code><span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"https://cdn.ethers.io/lib/ethers-5.2.umd.min.js"</span>
<span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"application/javascript"</span>
<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>

<span class="hljs-operator">&lt;</span>script<span class="hljs-operator">&gt;</span>
  <span class="hljs-comment">////////////////////</span>
  <span class="hljs-comment">//ADD YOUR CODE HERE</span>
  <span class="hljs-comment">////////////////////</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
</code></pre><p>Inside the script tag, import the contract ABI (what is that?) and specify the contract address on our provider's blockchain:</p>
<p>```const MoodContractAddress = "";
  const MoodContractABI = 
  let MoodContract;
  let signer;</p>
<pre><code><span class="hljs-keyword">For</span> the contract ABI, we want <span class="hljs-keyword">to</span> specifically navigate <span class="hljs-keyword">to</span> the <span class="hljs-type">JSON</span> Section. We need <span class="hljs-keyword">to</span> describe our smart contract <span class="hljs-keyword">in</span> <span class="hljs-type">JSON</span> <span class="hljs-keyword">format</span>

```const MoodContractABI = [
    {
        "constant": <span class="hljs-keyword">true</span>,
        "inputs": [],
        "name": "getMood",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "payable": <span class="hljs-keyword">false</span>,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": <span class="hljs-keyword">false</span>,
        "inputs": [
            {
                "internalType": "string",
                "name": "_mood",
                "type": "string"
            }
        ],
        "name": "setMood",
        "outputs": [],
        "payable": <span class="hljs-keyword">false</span>,
        "stateMutability": "nonpayable",
        "type": "function"
    }
]
</code></pre><p>Next, Define an ethers provider. In our case it is Ropsten:</p>
<pre><code>const provider <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ethers.providers.Web3Provider(window.ethereum, <span class="hljs-string">"ropsten"</span>);
</code></pre><p>Request access to the user's wallet and connect the signer to your metamask account (we use [0] as the default), and define the contract object using your contract address, ABI, and signer</p>
<pre><code>provider.<span class="hljs-built_in">send</span>(<span class="hljs-string">"eth_requestAccounts"</span>, []).then(() <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  provider.listAccounts().then((accounts) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    signer <span class="hljs-operator">=</span> provider.getSigner(accounts[<span class="hljs-number">0</span>]);
    MoodContract <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ethers.Contract(
      MoodContractAddress,
      MoodContractABI,
      signer
    );
  });
});
</code></pre><p>Create asynchronous functions to call your smart contract functions</p>
<pre><code>async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMood</span>(<span class="hljs-params"></span>) </span>{
  const getMoodPromise <span class="hljs-operator">=</span> MoodContract.getMood();
  const Mood <span class="hljs-operator">=</span> await getMoodPromise;
  console.log(Mood);
}

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setMood</span>(<span class="hljs-params"></span>) </span>{
  const mood <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"mood"</span>).<span class="hljs-built_in">value</span>;
  const setMoodPromise <span class="hljs-operator">=</span> MoodContract.setMood(mood);
  await setMoodPromise;
}
</code></pre><h2 id="heading-test-your-work-out"><strong> Test Your Work Out!</strong></h2>
<ul>
<li>Got your webserver up? Go to http://127.0.0.1:3000 or http://localhost:3000/ in your browser to see your page!</li>
<li>Test your functions and approve the transactions as needed through Metamask. Note block times are ~15 seconds... so wait a bit to read the state of the blockchain</li>
<li>See your contract and transaction info via https://ropsten.etherscan.io/</li>
<li>Open a console (Ctrl + Shift + i) in the browser to see the magic happen as you press those buttons</li>
</ul>
<h2 id="heading-done"><strong>DONE!</strong></h2>
<p>Celebrate! You just made a webpage that interacted with a real live Ethereum testnet on the internet! That is not something many folks can say they have done!</p>
]]></content:encoded></item></channel></rss>